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.
- albibong/__init__.py +92 -8
- albibong/__main__.py +6 -0
- albibong/classes/character.py +7 -23
- albibong/classes/dungeon.py +53 -32
- albibong/classes/event_handler/__init__.py +17 -1
- albibong/classes/event_handler/handle_event_character_equipment_changed.py +2 -10
- albibong/classes/event_handler/handle_event_might_and_favor_received_event.py +18 -0
- albibong/classes/event_handler/handle_event_other_grabbed_loot.py +9 -0
- albibong/classes/event_handler/handle_event_party.py +6 -13
- albibong/classes/event_handler/handle_event_update_fame.py +9 -0
- albibong/classes/event_handler/handle_event_update_re_spec_points.py +9 -0
- albibong/classes/event_handler/handle_operation_change_cluster.py +17 -22
- albibong/classes/event_handler/handle_operation_farmable_harvest.py +17 -0
- albibong/classes/event_handler/handle_operation_join.py +14 -36
- albibong/classes/event_handler/world_data_utils.py +62 -30
- albibong/classes/item.py +19 -4
- albibong/classes/location.py +136 -5
- albibong/classes/utils.py +20 -0
- albibong/gui_dist/assets/index-B31tZ4Ku.css +1 -0
- albibong/gui_dist/assets/index-BkyL_QUY.js +168 -0
- albibong/gui_dist/favor.png +0 -0
- albibong/gui_dist/index.html +2 -2
- albibong/gui_dist/might.png +0 -0
- albibong/migrations/001_init.py +97 -0
- albibong/migrations/002_alter_dungeon_table.py +53 -0
- albibong/models/__init__.py +0 -0
- albibong/models/models.py +12 -0
- albibong/requirements.txt +2 -0
- albibong/resources/items_by_unique_name.json +55282 -0
- albibong/resources/maps.json +259 -259
- albibong/threads/http_server.py +4 -0
- albibong/threads/sniffer_thread.py +39 -2
- albibong/threads/websocket_server.py +80 -43
- {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/METADATA +3 -1
- {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/RECORD +39 -32
- albibong/gui_dist/assets/index-DZvgNqlG.css +0 -1
- albibong/gui_dist/assets/index-Dt6hyZiS.css +0 -1
- albibong/gui_dist/assets/index-E7pha23k.js +0 -161
- albibong/gui_dist/assets/index-WIuC9Mnh.js +0 -161
- /albibong/resources/{items.json → items_by_id.json} +0 -0
- {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/WHEEL +0 -0
- {albibong-1.0.7.dist-info → albibong-1.1.1.dist-info}/entry_points.txt +0 -0
- {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
|
-
|
|
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
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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
|
-
|
|
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.
|
|
121
|
+
WorldDataUtils.ws_update_damage_meter(world_data)
|
|
106
122
|
|
|
107
|
-
def
|
|
123
|
+
def ws_update_damage_meter(world_data: WorldData):
|
|
108
124
|
event = {
|
|
109
|
-
"type": "
|
|
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
|
-
|
|
5
|
-
|
|
6
|
-
|
|
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 =
|
|
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"])
|
albibong/classes/location.py
CHANGED
|
@@ -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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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}
|