-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathggj.py
220 lines (167 loc) · 5.99 KB
/
ggj.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
#!/usr/bin/env python
#coding: utf-8
import picsgetter
import classifier
from collections import OrderedDict
try:
import cPickle as cpickle
except:
import cpickle
# Instantiating our skills classifier, born
# at Pilsner and Programming in Bergen #3 2016.
c = classifier.SkillzClassifier()
class JamSite():
def __init__(self):
self.jammers = OrderedDict()
# computer says no, human says yes.
# This is a list of human made overriding changes
# per jammer. It will be applied last in the
# import cascade, and thus have the highest priority.
self.administrated_jammers = OrderedDict()
def mergeinsert(self, other_list_of_jammers, accumulate=True):
""" Merging a the jamsites jammers with additional / overlapping jammer info """
for jammer in other_list_of_jammers:
if jammer in self.jammers:
# overwriting new data
self.jammers[jammer.username].update(jammer)
else:
self.jammers[jammer.username] = jammer
if accumulate:
# Learn some more about this jammer now with this
# new knowledge
self.jammers[jammer.username].accumulate()
def apply_human(self):
""" Last step is to overwrite with human changes """
self.apply_human_decissions(self.administrated_jammers.values())
def apply_human_decissions(self, list_of_jammers):
self.mergeinsert(list_of_jammers, accumulate=False)
def jammers_sorted_by_main_role(self, with_ticket=True):
""" Returns a list of jammers sorted by their classified main role.
so that the cards can be printed color by color. """
jammers = []
pool = self.jammers_with_ticket if with_ticket else self.jammers.values()
for main_role in classifier.groups:
jammers += self.jammers_with_main_role(main_role, pool)
jammers += self.jammers_with_main_role("unclassified", pool)
return jammers
def jammers_with_main_role(self, main_role, jammers=None):
""" returns jammers with selected main_role """
if jammers is None:
jammers = self.jammers.values()
return [j for j in jammers if j.main_role==main_role]
def jammer_distribution(self):
""" Returns some statistics about the distribution of jammer roles """
distribution = {}
for role in classifier.groups:
distribution[role] = len(self.jammers_with_main_role(role, self.jammers_with_ticket))
role = 'unclassified'
distribution[role] = len(self.jammers_with_main_role(role, self.jammers_with_ticket))
distribution["total"] = sum(distribution.values())
return distribution
def waiting_list(self):
""" Goes over all jammers, and returns those without a ticket """
wait_list = []
for jammer in self.jammers.values():
if not jammer.has_ticket:
wait_list.append(jammer)
return wait_list
@property
def jammers_with_ticket(self):
return [j for j in self.jammers.values() if j.has_ticket]
def save(self, filename="jamsite.pickle"):
""" sideeffects """
with open(filename, "wb") as statefile:
cpickle.dump(self, statefile)
def serialize(self):
"""used to store state """
return cpickle.dumps(self)
@staticmethod
def load(filename="jamsite.pickle"):
""" sideeffects """
try:
with open(filename, "rb") as statefile:
jamsite = cpickle.load(statefile)
except:
jamsite = JamSite()
return jamsite
def reset(self, all=False):
""" Empties the jammer list, but keeps the human made changes """
self.jammers = OrderedDict()
if all:
self.administrated_jammers = OrderedDict()
return self
class Jammer():
__docstring__ = """ Jammer class, must have Username as a minimum. """
def __init__(self, **kwargs):
""" populates itself from kwargs """
#self.Experience = ""
#self.Size = "?"
if 'Username' not in kwargs:
print("Missing Username field")
raise Exception
for key in kwargs:
value = kwargs[key]
setattr(self, key, value)
@property
def username(self):
""" Property and static hack to just keep it procedural. why not."""
return Jammer.format_username(self.Username)
@property
def has_ticket(self):
return hasattr(self, "ticket") and self.ticket == True
def update(self, updated_jammer):
"""
When agregating data from multiple sources, this
algorithm goes through the new data, adds fields not found
and overwrites old fields with the new version
"""
# Step 1, add or overwrite with updated data
for key in updated_jammer.__dict__:
self.__dict__[key] = updated_jammer.__dict__[key]
return self
@staticmethod
def format_username(Username):
"""
1. FB-registered users has a little twitchy nicky thingy
basically Name Surname => name-surname
2. all usernames are lowercased in the url
3. _ is allowed but stripped from the username in the url.
4. sometimes there are leading / trailing spaces in input. feush
"""
return Username.strip().lower().replace("_", "").replace(" ", "-")
def accumulate(self):
"""
Get more data from the data about this jammer.
"""
# Classify skills.
self.classifications = c.classify(self.Skills)
self.main_role = c.main_role(self.Skills)
self.skills_and_labels = c.label_skillset(self.Skills)
# Profile picture
self.picture = picsgetter.find_or_create_picture(self.__dict__)
return self
def __repr__(self):
return self.username
def __hash__(self):
""" Used for comparison with other jammers. normalized username is the hash. """
return hash(self.username)
def __getitem__(self, key):
""" Use the jammer as a dict :) """
return getattr(self, key)
def __eq__(self, other):
""" hmmm. using hash or not. that is the question """
try:
return self.username == other.username
except:
# explanation. it compares itself with a string username.
# return self.username == other
# hack to make it possible to compare keys in a dict of jammers
# with a jammer object.
return self.username == other
if __name__ == '__main__':
j = Jammer(Username="Technocake")
print(j.Username, j.username)
j.update(Jammer(Username='Technocake', Skills="music, programming, music"))
jamsite = JamSite.load()
print (jamsite.jammers_sorted_by_main_role(with_ticket=True))
print (jamsite.jammer_distribution())