albibong 1.0.7__py3-none-any.whl → 1.1.1__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.
Files changed (43) hide show
  1. albibong/__init__.py +92 -8
  2. albibong/__main__.py +6 -0
  3. albibong/classes/character.py +7 -23
  4. albibong/classes/dungeon.py +53 -32
  5. albibong/classes/event_handler/__init__.py +17 -1
  6. albibong/classes/event_handler/handle_event_character_equipment_changed.py +2 -10
  7. albibong/classes/event_handler/handle_event_might_and_favor_received_event.py +18 -0
  8. albibong/classes/event_handler/handle_event_other_grabbed_loot.py +9 -0
  9. albibong/classes/event_handler/handle_event_party.py +6 -13
  10. albibong/classes/event_handler/handle_event_update_fame.py +9 -0
  11. albibong/classes/event_handler/handle_event_update_re_spec_points.py +9 -0
  12. albibong/classes/event_handler/handle_operation_change_cluster.py +17 -22
  13. albibong/classes/event_handler/handle_operation_farmable_harvest.py +17 -0
  14. albibong/classes/event_handler/handle_operation_join.py +14 -36
  15. albibong/classes/event_handler/world_data_utils.py +62 -30
  16. albibong/classes/item.py +19 -4
  17. albibong/classes/location.py +136 -5
  18. albibong/classes/utils.py +20 -0
  19. albibong/gui_dist/assets/index-B31tZ4Ku.css +1 -0
  20. albibong/gui_dist/assets/index-BkyL_QUY.js +168 -0
  21. albibong/gui_dist/favor.png +0 -0
  22. albibong/gui_dist/index.html +2 -2
  23. albibong/gui_dist/might.png +0 -0
  24. albibong/migrations/001_init.py +97 -0
  25. albibong/migrations/002_alter_dungeon_table.py +53 -0
  26. albibong/models/__init__.py +0 -0
  27. albibong/models/models.py +12 -0
  28. albibong/requirements.txt +2 -0
  29. albibong/resources/items_by_unique_name.json +55282 -0
  30. albibong/resources/maps.json +259 -259
  31. albibong/threads/http_server.py +4 -0
  32. albibong/threads/sniffer_thread.py +39 -2
  33. albibong/threads/websocket_server.py +80 -43
  34. {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/METADATA +3 -1
  35. {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/RECORD +39 -32
  36. albibong/gui_dist/assets/index-DZvgNqlG.css +0 -1
  37. albibong/gui_dist/assets/index-Dt6hyZiS.css +0 -1
  38. albibong/gui_dist/assets/index-E7pha23k.js +0 -161
  39. albibong/gui_dist/assets/index-WIuC9Mnh.js +0 -161
  40. /albibong/resources/{items.json → items_by_id.json} +0 -0
  41. {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/WHEEL +0 -0
  42. {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/entry_points.txt +0 -0
  43. {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,4 +1,3 @@
1
- from albibong.classes.dungeon import Dungeon
2
1
  from albibong.classes.event_handler.world_data_utils import WorldDataUtils
3
2
  from albibong.classes.location import Location
4
3
  from albibong.classes.utils import Utils
@@ -7,20 +6,20 @@ from albibong.threads.websocket_server import send_event
7
6
 
8
7
 
9
8
  def handle_operation_join(world_data: WorldData, parameters):
10
- # update relative id if character has initialized before
11
- if world_data.me.username != "not initialized":
12
- WorldDataUtils.convert_id_to_name(
13
- world_data,
14
- old_id=world_data.me.id,
15
- new_id=parameters[0],
16
- char=world_data.me,
17
- )
18
-
19
9
  # set my character
20
- world_data.me.uuid = Utils.convert_int_arr_to_uuid(parameters[1])
21
10
  world_data.me.username = parameters[2]
11
+ world_data.me.uuid = Utils.convert_int_arr_to_uuid(parameters[1])
22
12
  world_data.me.guild = parameters[57] if 57 in parameters else ""
23
13
  world_data.me.alliance = parameters[77] if 77 in parameters else ""
14
+
15
+ # update relative id if character has initialized before
16
+ WorldDataUtils.convert_id_to_name(
17
+ world_data,
18
+ old_id=world_data.me.id,
19
+ new_id=parameters[0],
20
+ char=world_data.me,
21
+ )
22
+
24
23
  if world_data.me.id in world_data.change_equipment_log:
25
24
  world_data.me.update_equipment(
26
25
  world_data.change_equipment_log[world_data.me.id]
@@ -43,8 +42,8 @@ def handle_operation_join(world_data: WorldData, parameters):
43
42
  )
44
43
 
45
44
  ws_init_character(world_data)
46
- ws_update_location(world_data)
47
- ws_update_dps(world_data)
45
+ WorldDataUtils.ws_update_location(world_data)
46
+ WorldDataUtils.ws_update_damage_meter(world_data)
48
47
 
49
48
 
50
49
  def ws_init_character(world_data: WorldData):
@@ -55,30 +54,9 @@ def ws_init_character(world_data: WorldData):
55
54
  "fame": world_data.me.fame_gained,
56
55
  "re_spec": world_data.me.re_spec_gained,
57
56
  "silver": world_data.me.silver_gained,
57
+ "might": world_data.me.might_gained,
58
+ "favor": world_data.me.favor_gained,
58
59
  "weapon": world_data.me.equipment[0].image,
59
60
  },
60
61
  }
61
62
  send_event(event)
62
-
63
-
64
- def ws_update_location(world_data: WorldData):
65
- event = {
66
- "type": "update_location",
67
- "payload": {
68
- "map": world_data.current_map.name if world_data.current_map else "None",
69
- "dungeon": (
70
- Dungeon.serialize(world_data.current_dungeon)
71
- if world_data.current_dungeon
72
- else None
73
- ),
74
- },
75
- }
76
- send_event(event)
77
-
78
-
79
- def ws_update_dps(world_data: WorldData):
80
- event = {
81
- "type": "update_dps",
82
- "payload": {"party_members": world_data.serialize_party_members()},
83
- }
84
- send_event(event)
@@ -1,38 +1,54 @@
1
- from collections import deque
2
- import json
3
- import os
4
-
5
1
  from albibong.classes.character import Character
6
2
  from albibong.classes.dungeon import Dungeon
7
- from albibong.classes.location import Location
8
- from albibong.classes.utils import Utils
3
+ from albibong.classes.location import Island, Location
9
4
  from albibong.classes.world_data import WorldData
10
5
  from albibong.threads.websocket_server import send_event
11
6
 
12
- FILENAME = os.path.join(os.path.expanduser("~"), "Albibong/list_dungeon.json")
13
- os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
14
-
15
7
 
16
8
  class WorldDataUtils:
17
9
 
18
- def end_current_dungeon(world_data: WorldData):
19
- if world_data.current_dungeon:
20
- list_dungeon = deque()
21
-
22
- try:
23
- with open(FILENAME) as json_file:
24
- list_dungeon = deque(json.load(json_file))
25
- except:
26
- pass
27
-
28
- world_data.current_dungeon.get_elapsed_time()
29
- list_dungeon.appendleft(Dungeon.serialize(world_data.current_dungeon))
30
-
31
- with open(FILENAME, "w") as json_file:
32
- json.dump(list(list_dungeon), json_file)
10
+ def save_current_island(current_map: Island):
11
+ current_map.save(force_insert=True)
12
+ WorldDataUtils.ws_update_total_harvest_by_date(
13
+ Island.get_total_harvest_by_date()
14
+ )
15
+ WorldDataUtils.ws_update_island(Island.get_all_island())
16
+
17
+ def set_island_status(current_island: Island, parameters):
18
+ check_map = (
19
+ Location.get_location_from_code(parameters[1])
20
+ if 1 in parameters
21
+ else Location.get_location_from_code(parameters[0])
22
+ )
23
+ check_map_name = (
24
+ f"{parameters[2]}'s {check_map.name}" if 2 in parameters else check_map.name
25
+ )
26
+ if current_island.name != check_map_name:
27
+ if current_island.crops != {} or current_island.animals != {}:
28
+ WorldDataUtils.save_current_island(current_island)
29
+
30
+ def ws_update_total_harvest_by_date(payload):
31
+ event = {
32
+ "type": "update_total_harvest_by_date",
33
+ "payload": payload,
34
+ }
35
+ send_event(event)
33
36
 
34
- WorldDataUtils.ws_update_dungeon(list(list_dungeon))
37
+ def ws_update_island(list_island: list):
38
+ event = {
39
+ "type": "update_island",
40
+ "payload": {"list_island": list_island},
41
+ }
42
+ send_event(event)
35
43
 
44
+ def end_current_dungeon(world_data: WorldData):
45
+ if world_data.current_dungeon:
46
+ world_data.current_dungeon.set_end_time()
47
+ world_data.current_dungeon.update_meter(
48
+ world_data.serialize_party_members()
49
+ )
50
+ world_data.current_dungeon.save(force_insert=True)
51
+ WorldDataUtils.ws_update_dungeon(Dungeon.get_all_dungeon())
36
52
  world_data.current_dungeon = None
37
53
 
38
54
  def ws_update_dungeon(list_dungeon: list):
@@ -45,14 +61,14 @@ class WorldDataUtils:
45
61
  @staticmethod
46
62
  def start_current_dungeon(world_data: WorldData, type: str, name: str):
47
63
  if world_data.current_dungeon == None:
48
- new_dungeon = Dungeon(type, name)
64
+ new_dungeon = Dungeon(type=type, name=name)
49
65
  world_data.current_dungeon = new_dungeon
50
66
 
51
67
  @staticmethod
52
68
  def set_dungeon_status(
53
69
  world_data: WorldData, check_map: Location, map_type_splitted: set
54
70
  ):
55
- if "EXPEDITION" in map_type_splitted:
71
+ if "EXPEDITION" in map_type_splitted or "HELLGATE" in map_type_splitted:
56
72
  WorldDataUtils.start_current_dungeon(
57
73
  world_data, type=check_map.type, name=check_map.name
58
74
  )
@@ -102,11 +118,27 @@ class WorldDataUtils:
102
118
  else:
103
119
  char.update_heal_dealt(nominal)
104
120
 
105
- WorldDataUtils.ws_update_damage_heal(world_data)
121
+ WorldDataUtils.ws_update_damage_meter(world_data)
106
122
 
107
- def ws_update_damage_heal(world_data: WorldData):
123
+ def ws_update_damage_meter(world_data: WorldData):
108
124
  event = {
109
- "type": "update_dps",
125
+ "type": "update_damage_meter",
110
126
  "payload": {"party_members": world_data.serialize_party_members()},
111
127
  }
112
128
  send_event(event)
129
+
130
+ def ws_update_location(world_data: WorldData):
131
+ event = {
132
+ "type": "update_location",
133
+ "payload": {
134
+ "map": (
135
+ world_data.current_map.name if world_data.current_map else "None"
136
+ ),
137
+ "dungeon": (
138
+ world_data.current_dungeon.name
139
+ if world_data.current_dungeon
140
+ else "None"
141
+ ),
142
+ },
143
+ }
144
+ send_event(event)
albibong/classes/item.py CHANGED
@@ -1,9 +1,16 @@
1
1
  import json
2
2
  import os
3
3
 
4
- itemsJsonPath = os.path.join(os.path.dirname(__file__), "../resources/items.json")
5
- with open(itemsJsonPath) as json_file:
6
- item_data = json.load(json_file)
4
+ itemsByIdJsonPath = os.path.join(
5
+ os.path.dirname(__file__), "../resources/items_by_id.json"
6
+ )
7
+ itemsByUniqueNameJsonPath = os.path.join(
8
+ os.path.dirname(__file__), "../resources/items_by_unique_name.json"
9
+ )
10
+ with open(itemsByIdJsonPath) as json_file:
11
+ items_by_id = json.load(json_file)
12
+ with open(itemsByUniqueNameJsonPath) as json_file:
13
+ items_by_unique_name = json.load(json_file)
7
14
 
8
15
 
9
16
  class Item:
@@ -17,6 +24,7 @@ class Item:
17
24
  if self.unique_name != "None"
18
25
  else "/No Equipment.png"
19
26
  )
27
+ self.quantity = 0
20
28
 
21
29
  @staticmethod
22
30
  def serialize(item):
@@ -25,6 +33,7 @@ class Item:
25
33
  "name": item.name,
26
34
  "unique_name": item.unique_name,
27
35
  "image": item.image,
36
+ "quantity": item.quantity,
28
37
  }
29
38
 
30
39
  @staticmethod
@@ -36,6 +45,12 @@ class Item:
36
45
 
37
46
  @classmethod
38
47
  def get_item_from_code(cls, code: str):
39
- item = item_data[code]
48
+ item = items_by_id[code]
49
+
50
+ return cls(id=item["id"], name=item["name"], unique_name=item["unique_name"])
51
+
52
+ @classmethod
53
+ def get_item_from_unique_name(cls, unique_name: str):
54
+ item = items_by_unique_name[unique_name]
40
55
 
41
56
  return cls(id=item["id"], name=item["name"], unique_name=item["unique_name"])
@@ -1,20 +1,151 @@
1
1
  import json
2
2
  import os
3
+ import stat
4
+ import uuid
5
+ from datetime import date, datetime, timedelta
6
+
7
+ from peewee import CharField, DateTimeField, UUIDField, fn
8
+ from playhouse.sqlite_ext import JSONField
9
+
10
+ from albibong.classes.dungeon import Dungeon
11
+ from albibong.classes.item import Item
12
+ from albibong.models.models import BaseModel
3
13
 
4
14
  mapsJsonPath = os.path.join(os.path.dirname(__file__), "../resources/maps.json")
5
15
  with open(mapsJsonPath) as json_file:
6
16
  map_data = json.load(json_file)
7
17
 
8
18
 
9
- class Location:
19
+ class Location(BaseModel):
10
20
 
11
- def __init__(self, id: str, name: str, type: str):
12
- self.id = id
13
- self.name = name
14
- self.type = type
21
+ uuid = UUIDField(unique=True, default=uuid.uuid4)
22
+ id = CharField()
23
+ name = CharField()
24
+ type = CharField()
15
25
 
16
26
  @classmethod
17
27
  def get_location_from_code(cls, code: str):
18
28
  location = map_data[code]
19
29
 
20
30
  return cls(id=location["id"], name=location["name"], type=location["type"])
31
+
32
+
33
+ class Island(Location, BaseModel):
34
+
35
+ uuid = UUIDField(unique=True, default=uuid.uuid4)
36
+ id = CharField()
37
+ name = CharField()
38
+ type = CharField()
39
+ start_time = DateTimeField(default=datetime.now)
40
+ crops = JSONField(default=dict)
41
+ animals = JSONField(default=dict)
42
+
43
+ def add_crop(self, unique_name, quantity):
44
+ crop = Item.get_item_from_unique_name(unique_name)
45
+
46
+ if crop.name not in self.crops:
47
+ self.crops[crop.name] = Item.serialize(crop)
48
+
49
+ self.crops[crop.name]["quantity"] += quantity
50
+
51
+ def add_animal(self, unique_name, quantity):
52
+ animal = Item.get_item_from_unique_name(unique_name)
53
+
54
+ if animal.name not in self.animals:
55
+ self.animals[animal.name] = Item.serialize(animal)
56
+
57
+ self.animals[animal.name]["quantity"] += quantity
58
+
59
+ @staticmethod
60
+ def serialize(island):
61
+ data = {
62
+ "id": str(island.uuid),
63
+ "name": island.name,
64
+ "type": island.type,
65
+ "date_time": island.start_time.strftime("%a %d %b %Y, %I:%M%p"),
66
+ "crops": island.serialize_crops(),
67
+ "animals": island.serialize_animals(),
68
+ }
69
+ return data
70
+
71
+ def serialize_animals(self):
72
+ serialized = []
73
+
74
+ for key, value in self.animals.items():
75
+ serialized.append(value)
76
+
77
+ return serialized
78
+
79
+ def serialize_crops(self):
80
+ serialized = []
81
+
82
+ for key, value in self.crops.items():
83
+ serialized.append(value)
84
+
85
+ return serialized
86
+
87
+ @staticmethod
88
+ def get_all_island():
89
+ query = Island.select().order_by(Island.start_time.desc())
90
+ a = [Island.serialize(island) for island in query]
91
+ return a
92
+
93
+ @staticmethod
94
+ def get_total_harvest_by_date(date=datetime.today()):
95
+
96
+ date = date
97
+ tomorrow = date + timedelta(days=1)
98
+
99
+ query = Island.select().where(
100
+ Island.start_time >= date.date(),
101
+ Island.start_time < tomorrow.date(),
102
+ )
103
+
104
+ total_crops = {}
105
+ total_animals = {}
106
+
107
+ for island in query:
108
+
109
+ crops = island.crops
110
+ for key, value in crops.items():
111
+ if key not in total_crops:
112
+ total_crops[key] = {
113
+ "name": key,
114
+ "quantity": value["quantity"],
115
+ "image": value["image"],
116
+ }
117
+ else:
118
+ total_crops[key]["quantity"] += value["quantity"]
119
+
120
+ animals = island.animals
121
+ for key, value in animals.items():
122
+ if key not in total_animals:
123
+ total_animals[key] = {
124
+ "name": key,
125
+ "quantity": value["quantity"],
126
+ "image": value["image"],
127
+ }
128
+ else:
129
+ total_animals[key]["quantity"] += value["quantity"]
130
+
131
+ crops_result = []
132
+ for key, value in total_crops.items():
133
+ crops_result.append(value)
134
+
135
+ animals_result = []
136
+ for key, value in total_animals.items():
137
+ animals_result.append(value)
138
+
139
+ return {
140
+ "crops": crops_result,
141
+ "animals": animals_result,
142
+ "date": str(date.date()),
143
+ }
144
+
145
+ @staticmethod
146
+ def get_island_from_code(code: str):
147
+ island = map_data[code]
148
+
149
+ obj = Island(id=island["id"], name=island["name"], type=island["type"])
150
+
151
+ return obj
albibong/classes/utils.py CHANGED
@@ -1,5 +1,13 @@
1
+ import os
2
+ import platform
3
+ from importlib.metadata import version
1
4
  from uuid import UUID
2
5
 
6
+ from scapy.all import conf, get_if_addr
7
+
8
+ FILENAME = os.path.join(os.path.expanduser("~"), "Albibong/Debug/user_spec.txt")
9
+ os.makedirs(os.path.dirname(FILENAME), exist_ok=True)
10
+
3
11
 
4
12
  class Utils:
5
13
 
@@ -7,3 +15,15 @@ class Utils:
7
15
  def convert_int_arr_to_uuid(arr):
8
16
  b = bytes(arr)
9
17
  return UUID(bytes=b)
18
+
19
+ @staticmethod
20
+ def get_user_specifications(install_source: str):
21
+ os_ver = f"{platform.system()} {platform.release()}"
22
+ python_ver = platform.python_version()
23
+ albibong_ver = version("albibong")
24
+ interfaces = f"{conf.iface} ({get_if_addr(conf.iface)})"
25
+
26
+ text = f"\n===\n\nAlbibong Ver : {albibong_ver}\nPython Ver : {python_ver}\nOS Ver : {os_ver}\nInstallation Source : {install_source}\nInterfaces : {interfaces}\n\n===\n"
27
+ print(text)
28
+ with open(FILENAME, "w+") as file:
29
+ file.write(text)
@@ -0,0 +1 @@
1
+ *{box-sizing:border-box}:root{font-family:Inter,system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}p{margin:0}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}#root,body{margin:auto;display:flex;flex-direction:column;justify-content:start;align-items:center;min-width:320px;min-height:100vh;color:#fff;width:100%}h1{font-size:2em;line-height:1}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}._passed_ifjrf_1{background-color:green}._failed_ifjrf_4{background-color:red}._healthCheckDiv_ifjrf_7{width:1rem;height:1rem;border-radius:1rem}._toolbar_ifjrf_14{display:flex;justify-content:space-between}._data_ifjrf_19{display:flex;gap:1rem;align-items:center}._dmgBar_uvx94_1{background:linear-gradient(135deg,#ff6486,#6486ff);height:6px;border-radius:8px;margin-bottom:2px}._healBar_uvx94_8{background:linear-gradient(135deg,#64ffde,#64ff90);height:2px;border-radius:4px}._dpsContainer_uvx94_14{display:flex;flex-direction:column;justify-content:flex-start;width:100%;gap:4px;box-sizing:content-box;padding:16px}._dpsRow_uvx94_24{display:flex;flex-direction:row;justify-content:space-between;align-items:center}._dpsNumber_uvx94_31{width:128px;text-align:right}._dpsButton_uvx94_36{display:flex;flex-grow:1;gap:1rem}._hidden_uvx94_42{display:none}._player_uvx94_46{flex-grow:1}._checkboxColor_uvx94_50{accent-color:#64d3ff}._dungeonContainer_1kru6_1{border-radius:1rem;width:100%;padding:2rem;display:flex;flex-direction:column;gap:1rem}._tag_1kru6_12{background-color:#64d3ff;padding:0 1rem;border-radius:1rem;color:#0f3c4e;font-weight:700}._stats_1kru6_20{display:flex;flex-direction:row;align-items:start;gap:.5rem}._statRow_1kru6_27{display:flex;flex-direction:row;align-items:start;gap:3rem}._stickToTop_1kru6_34{z-index:10;position:sticky;top:64px;left:0;width:100%;padding:24px 0}@media screen and (max-width: 1000px){._statRow_1kru6_27{width:100%;justify-content:space-between;gap:0}}._container_1ha35_1{display:flex;flex-direction:column;align-items:center;gap:8px;width:100%;gap:1.5rem}._snackbar_1ha35_10{position:fixed;right:64px}._stats_1ha35_15{display:flex;flex-direction:row;align-items:center;gap:.5rem}._options_1ha35_22{display:flex;flex-direction:row;align-items:center;gap:2rem}._row_1ha35_29{display:flex;width:100%;justify-content:space-between;align-items:center}._hidden_1ha35_36{display:none}._column_owxpy_1{width:50%;display:flex;flex-direction:column;gap:16px}._row_owxpy_8{display:flex;gap:40px}._harvest_owxpy_13{display:flex;gap:8px;align-items:center}._statsContainer_owxpy_19{width:100%;display:flex;flex-direction:column;gap:0}