morelists 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
morelists/__init__.py CHANGED
@@ -1,9 +1,29 @@
1
1
  import time
2
+ import json
2
3
 
3
4
  class GameList():
4
- def __init__(self):
5
- self.list = {}
6
- self.flippedList = {}
5
+ def __init__(self, list = None, expirationList = None, flippedList = None, freeze = False, deltaTime = 0):
6
+ """
7
+ Creates a new GameList
8
+
9
+ Useful when you want to add, subtract, multiply, and divide items
10
+ inside a list to calculate strength of effect or other things.
11
+ Comes with a built-in expiration date for easy use.
12
+
13
+ Perfect for game engine with changing stats like adding buffs and debuffs.
14
+
15
+ Should not receive any arguments without experienced knowledge of the library.
16
+
17
+ Keyword arguments:
18
+ list -- the starting list (default None)
19
+ expirationList -- the starting list tracking expiration dates (default None)
20
+ flippedList -- inverted list, used for faster lookup (default None)
21
+ freeze -- preserve the list and stops the built-in expiration date deletor (default False)
22
+ deltaTime -- tells the list how much behind it is in time. Used in updateToPresent() (default 0)
23
+ """
24
+ self.list: dict = list if list != None else {}
25
+ self.expirationList: dict = expirationList if expirationList != None else {}
26
+ self.flippedList: dict = flippedList if flippedList != None else {}
7
27
 
8
28
  self.addValue = 0
9
29
  self.subtractValue = 0
@@ -11,12 +31,50 @@ class GameList():
11
31
  self.divideValue = 1
12
32
  self.sum = 0
13
33
 
34
+ self.freeze = freeze
35
+
36
+ self.history = [(0, {}, {}, {}, 0.0)]
37
+
38
+ self.deltaTime = deltaTime
39
+
40
+
41
+ def safeSum(self):
42
+ try:
43
+ return (self.addValue - self.subtractValue) * self.multiplyValue / self.divideValue
44
+ except ZeroDivisionError:
45
+ print("[WARNING]: GameList can't sum the list because of a ZeroDivisionError. Defaulted the sum value to be 0.")
46
+ return 0
47
+
48
+
14
49
  def add(self, item, expires = -1):
15
- expires += time.time()
50
+ """
51
+ Adds a item to the list.
52
+
53
+ Keyword arguments:
54
+ item -- item you wish to add. Format: {"name":"nameHere", "type":"add/subtract/multiply/divide", "value":float}
55
+ expires -- in seconds on how long until it expires and gets deleted. Set it to -1 to allow it to exist forever (default -1)
56
+ """
57
+ immortal = True if expires == -1 else False
58
+ perf_counter = time.time()
59
+ expires += perf_counter
16
60
  self.list[expires] = {"name":item.get("name", ""), "type":item.get("type", "add"), "value":item.get("value", 0)}
61
+
62
+
17
63
  if self.list[expires]["type"] not in ["add", "subtract", "multiply", "divide"]:
18
- self.list[expires]["type"] = "add"
19
- self.flippedList[str(self.list[expires])] = expires
64
+ print(f"[WARNING]: GameList only supports add/subtract/multiply/divide types. Your input type: {self.list[expires]["type"]}. Defaulting to add type.")
65
+ self.list[expires]["type"] = "add"
66
+
67
+ if not "value" in item:
68
+ defaultValue = 0 if self.list[expires]["type"] in ["add", "subtract"] else 1
69
+ self.list[expires]["value"] = defaultValue
70
+ print(f"[WARNING]: GameList uses the key 'value' to store the value of each item. You seem to have not given it a value. Defaulted to {defaultValue}.")
71
+
72
+ if self.list[expires]["name"] == "":
73
+ print(f'[WARNING]: GameList uses the key \'name\' to track items. You seem to have not given it a value. This will make it hard to track and pop at a later time (before its expiration date). Defaulted to "".')
74
+
75
+ if not immortal:
76
+ self.expirationList[expires] = self.list[expires]
77
+ self.flippedList[json.dumps(self.list[expires], sort_keys=True)] = expires
20
78
 
21
79
  if item["type"] == "add":
22
80
  self.addValue += item["value"]
@@ -25,12 +83,27 @@ class GameList():
25
83
  elif item["type"] == "multiply":
26
84
  self.multiplyValue += (item["value"] - 1)
27
85
  elif item["type"] == "divide":
28
- self.divideValue += (item["value"] - 1)
86
+ self.divideValue += (item["value"] - 1)
87
+
88
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
29
89
 
30
90
  def unsafeAdd(self, item, expires = -1):
31
- expiration = expires + time.time()
32
- self.list[expiration] = item
33
- self.flippedList[str(item)] = expiration
91
+ """
92
+ Adds a item to the list using a more unsafe method.
93
+
94
+ Only use this if you know what you are doing!
95
+
96
+ Keyword arguments:
97
+ item -- item you wish to add. Format: {"name":"nameHere", "type":"add/subtract/multiply/divide", "value":float}
98
+ expires -- in seconds on how long until it expires and gets deleted. Set it to -1 to allow it to exist forever (default -1)
99
+ """
100
+ immortal = True if expires == -1 else False
101
+ perf_counter = time.time()
102
+ expires += perf_counter
103
+ self.list[expires] = item
104
+ if not immortal:
105
+ self.expirationList[expires] = self.list[expires]
106
+ self.flippedList[json.dumps(item, sort_keys=True)] = expires
34
107
 
35
108
  if item["type"] == "add":
36
109
  self.addValue += item["value"]
@@ -41,10 +114,44 @@ class GameList():
41
114
  elif item["type"] == "divide":
42
115
  self.divideValue += (item["value"] - 1)
43
116
 
117
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
118
+
119
+
120
+ def calculateSumWithoutUpdate(self):
121
+ """
122
+ Calculates the sum of the list without checking for expired items
123
+
124
+ Use only if you want to access the sum without updating
125
+ """
126
+ self.addValue = 0
127
+ self.subtractValue = 0
128
+ self.multiplyValue = 1
129
+ self.divideValue = 1
130
+ for item in self.list.values():
131
+ if item["type"] == "add":
132
+ self.addValue += item["value"]
133
+ elif item["type"] == "subtract":
134
+ self.subtractValue += item["value"]
135
+ elif item["type"] == "multiply":
136
+ self.multiplyValue += (item["value"] - 1)
137
+ elif item["type"] == "divide":
138
+ self.divideValue += (item["value"] - 1)
139
+
140
+ return self.safeSum()
141
+
142
+
44
143
 
45
144
  def update(self):
145
+ """
146
+ Updates the list and removes any expires items.
147
+
148
+ This is already called upon when accessing the sum or history.
149
+ This function doesn't need to be by the user.
150
+ """
151
+
152
+ # update() ignore the reeze flag because it's assumed the user is calling it with the purpose of updating it manually
46
153
  try:
47
- expiration = min(self.list.keys())
154
+ expiration = min(self.expirationList.keys())
48
155
  while expiration < time.time():
49
156
  if self.list[expiration]["type"] == "add":
50
157
  self.addValue -= self.list[expiration]["value"]
@@ -54,36 +161,181 @@ class GameList():
54
161
  self.multiplyValue -= (self.list[expiration]["value"] - 1)
55
162
  else:
56
163
  self.divideValue -= (self.list[expiration]["value"] - 1)
164
+
165
+ del self.flippedList[json.dumps(self.list[expiration], sort_keys=True)]
57
166
  del self.list[expiration]
58
167
 
59
- expiration = min(self.list.keys())
60
- except ValueError:
61
- pass
168
+ object.__getattribute__(self, "history").append((expiration, self.list, self.expirationList, self.flippedList, self.safeSum()))
169
+ expiration = min(self.expirationList.keys())
170
+ except ValueError as e:
171
+ print(f"[WARNING]: While updating the list, a new error appeared: {e}")
172
+
173
+ def pause(self):
174
+ """
175
+ Prevents the list from auto-updating and prevents deletions of expired items without user input.
176
+ """
177
+ self.freeze = True
178
+
179
+ def resume(self):
180
+ """
181
+ Resumes the list to auto-update and delete expired items automatically.
182
+ """
183
+ self.freeze = False
184
+
185
+ def updateToPresent(self):
186
+ """
187
+ Updates each item in the list to match if the list was in the present. Setting deltaTime changes how much this affects the list.
188
+
189
+ Only use this if you are experienced and know what you are doing.
190
+ """
191
+ newList = {}
192
+ for key, value in self.list.items():
193
+ newList[key + self.deltaTime] = value
194
+ self.deltaTime = 0
195
+
196
+ def restoreState(self, t) -> "GameList":
197
+ """
198
+ Creates a new GameList from the history of the list. Useful if you want to track previous sum values and such.
199
+
200
+ Keyword arguments:
201
+ t -- the time you want the new list to be based on
202
+ """
203
+ self.update()
204
+ lastItem = None
205
+ for item in self.history:
206
+ if item[0] < t:
207
+ lastItem = item
208
+ else:
209
+ break
210
+
211
+ if lastItem == None:
212
+ return GameList()
213
+ else:
214
+ return GameList(lastItem[1], lastItem[2], False, time.time() - lastItem[0])
215
+
216
+ def getOldSums(self, t0, t1) -> list[tuple]:
217
+ """
218
+ Creates a list of tuples with the sum value from t0 -> t1.
219
+
220
+ Format: [(time, sum_value), ...]
221
+
222
+ Keyword arguments:
223
+ t0 -- the time you want the list to start
224
+ t1 -- the time you want the list to end
225
+ """
226
+ self.update()
227
+ items = []
228
+ for item in self.history:
229
+ if item[0] < t0:
230
+ items = [(item[0], item[4])]
231
+ elif item[0] < t1:
232
+ items.append((item[0], item[4]))
233
+ else:
234
+ break
235
+
236
+ return items
237
+
62
238
 
63
239
  def pop(self, name):
64
- pops = [value for value in self.list.values() if value["name"] == name]
65
- pops.sort(key=lambda a: a["expires"])
240
+ """
241
+ Pops a item from the list with the closest expiration date to the current time
242
+
243
+ Keyword arguments:
244
+ name -- the name you gave the item in the list
245
+ """
246
+ perf_counter = time.time()
247
+ pops = [(key, value) for key, value in self.list.items() if value["name"] == name]
248
+ pops.sort(key=lambda a: a[0])
66
249
  if pops:
67
- del self.list[self.flippedList[str(pops[0])]]
68
- del self.flippedList[str(pops[0])]
250
+ stringedList = json.dumps(pops[0][1], sort_keys=True)
251
+
252
+ item = self.list[self.flippedList[stringedList]]
253
+ del self.list[self.flippedList[stringedList]]
254
+ if self.flippedList[stringedList] in self.expirationList: del self.expirationList[self.flippedList[stringedList]]
255
+ del self.flippedList[stringedList]
256
+
257
+ if item["type"] == "add":
258
+ self.addValue -= item["value"]
259
+ elif item["type"] == "subtract":
260
+ self.subtractValue -= item["value"]
261
+ elif item["type"] == "multiply":
262
+ self.multiplyValue -= (item["value"] - 1)
263
+ else:
264
+ self.divideValue -= (item["value"] - 1)
265
+
266
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
69
267
 
70
268
  def popAny(self, name):
269
+ """
270
+ Pops a item from the list with no regards for expiration date
271
+
272
+ Keyword arguments:
273
+ name -- the name you gave the item in the list
274
+ """
275
+ perf_counter = time.time()
71
276
  pops = [value for value in self.list.values() if value["name"] == name]
72
277
  if pops:
73
- del self.list[self.flippedList[str(pops[0])]]
74
- del self.flippedList[str(pops[0])]
278
+ stringedList = json.dumps(pops[0], sort_keys=True)
279
+
280
+ item = self.list[self.flippedList[stringedList]]
281
+ del self.list[self.flippedList[stringedList]]
282
+ if self.flippedList[stringedList] in self.expirationList: del self.expirationList[self.flippedList[stringedList]]
283
+ del self.flippedList[stringedList]
284
+
285
+ if item["type"] == "add":
286
+ self.addValue -= item["value"]
287
+ elif item["type"] == "subtract":
288
+ self.subtractValue -= item["value"]
289
+ elif item["type"] == "multiply":
290
+ self.multiplyValue -= (item["value"] - 1)
291
+ else:
292
+ self.divideValue -= (item["value"] - 1)
293
+
294
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
75
295
 
76
296
  def popAll(self, name):
297
+ """
298
+ Pops every item from the list with the given name
299
+
300
+ Keyword arguments:
301
+ name -- the name you gave the item(s) in the list
302
+ """
303
+ perf_counter = time.time()
77
304
  pops = [value for value in self.list.values() if value["name"] == name]
78
305
  if pops:
79
306
  for x in range(len(pops)):
80
- del self.list[self.flippedList[str(pops[x])]]
81
- del self.flippedList[str(pops[x])]
307
+ stringedList = json.dumps(pops[x], sort_keys=True)
308
+
309
+
310
+ item = self.list[self.flippedList[stringedList]]
311
+ del self.list[self.flippedList[stringedList]]
312
+ if self.flippedList[stringedList] in self.expirationList: del self.expirationList[self.flippedList[stringedList]]
313
+ del self.flippedList[stringedList]
314
+
315
+ if item["type"] == "add":
316
+ self.addValue -= item["value"]
317
+ elif item["type"] == "subtract":
318
+ self.subtractValue -= item["value"]
319
+ elif item["type"] == "multiply":
320
+ self.multiplyValue -= (item["value"] - 1)
321
+ else:
322
+ self.divideValue -= (item["value"] - 1)
323
+
324
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
82
325
 
83
326
  def remove(self, item):
84
- if self.flippedList.get(str(item), None):
85
- del self.list[self.flippedList[str(item)]]
86
- del self.flippedList[str(item)]
327
+ """
328
+ Removes a specific item from the list (if it exists)
329
+
330
+ Keyword arguments:
331
+ name -- the name you gave the item(s) in the list
332
+ """
333
+ perf_counter = time.time()
334
+ stringedList = json.dumps(item, sort_keys=True)
335
+ if self.flippedList.get(stringedList, None):
336
+ del self.list[self.flippedList[stringedList]]
337
+ if self.flippedList[stringedList] in self.expirationList: del self.expirationList[self.flippedList[stringedList]]
338
+ del self.flippedList[stringedList]
87
339
 
88
340
  if item["type"] == "add":
89
341
  self.addValue -= item["value"]
@@ -94,10 +346,23 @@ class GameList():
94
346
  else:
95
347
  self.divideValue -= (item["value"] - 1)
96
348
 
349
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
350
+
97
351
  def unsafeRemove(self, item):
352
+ """
353
+ Removes a specific item from the list (if it exists)
354
+
355
+ More unsafe compared to remove(item), so use only if you know what you are doing!
356
+
357
+ Keyword arguments:
358
+ name -- the name you gave the item(s) in the list
359
+ """
360
+ perf_counter = time.time()
98
361
  if item in self.list.values():
99
- del self.list[dict(self.flippedList[str(item)])]
100
- del self.flippedList[str(item)]
362
+ stringedList = json.dumps(item, sort_keys=True)
363
+ del self.list[dict(self.flippedList[stringedList])]
364
+ if dict(self.flippedList[stringedList]) in self.expirationList: del self.expirationList[dict(self.flippedList[stringedList])]
365
+ del self.flippedList[stringedList]
101
366
 
102
367
  if item["type"] == "add":
103
368
  self.addValue -= item["value"]
@@ -108,18 +373,31 @@ class GameList():
108
373
  else:
109
374
  self.divideValue -= (item["value"] - 1)
110
375
 
376
+ object.__getattribute__(self, "history").append((perf_counter, self.list, self.expirationList, self.flippedList, self.safeSum()))
377
+
111
378
  def __getattribute__(self, name):
379
+ """
380
+ Retrieves attributes from the class
381
+
382
+ Updates the list if you grab the sum value or the history data
383
+
384
+ Keyword arguments:
385
+ name -- the name of the attribute you want to grab
386
+ """
112
387
  if name == "sum":
113
- self.update()
388
+ if not object.__getattribute__(self, "freeze"):
389
+ self.update()
114
390
  return (object.__getattribute__(self, "addValue") -
115
391
  object.__getattribute__(self, "subtractValue")) * \
116
392
  object.__getattribute__(self, "multiplyValue") / \
117
393
  object.__getattribute__(self, "divideValue")
118
- return object.__getattribute__(self, name)
119
-
120
-
394
+ elif name == "history":
395
+ if not object.__getattribute__(self, "freeze"):
396
+ self.update()
121
397
 
122
398
 
399
+ return object.__getattribute__(self, name)
400
+
123
401
 
124
402
 
125
403
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: morelists
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A small and easy list you can add together like a math equation and has a expiration date for items. Mostly useful for games with stats from multiple sources. More lists will come soon.
5
5
  Home-page: https://github.com/EmanuelNorsk/enlist
6
6
  Author: Emanuel Odén Hesselroth
@@ -13,3 +13,4 @@ Requires-Python: >=3.6
13
13
  License-File: LICENSE
14
14
  Dynamic: author
15
15
  Dynamic: home-page
16
+ Dynamic: license-file
@@ -0,0 +1,6 @@
1
+ morelists/__init__.py,sha256=b46BNQD_evFdrX8YU5ignMxU6ZBDIpEx0KbXoQCY8PI,16729
2
+ morelists-0.1.2.dist-info/licenses/LICENSE,sha256=-ASFHlrne1rk8zV57Qj01X2JB-D67ZHPMv1PtQhrbN8,32
3
+ morelists-0.1.2.dist-info/METADATA,sha256=JtoS_qxKDCJ8q_r3ootsTvDI_1E38VcM7jx4dVHaMvk,681
4
+ morelists-0.1.2.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
5
+ morelists-0.1.2.dist-info/top_level.txt,sha256=Zd7NosYzor-RcH_aD86FXJa3fQzWunYA4_FQS3Yodqo,10
6
+ morelists-0.1.2.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.8.0)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,6 +0,0 @@
1
- morelists/__init__.py,sha256=MCofk70SKqV9lkk01iBpyYAIFl29vB09RXX4WnOM0UA,4718
2
- morelists-0.1.0.dist-info/LICENSE,sha256=-ASFHlrne1rk8zV57Qj01X2JB-D67ZHPMv1PtQhrbN8,32
3
- morelists-0.1.0.dist-info/METADATA,sha256=jq8smAfeCnSeI0uDBOOBJt-44Xa4oI-AY2GWO-H517Q,658
4
- morelists-0.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
5
- morelists-0.1.0.dist-info/top_level.txt,sha256=Zd7NosYzor-RcH_aD86FXJa3fQzWunYA4_FQS3Yodqo,10
6
- morelists-0.1.0.dist-info/RECORD,,