Skip to content

Instantly share code, notes, and snippets.

@mousetail
Created December 25, 2020 15:55
Show Gist options
  • Save mousetail/7947d60ad75af60facb5241d2a2e88cd to your computer and use it in GitHub Desktop.
Save mousetail/7947d60ad75af60facb5241d2a2e88cd to your computer and use it in GitHub Desktop.
class Multiset():
def __init__(self, name):
self.name = name
self.fixed_items = {}
self.nrof_items = 0
def add(self, item):
self.fixed_items[item] = self.fixed_items.get(item, 0)+1
self.nrof_items+=1
def remove(self, item):
if self.fixed_items.get(item, 0) > 0:
self.fixed_items[item] -= 1
self.nrof_items-=1
return True
return False
#def transfer(self, other):
# pass
class SetSystem():
def __init__(self, set_names=[]):
self.sets = {name: Multiset(name) for name in set_names}
self.variables = {}
self.variable_numbers = {}
self.logfile = open("setsystem_log.py", "w")
def add(self, name, value):
self.logfile.write(f"t.add({repr(name)}, {repr(value)})\n")
if name not in self.sets:
self.sets[name] = Multiset(name)
self.sets[name].add(value)
#if not value in variables:
# variables[value]=[]
#variables[value].append(name)
def remove(self, group, resource):
self.logfile.write(f"t.remove({repr(group)}, {repr(resource)})\n")
if not self.sets[group].remove(resource):
self.sets[group].nrof_items-=1
if group in self.variables[resource]:
#print("number in vnums", self.variable_numbers[resource], "in res", self.variables[resource][group])
self.variable_numbers[resource]-=1
if (self.variable_numbers[resource]<0):
print("Huge problem: ",self.variable_numbers[resource],"floating variables")
self.logfile.write(f"# error with negative floating variables, variable: {resource} amount: {self.variable_numbers[resource]}\n")
self.variables[resource][group]-=1
if self.variables[resource][group]==0:
del self.variables[resource][group]
else:
raise ValueError("trying to remove a item from a set that can't possibly contain it")
self.consolidate()
def transfer(self, name1, name2):
self.logfile.write(f"t.transfer({repr(name1)}, {repr(name2)})\n")
if name2 not in self.sets:
self.sets[name2]=Multiset(name2)
possible_values = set()
for key, value in self.sets[name1].fixed_items.items():
if value!=0:
self.sets[name1].fixed_items[key]-=1
self.variable_numbers[key]=self.variable_numbers.get(value, 0)+1
possible_values.add(key)
for resource, value_map in self.variables.items():
if value_map.get(name1,0)>0:
self.variables[resource][name2]=self.variables[resource].get(name2,0)+1
self.sets[name1].nrof_items-=1
self.sets[name2].nrof_items+=1
for value in possible_values:
if value not in self.variables:
self.variables[value]={}
if name1 not in self.variables[value]:
self.variables[value][name1]=0
if name2 not in self.variables[value]:
self.variables[value][name2]=0
self.variables[value][name2]+=1
self.variables[value][name1]+=1
self.consolidate()
#for
def consolidate(self):
#print()
#self.print_system()
self.consolidate_setwise()
#print()
#self.print_system()
#self.consolidate_itemwise()
print()
self.logfile.flush()
def consolidate_itemwise(self):
for resource, amount in self.variable_numbers.items():
t = self.variables[resource]
total_slots = sum(value for value in t.values())
holes = total_slots - amount
#print(self.variables[resource])
#print("resource", resource, "holes", holes, "total_slots", total_slots, "amount", amount)
for group, max_amount in t.items():
if max_amount>holes:
diff = max_amount-holes
#print("diff: ", diff)
self.sets[group].fixed_items[resource]=self.sets[group].fixed_items.get(resource, 0)+diff
self.variables[resource][group]-=diff
self.variable_numbers[resource]-=diff
if (self.variable_numbers[resource]<0):
print("Huge problem: ",self.variable_numbers[resource],"floating variables")
self.logfile.write(f"# error with negative floating variables, variable: {resource} amount: {self.variable_numbers[resource]}\n")
def consolidate_setwise(self):
for key, s in self.sets.items():
guarenteed_length = sum(i[1] for i in s.fixed_items.items())
delta_length = s.nrof_items - guarenteed_length
optional_length = sum(var[key] for val, var in self.variables.items() if var.get(key,0)>0)
#print(key, optional_length, delta_length)
if delta_length < 0:
print("things are even more broken")
self.logfile.write(f"#broken from here (delta_length={delta_length} key={key})\n")
self.broken = True
if delta_length > optional_length:
print("Everything is broken: ", delta_length, optional_length)
print()
print()
return
if delta_length == optional_length and delta_length!=0:
dt = [(val, var[key]) for val, var in self.variables.items() if var[key]>0]
for val, amount in dt:
self.sets[key].fixed_items[val]=self.sets[key].fixed_items.get(val, 0)+amount
self.variables[val][key]-=amount
self.variable_numbers[val]-=amount
elif optional_length>0:
for resource, amount_map in self.variables.items():
if amount_map.get(key,0)>0:
self.variables[resource][key]=min(self.variables[resource][key], delta_length, self.variable_numbers[resource])
def print_system(self):
for key, s in self.sets.items():
print(str(key) + " #"+str(s.nrof_items)+"")
print("\t"+"\t".join(str(num)+":"+str(value) for num, value in s.fixed_items.items() if value!=0))
length = sum(i[1] for i in s.fixed_items.items())
if length<s.nrof_items:
print("\t+",s.nrof_items - length,"of"," or ".join(str(var) for var, val in self.variables.items() if val.get(key, 0)>0))
print("total loose variables: ", ",".join(f"{key}:{value}" for key, value in self.variable_numbers.items()))
#for variable
if __name__=="__main__":
t = SetSystem()
CASE = 6
if CASE==1:
t.add('red', 'wheat')
t.add('red', 'sheap')
t.add('red', 'sheap')
#t.print_system()
t.transfer('red','green')
t.remove('green', 'wheat')
elif CASE==2:
t.add('red', 'wheat')
t.add('red', 'sheap')
t.transfer('red', 'green')
t.transfer('red', 'blue')
t.remove('blue', 'sheap')
elif CASE==3:
for i in range(5):
t.add('red', 'wheat')
t.add('red', 'brick')
t.add('green', 'wheat')
t.transfer('red', 'green')
t.remove('green', 'wheat')
t.transfer('green', 'blue')
elif CASE==4:
t.add('red', 'sheep')
for i in range(10):
t.add('red', 'brick')
t.add('green', 'brick')
t.add('blue', 'brick')
t.transfer('red', 'green')
t.transfer('green', 'blue')
for i in range(9):
t.remove('red', 'brick')
t.remove('green', 'brick')
t.remove('blue', 'brick')
elif CASE==5:
t.add(5, 4)
t.add(5, 3)
t.add(1, 4)
t.add(1, 1)
t.add(1, 4)
t.add(2, 5)
t.add(2, 4)
t.add(2, 5)
t.add(3, 1)
t.add(3, 2)
t.add(3, 2)
t.add(1, 2)
t.add(3, 3)
t.add(2, 3)
t.remove(3, 1)
t.remove(3, 2)
t.add(2, 5)
t.add(2, 3)
t.add(5, 3)
t.remove(1, 1)
t.remove(1, 2)
t.add(5, 3)
t.remove(3, 3)
t.add(2, 3)
t.remove(5, 3)
t.remove(2, 3)
t.remove(2, 4)
t.remove(2, 5)
t.add(1, 2)
t.add(3, 3)
t.add(2, 3)
t.add(1, 2)
t.add(3, 3)
t.add(2, 3)
t.transfer(1, 2)
t.add(5, 3)
t.add(1, 1)
t.add(3, 1)
t.add(2, 4)
t.add(2, 5)
t.add(1, 5)
t.add(2, 4)
t.remove(1, 4)
t.add(1, 3)
t.remove(2, 3)
t.remove(1, 1)
t.remove(1, 2)
t.remove(1, 3)
t.remove(1, 4)
t.add(5, 1)
t.add(5, 1)
t.remove(2, 4)
t.remove(2, 4)
t.remove(2, 5)
t.remove(2, 5)
t.remove(2, 5)
t.add(2, 4)
t.add(1, 4)
t.add(2, 4)
t.add(2, 4)
t.add(1, 5)
t.add(2, 5)
t.add(1, 5)
t.add(3, 5)
t.remove(1, 5)
t.add(1, 3)
t.remove(3, 3)
t.remove(2, 3)
t.remove(2, 3)
t.remove(2, 4)
t.remove(2, 5)
t.add(5, 1)
t.remove(3, 1)
t.add(2, 1)
t.add(2, 1)
t.remove(5, 1)
t.remove(5, 1)
t.add(5, 2)
t.remove(2, 2)
t.remove(5, 1)
t.remove(5, 2)
t.add(5, 4)
t.add(3, 4)
t.add(3, 2)
t.add(5, 2)
t.add(3, 1)
t.remove(2, 1)
t.add(2, 2)
t.remove(3, 2)
t.remove(2, 1)
t.remove(2, 2)
t.add(1, 2)
t.add(3, 3)
t.add(2, 3)
t.add(2, 3)
t.remove(3, 1)
t.remove(3, 2)
t.remove(3, 3)
t.remove(3, 4)
t.transfer(2, 1)
t.add(1, 2)
t.remove(5, 4)
t.remove(5, 4)
t.add(5, 1)
t.remove(5, 1)
t.remove(5, 2)
t.add(2, 5)
t.add(2, 3)
t.add(2, 3)
t.add(5, 3)
t.remove(1, 3)
t.remove(1, 4)
t.remove(1, 5)
t.add(2, 4)
t.add(1, 4)
t.remove(2, 3)
t.remove(2, 4)
t.remove(2, 5)
t.add(5, 3)
t.add(1, 1)
t.add(3, 1)
t.add(2, 4)
t.add(1, 4)
t.remove(1, 1)
t.remove(1, 2)
t.add(5, 2)
t.remove(1, 2)
t.add(1, 3)
t.remove(5, 3)
t.add(5, 3)
t.add(1, 1)
t.add(3, 1)
t.add(1, 3)
t.remove(5, 3)
t.add(5, 4)
t.remove(1, 4)
t.add(1, 3)
t.add(1, 3)
t.remove(5, 3)
t.remove(5, 3)
t.add(5, 1)
t.remove(1, 1)
t.remove(5, 1)
t.remove(5, 2)
t.remove(5, 3)
t.remove(5, 4)
t.add(1, 4)
t.add(3, 2)
t.add(2, 1)
t.add(2, 2)
t.remove(2, 1)
t.remove(2, 2)
t.remove(2, 3)
t.remove(2, 4)
t.add(1, 2)
t.remove(3, 1)
t.remove(3, 2)
t.add(1, 2)
t.remove(1, 3)
t.remove(1, 4)
t.remove(1, 5)
t.remove(1, 3)
t.remove(1, 3)
t.remove(1, 3)
t.add(1, 1)
t.remove(1, 1)
t.remove(1, 2)
t.add(5, 1)
t.add(1, 1)
t.add(3, 1)
#t.transfer(1, 2)
#t.transfer(2, 3)
#t.transfer(2, 1)
#t.add(1, 2)
#t.transfer(1, 2)
#t.add(3, 2)
#t.remove(2, 2)
#t.add(2, 5)
#t.remove(3, 5)
#t.add(1, 2)
#t.add(3, 3)
#t.add(2, 3)
#t.add(2, 3)
#t.remove(3, 1)
#t.remove(3, 2)
#t.add(3, 5)
#t.remove(1, 1)
elif CASE==6:
t.add(1,4)
t.add(1,3)
t.transfer(1,2)
#t.add(5,1)
#t.add(5,3)
t.add(1, 4)
t.add(1, 1)
t.add(1, 2)
t.add(2, 4)
t.add(2, 3)
t.add(2, 3)
#t.add(3, 1)
#t.add(3, 1)
#t.add(3, 3)
#t.add(3, 5)
print("final transfer")
t.print_system()
t.transfer(1,2)
#t.transfer('red','green')
t.print_system()
t.logfile.close()
@fdharamshi
Copy link

Would you be able to share the greasemonkey script and the python code for the server as well?
I have a different approach to this and want to give it a shot!

@mousetail
Copy link
Author

@fdharamshi I purposefully didn't want to share the code that actually let you cheat. It also wouldn't work anymore because Colonist has updated a lot since. However, it should be fairly easy to rebuild. Basically it just assigned a wrapper around the WebSocket class so that it would also forward all messages to the flask server. Some basic trial and error should allow you to figure out what the messages mean.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment