From ac1c9bd30eae33bd8b9d42f561bc4e4f3370810d Mon Sep 17 00:00:00 2001 From: 0ceanSlim <89587889+0ceanSlim@users.noreply.github.com> Date: Mon, 4 Sep 2023 20:32:51 -0400 Subject: [PATCH] just add csv and run main.py, set id starts in id.py --- Database/__pycache__/id.cpython-311.pyc | Bin 0 -> 223 bytes Database/createTables.py | 91 ++++++++++----------- Database/data/ammo.csv | 25 +++--- Database/data/craft.csv | 102 ++++++++++++------------ Database/id.py | 7 ++ Database/importData.py | 59 +++++--------- Database/items.db | Bin 77824 -> 81920 bytes 7 files changed, 129 insertions(+), 155 deletions(-) create mode 100644 Database/__pycache__/id.cpython-311.pyc create mode 100644 Database/id.py diff --git a/Database/__pycache__/id.cpython-311.pyc b/Database/__pycache__/id.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0a8e97bdc669d430e28baa367e8c1ad0c5dfaed6 GIT binary patch literal 223 zcmZ3^%ge<81kEMiQVN0eV-N=hSfGs0LO{lJh7^Vr#uTO$<~ht!3@I$Z44SN&3VsX> znF8uS!l0CaL6i9wXHjZSequ^yUivMT#N6EcTdc`NiD@N%nvA!2ic1oUN`Nx)nJL99 z89svy|E1_`72}+rk{VM`l%JKFT;iIO8RL>zl9-fOoEnpvqE}G)i^C>2KczG$)vkyW tsDlxRixq&x2WCb_#t$3}LgF`g1aI&PePCx1VEe!TBpP@?u!tR~2motVIVS)B literal 0 HcmV?d00001 diff --git a/Database/createTables.py b/Database/createTables.py index c9460dae..1ec4dcfa 100644 --- a/Database/createTables.py +++ b/Database/createTables.py @@ -1,60 +1,51 @@ import sqlite3 +import os +import csv + + +# Function to determine the data type of a value +def get_data_type(value): + try: + int(value) + return "INTEGER" + except ValueError: + try: + float(value) + return "REAL" + except ValueError: + return "TEXT" + # Connect to the SQLite database conn = sqlite3.connect("items.db") cursor = conn.cursor() -# Define the table schema for reloading -cursor.execute( - """ - CREATE TABLE IF NOT EXISTS reloading ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - type TEXT, - name TEXT, - rarity INTEGER, - weight REAL, - width INTEGER, - height INTEGER, - stack INTEGER, - value INTEGER - ) -""" -) +# Get a list of CSV files in the "data" directory +data_dir = "data" # Change this to your data directory path +csv_files = [f for f in os.listdir(data_dir) if f.endswith(".csv")] -# Define the table schema for ammo -cursor.execute( - """ - CREATE TABLE IF NOT EXISTS ammo ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - type TEXT, - name TEXT, - rarity INTEGER, - weight REAL, - width INTEGER, - height INTEGER, - stack INTEGER, - value INTEGER, - gunpowder INTEGER - ) -""" -) +# Iterate through CSV files and create tables +for csv_file in csv_files: + table_name = os.path.splitext(csv_file)[ + 0 + ] # Remove the file extension to get the table name -# Define the table schema for ammo -cursor.execute( - """ - CREATE TABLE IF NOT EXISTS craft ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - type TEXT, - name TEXT, - rarity INTEGER, - weight REAL, - width INTEGER, - height INTEGER, - stack INTEGER, - value INTEGER - ) -""" -) + # Read the first row of the CSV file to determine the column names and data types + with open(os.path.join(data_dir, csv_file), newline="") as csvfile: + csv_reader = csv.reader(csvfile) + header = next(csv_reader) -# Close the connection + data_types = [get_data_type(value) for value in header] + + # Generate the CREATE TABLE statement dynamically based on the column names and data types + create_table_sql = f"CREATE TABLE IF NOT EXISTS {table_name} (\n" + for column_name, data_type in zip(header, data_types): + create_table_sql += f" {column_name} {data_type},\n" + create_table_sql = create_table_sql.rstrip(",\n") + "\n);" + + # Execute the CREATE TABLE statement + cursor.execute(create_table_sql) + +# Commit the changes and close the connection +conn.commit() conn.close() diff --git a/Database/data/ammo.csv b/Database/data/ammo.csv index a6465978..211711ed 100644 --- a/Database/data/ammo.csv +++ b/Database/data/ammo.csv @@ -1,14 +1,13 @@ id,type,name,rarity,weight,width,height,stack,value,gunpowder -NULL,rifle_ammo,5.56x45 AP,4,0.02646,1,1,30,7500,15 -NULL,rifle_ammo,5.56x45 FMJ,1,0.02646,1,1,30,2500,10 -NULL,rifle_ammo,5.56x45 HP,2,0.02646,1,1,30,5000,10 -NULL,pistol_ammo,9mm AP,3,0.01984,1,1,45,5000,12 -NULL,pistol_ammo,9mm FMJ,1,0.01984,1,1,45,2000,6 -NULL,pistol_ammo,9mm HP,2,0.01984,1,1,45,4000,6 -NULL,pistol_ammo,.40 S&W AP,3,0.01984,1,1,45,5500,13 -NULL,pistol_ammo,.40 S&W FMJ,1,0.01984,1,1,45,3000,7 -NULL,pistol_ammo,.40 S&W HP,2,0.01984,1,1,45,4500,7 -NULL,rifle_ammo,7.62x39 AP,4,0.02646,1,1,30,5200,15 -NULL,rifle_ammo,7.62x39 FMJ,1,0.02646,1,1,30,1800,10 -NULL,rifle_ammo,7.62x39 HP,2,0.02646,1,1,30,3600,10 -NULL,rifle_ammo,27.62x39 HP,2,0.02646,1,1,30,3600,10 +NULL,ammoRifle,5.56x45 AP,4,0.02646,1,1,30,7500,15 +NULL,ammoRifle,5.56x45 FMJ,1,0.02646,1,1,30,2500,10 +NULL,ammoRifle,5.56x45 HP,2,0.02646,1,1,30,5000,10 +NULL,ammoPistol,9mm AP,3,0.01984,1,1,45,5000,12 +NULL,ammoPistol,9mm FMJ,1,0.01984,1,1,45,2000,6 +NULL,ammoPistol,9mm HP,2,0.01984,1,1,45,4000,6 +NULL,ammoPistol,.40 S&W AP,3,0.01984,1,1,45,5500,13 +NULL,ammoPistol,.40 S&W FMJ,1,0.01984,1,1,45,3000,7 +NULL,ammoPistol,.40 S&W HP,2,0.01984,1,1,45,4500,7 +NULL,ammoRifle,7.62x39 AP,4,0.02646,1,1,30,5200,15 +NULL,ammoRifle,7.62x39 FMJ,1,0.02646,1,1,30,1800,10 +NULL,ammoRifle,7.62x39 HP,2,0.02646,1,1,30,3600,10 \ No newline at end of file diff --git a/Database/data/craft.csv b/Database/data/craft.csv index ef5580af..ad6e0858 100644 --- a/Database/data/craft.csv +++ b/Database/data/craft.csv @@ -1,52 +1,52 @@ id,type,name,rarity,weight,width,height,stack,value -NULL,Basic Materials,Coal,2,0.02100,1,1,5,2500 -NULL,Basic Materials,Wood,1,0.02100,1,1,20,1000 -NULL,Basic Materials,Leather,2,0.25000,1,1,2,20000 -NULL,Basic Materials,Cloth,1,0.03086,1,1,5,5000 -NULL,Basic Materials,Plastic,1,0.22046,1,1,10,600 -NULL,Basic Materials,Thread,1,0.00772,1,1,20,250 -NULL,Basic Materials,Acid,1,0.02100,1,1,10,2500 -NULL,Basic Materials,Adhesive,2,0.03969,1,1,10,6000 -NULL,Basic Materials,Antiseptic,2,0.03969,1,1,2,5000 -NULL,Basic Materials,Oil,2,0.06857,1,1,10,5000 -NULL,Basic Materials,Steel,1,0.06857,1,1,20,300 -NULL,Basic Materials,Copper,2,0.06857,1,1,10,2000 -NULL,Basic Materials,Zinc,1,0.06857,1,1,10,400 -NULL,Basic Materials,Lead,2,0.34286,1,1,5,1500 -NULL,Basic Materials,Aluminum,2,0.06857,1,1,10,1200 -NULL,Basic Materials,Gold Scrap,5,0.06857,1,1,10,250000 -NULL,Basic Materials,Silver Scrap,4,0.06857,1,1,10,50000 -NULL,Basic Materials,Glass,1,0.03969,1,1,10,1000 -NULL,Basic Materials,Ceramic,2,0.22046,1,1,10,1000 -NULL,Tools,Hammer,1,1.25000,1,2,1,75000 -NULL,Tools,Flathead Screwdriver,1,0.33069,1,1,2,25000 -NULL,Tools,Phillip Head Screwdriver,1,0.33069,1,1,2,25000 -NULL,Tools,Set of Wrenches,3,3.00000,2,2,4,165000 -NULL,Tools,Large Pliers,1,0.33069,1,1,1,25000 -NULL,Tools,Needle Nose Pliers,1,0.33069,1,1,1,25000 -NULL,Tools,Measuring Tape,1,0.33069,1,1,1,40000 -NULL,Tools,Lock Pick,2,0.05000,1,1,5,50000 -NULL,Tools,Drill,3,4.00000,2,2,4,225000 -NULL,Tools,Multi-Tool,4,0.25000,1,1,1,400000 -NULL,Tools,Roll Pin Punch Set,3,3.00000,2,2,4,120000 -NULL,Tools,Set of Files,3,2.00000,2,2,4,200000 -NULL,Tools,Rotary Tool,3,1.50000,1,2,2,180000 -NULL,Tools,Bench Vise,3,30.00000,2,2,4,350000 -NULL,Tools,Scissors,1,0.20000,2,1,2,35000 -NULL,Tools,Set of sockets,3,3.12500,2,1,2,50000 -NULL,Tools,Socket,1,0.31250,1,1,10,5000 -NULL,Tools,Wrench,1,0.60000,1,2,2,33000 -NULL,Tools,File,1,0.40000,1,2,2,40000 -NULL,Tools,Ratchet,2,1.00000,1,2,2,25000 -NULL,Tools,Needle,1,0.01544,1,1,10,200 -NULL,Advanced Materials,Brass,3,0.06857,1,1,10,2500 -NULL,Advanced Materials,Tape,2,0.11023,1,1,1,5000 -NULL,Advanced Materials,Ballistic Fiber,3,0.57500,1,1,2,25000 -NULL,Advanced Materials,Circuitry,3,0.22046,1,1,10,20000 -NULL,Advanced Materials,Springs,3,0.07938,1,1,5,10000 -NULL,Advanced Materials,Screws,3,0.07938,1,1,10,5000 -NULL,Advanced Materials,Gears,3,0.07938,1,1,5,8000 -NULL,Advanced Materials,Rubber,1,0.22046,1,1,10,5600 -NULL,Junk,Car Battery,3,35.00000,3,2,6,500000 -NULL,Junk,Pre-War Money,3,0.00050,1,1,100,5000 -NULL,Junk,Syringe,2,0.22046,1,1,1,7500 \ No newline at end of file +NULL,matBasic,Coal,2,0.021,1,1,5,2500 +NULL,matBasic,Wood,1,0.021,1,1,20,1000 +NULL,matBasic,Leather,2,0.25,1,1,2,20000 +NULL,matBasic,Cloth,1,0.03086,1,1,5,5000 +NULL,matBasic,Plastic,1,0.22046,1,1,10,600 +NULL,matBasic,Thread,1,0.00772,1,1,20,250 +NULL,matBasic,Acid,1,0.021,1,1,10,2500 +NULL,matBasic,Adhesive,2,0.03969,1,1,10,6000 +NULL,matBasic,Antiseptic,2,0.03969,1,1,2,5000 +NULL,matBasic,Oil,2,0.06857,1,1,10,5000 +NULL,matBasic,Steel,1,0.06857,1,1,20,300 +NULL,matBasic,Copper,2,0.06857,1,1,10,2000 +NULL,matBasic,Zinc,1,0.06857,1,1,10,400 +NULL,matBasic,Lead,2,0.34286,1,1,5,1500 +NULL,matBasic,Aluminum,2,0.06857,1,1,10,1200 +NULL,matBasic,Gold Scrap,5,0.06857,1,1,10,250000 +NULL,matBasic,Silver Scrap,4,0.06857,1,1,10,50000 +NULL,matBasic,Glass,1,0.03969,1,1,10,1000 +NULL,matBasic,Ceramic,2,0.22046,1,1,10,1000 +NULL,tool,Hammer,1,1.25,1,2,1,75000 +NULL,tool,Flathead Screwdriver,1,0.33069,1,1,2,25000 +NULL,tool,Phillip Head Screwdriver,1,0.33069,1,1,2,25000 +NULL,tool,Set of Wrenches,3,3,2,2,4,165000 +NULL,tool,Large Pliers,1,0.33069,1,1,1,25000 +NULL,tool,Needle Nose Pliers,1,0.33069,1,1,1,25000 +NULL,tool,Measuring Tape,1,0.33069,1,1,1,40000 +NULL,tool,Lock Pick,2,0.05,1,1,5,50000 +NULL,tool,Drill,3,4,2,2,4,225000 +NULL,tool,Multi-Tool,4,0.25,1,1,1,400000 +NULL,tool,Roll Pin Punch Set,3,3,2,2,4,120000 +NULL,tool,Set of Files,3,2,2,2,4,200000 +NULL,tool,Rotary Tool,3,1.5,1,2,2,180000 +NULL,tool,Bench Vise,3,30,2,2,4,350000 +NULL,tool,Scissors,1,0.2,2,1,2,35000 +NULL,tool,Set of sockets,3,3.125,2,1,2,50000 +NULL,tool,Socket,1,0.3125,1,1,10,5000 +NULL,tool,Wrench,1,0.6,1,2,2,33000 +NULL,tool,File,1,0.4,1,2,2,40000 +NULL,tool,Ratchet,2,1,1,2,2,25000 +NULL,tool,Needle,1,0.01544,1,1,10,200 +NULL,matAdv,Brass,3,0.06857,1,1,10,2500 +NULL,matAdv,Tape,2,0.11023,1,1,1,5000 +NULL,matAdv,Ballistic Fiber,3,0.575,1,1,2,25000 +NULL,matAdv,Circuitry,3,0.22046,1,1,10,20000 +NULL,matAdv,Springs,3,0.07938,1,1,5,10000 +NULL,matAdv,Screws,3,0.07938,1,1,10,5000 +NULL,matAdv,Gears,3,0.07938,1,1,5,8000 +NULL,matAdv,Rubber,1,0.22046,1,1,10,5600 +NULL,junk,Car Battery,3,35,3,2,6,500000 +NULL,junk,Pre-War Money,3,0.0005,1,1,100,5000 +NULL,junk,Syringe,2,0.22046,1,1,1,7500 diff --git a/Database/id.py b/Database/id.py new file mode 100644 index 00000000..404e98dd --- /dev/null +++ b/Database/id.py @@ -0,0 +1,7 @@ +# starting_ids.py + +starting_ids = { + "reloading": 20000, + "ammo": 10000, + "craft": 30000 + } diff --git a/Database/importData.py b/Database/importData.py index b27e999a..201785dc 100644 --- a/Database/importData.py +++ b/Database/importData.py @@ -1,6 +1,7 @@ import csv import os import sqlite3 +from id import starting_ids # Connect to the SQLite database conn = sqlite3.connect("items.db") @@ -9,41 +10,12 @@ cursor = conn.cursor() # Define the directory where the CSV files are located csv_directory = "data" # Change this to your directory path -# Define the CSV file names -csv_file_reloading = "reloading.csv" -csv_file_ammo = "ammo.csv" -csv_file_craft = "craft.csv" - -# Build the full paths to the CSV files -csv_path_reloading = os.path.join(csv_directory, csv_file_reloading) -csv_path_ammo = os.path.join(csv_directory, csv_file_ammo) -csv_path_craft = os.path.join(csv_directory, csv_file_craft) - -# Define the starting ID values for each table -starting_id_reloading = 20000 -starting_id_ammo = 10000 -starting_id_craft = 30000 - -# Set the starting ID values for each table using INSERT statements -cursor.execute(f"INSERT INTO reloading (id) VALUES ({starting_id_reloading})") -cursor.execute(f"INSERT INTO ammo (id) VALUES ({starting_id_ammo})") -cursor.execute(f"INSERT INTO craft (id) VALUES ({starting_id_craft})") - -# Reset the ID sequences for all tables -cursor.execute("DELETE FROM SQLITE_SEQUENCE") -cursor.execute( - f"INSERT INTO SQLITE_SEQUENCE (name, seq) VALUES ('reloading', {starting_id_reloading})" -) -cursor.execute( - f"INSERT INTO SQLITE_SEQUENCE (name, seq) VALUES ('ammo', {starting_id_ammo})" -) -cursor.execute( - f"INSERT INTO SQLITE_SEQUENCE (name, seq) VALUES ('craft', {starting_id_craft})" -) +# Define the starting IDs for each table type +# starting_ids = {"reloading": 20000, "ammo": 10000, "craft": 30000} # Function to load data from a CSV file into a table -def load_csv_data(csv_path, table_name, cursor): +def load_csv_data(csv_path, table_name, cursor, starting_id): # Delete existing data in the table delete_query = f"DELETE FROM {table_name}" cursor.execute(delete_query) @@ -55,18 +27,23 @@ def load_csv_data(csv_path, table_name, cursor): # Exclude the first column (id) from the row values = row[1:] placeholders = ", ".join(["?"] * len(values)) - insert_query = f"INSERT INTO {table_name} VALUES (NULL, {placeholders})" - cursor.execute(insert_query, values) + insert_query = f"INSERT INTO {table_name} VALUES (?, {placeholders})" + cursor.execute(insert_query, [starting_id] + values) + starting_id += 1 -# Load data from the reloading CSV file into the reloading table -load_csv_data(csv_path_reloading, "reloading", cursor) +# Get a list of CSV files in the data directory +csv_files = [f for f in os.listdir(csv_directory) if f.endswith(".csv")] -# Load data from the ammo CSV file into the ammo table -load_csv_data(csv_path_ammo, "ammo", cursor) - -# Load data from the ammo CSV file into the ammo table -load_csv_data(csv_path_craft, "craft", cursor) +# Loop through the CSV files and load data into respective tables +for csv_file in csv_files: + table_name = os.path.splitext(csv_file)[ + 0 + ] # Remove the file extension to get the table name + csv_path = os.path.join(csv_directory, csv_file) + if table_name in starting_ids: + starting_id = starting_ids[table_name] + load_csv_data(csv_path, table_name, cursor, starting_id) # Commit the changes and close the connection conn.commit() diff --git a/Database/items.db b/Database/items.db index 9af55b2b7a25f9cf51d5e617eba2862160bb8ff5..e35dcfec0b245e47daceee1a6fc1a39de08e1d01 100644 GIT binary patch literal 81920 zcmeI5d2k$8oyYqaX{LK-`bn1Lu`J7KNtP{H_vP3j$yiq8BbMZeB%)lPv_~zg@kpc0 zjO;k1NGA5yie&>Sj)H*LgoT2nfDm>=Dtl0&3KNdn72Z@_OLjwwO|rGl6eJr6td@c* ze!uSNxpm|ZBocn@>aTiwzWv_sefpU0dGmfAy>ZZp>FQKCGNZ-RZmxvmdG4U9avb+K z%;hjkFf*7VFgswjC*EFI%MtMEVfx0TzJ+g2%! z-Xa2Yw38t{7}2I;ra1aX2KvSZ)Um!pg9EC$N^O+YbfstcFeIvK1#|Lgv``$Zt;@B{3IW#al){=6^&durS*uc#ht7f&C+*J`RV#Lnb z<)*hjs~e}LV=9C*n6c8Bj7{fzr!8+XwzNGO(}Jh-?Ps*myl$^H!);QQ975s&E z6Nol56UJH0!hvhv1!mr51!NWU1Bf za&Gof`{t+@2Oac1GZ4n&QbKV6J*+ zA!zax`>yq^gurajM5p-&ZY#w^=0Tuqky9|sSqN~=#u1=fg`8W3`*&}3(yhY4$eOnb z_iwLo(yapCI%j>9TDJ;;@?u|eGk=SDu}gk-M)f=A_1U1F^Rg)G?9X|#5$^$7V9O?s z<6X&XNBr(8r?0)8KVNSbe{v$G&&*AjFDE*ojO-QJxBYc_@7KZgMyfL=>m=)bUaG@8 zk@PDJBK^v`52=$<_v2EXbsJJAS-11>8t+1~9M&yJ)++OMBWsNbGILGFV@R>D*nE=m zf-2sRbL^+=DYn3FWi3olE-Q~JA5=z^TJQgQpMf`NA_7E!2oM1xKm>>Y5g-CYfCvzQ zKLUZK_+qQfRW?aZN#cc|7KQ$TtJ?N;-PL_S?KfZfqrJ}^d-cR4JNdU-vJ>De0`9=aj9MQQ`V3mfcRsfIqg z21jZG@7EgQi%qaWZD#xjW@d6@7hZ>kHiB_aX6$Gz5O>jwVBQ1fBo!-eG#7}Oe-O;O z3zeLTS4_pr9@!mVYyfk8X1u*^z58+l7O(7$FYdw^G6Oc91tNC3z+DgS=1kJ2yFkdo z>)@^{SavGrG~=>``uJk4%vIDt*}TAGZ^03}1ImBR<^NyY|HN^Df2*q|zNmt&(h31> zfrv4qNBlACc$nl{@cG~4eTiewu`jVR>^M`EUn|clpH`-os}*>|`wj1Xe}sdaiX;L= zfCvx)B0vO)01+SpM1TnV*%4@2s&;cV_0}ULkH485F{VO#SNb7d@PBUG*k66_$Cr01 zC34Hsj<;iPUaA6nZEoo+6yChF9SgUf7SplVZg_4@h2nI{%}bT5mE9L`q}=5J*0QwC z&DCZ`5-_5%aHy@PLmk~c4iEi;|C82JX=~{xoh?f~uxEynZO2$_yZdRdZ(X(YzJQpr zSKQ-mT&e(jWd;_jbnDxPbRg`J;>M+NuvTR-Nn106a9#py*@~rR22i%(XHjSe9AAC zA1I5;S>;BhNpZk;08e`V(tESF%PV>Q+w-L7Ue8UQHV@~%?Ebp@qwXp9)$VfnHTiq; z-^g?FklZL2N&h2VlpdDuk%pvQuHU=<-Su~_2VB#xYoQvNhyW2F0z`la5P?5s0%|;Q z68a9R@FqzTJ}^Ifdh}cbx}tQ!|1bMpe<3}ySUtEWp3uOP?7=}#AfmU9!w;^9!n680 z(SPvd&~tA-_Pfclh1z)H4zSkqIEiTO2iqYn7Ski=#ClOEc78zx(*$&a*!>k+tZ(wn z$o$EZ&|{ITQ?B?KnBEU2pLO>JqZYw*1b*Zl75z_+_)op{pFbrx$ z`q{Kg#%`3v?cg%o$O~3cqjT8Gw5@1QNkcqw8`x?x3+p!`!FeMFv8O^CR-5CATfx|z zX*{HbLU5;R1l7X^G(_~jJY`OT_GnE!aSPZh&@LsbAJgW5@IPCGO>8%VC9AQAB3cyU z`{o1x`uF!d^bJ|M2<42YyLn>aaA;W9CqugbV-NFBPrdpcnft-^c;Y5=Z$h6UFQ8>a ziv_3km>^hzycgcB!0seo#CH!Hu=xuQ;q+NS;1&-8^|53fNy~TyetkRbf2G@;z;xdg z2xK%nkkN4Pv>x+6Zyo7?d~ZB40v6~)<0Y%AQ9Y)Hr_`wFjEVYDHee(i z(<0~8F|dpNWxH1485ItmVX!u&i%Z6cRH7mvbBNx9jq$_~xH{9Wk#H!a28>xXFpssv zMk1IU{PW-06;BMB0pgxE0T0cGVn!?0?eJf+>Mq`XUsXJD9DKfXnb${*P)KxOm9tl% zm>b}2>p(P%83bxjW$?7%f6M|>1lXXh$G~THmL{vywdgz^*eV`i{>yudgWo^#E!eNH zKaPUc><^aA1H(FY)ZuVcR|6qK2i8fu_9z5!1l$eyIApm8am+=Y56+mw;A>8|BT3LY zXaFLD5iTrr#uEczyw-ZY!aWz5h6WpR>QP;rRLxU%GGd&8D?l;`I9yxfiR)pb-t3~Rl=)V2uk*W>A>>0cSDn5V9D=^~V80&GW{hC!nkS1_ z;OOWBqtB`xE*hrsNC-|!|Cg)_5V+t{a1dM#=A}TiU86<_nu5*J<{YUr81`6GJmCks z^?aPN9|?y{2HIRv$}C=baCba$9hj?Aml-pHzR>)PF*`paq^yo7Al7TaX3!Ld3 z1X6j%^>87nPG3~9rsCpkbb6VRMG$#F@iWl$tX?qo1QsKhW3#RlZk=fd@=?I|n z-)mh~%emhIlpe4pzaFq748XAf;iWzpgqs0MH~4a(^oPQ+Y5&6yefJ}duijBqwg87< z7nYU{1@;yk+rT(^nGlBYbFveRIZYT3hf_@`H;>Z}G-a38AJ%|zvY|!NMST7j*$W)| zHG7S{z;0*bY=jN5qpTmk2{^!dSUcOx8kowe*j84`Jj@B>1Aeb8E5A}+S6)+IWvAJ1 z*w5L^>?drAU1a~ro?u^Qi|petmf%Cy$wf*8hyW2F0z`la5CI}U1c(3;AOb{SV+c4z zj^B@R70N!8UX&h`Zj>&RPLvLmc9b@hR+JW$W|X}sO(=~hdr)?xG@$H4sYj_psYOvy zYEX7cqL1(B=;-XmWO@!Gr_WyM*qU7GJWydT z?N>xa6l;W3LaE_aSrC1KnWAj|Bz*H)A>eOK_Eh8ZKP3I5i3kt@B0vO)01+SpM1Tko z0U|&IhyW3I7ZZ@NZS?&AF5bh`G$KF*hyW2F0z`la5CI}U1c(3;AOaj`_y4mO*+0Oq z_GjUj|MiShexf|Cd_*~=^eH>Nzx6)n{fhT)?@iuzuh;XE=c}Fzp7(pYJd*nr_p|Ot z+-KY)?k2ZWep!A>{*)Y%Z z9N7qC=Qa30lqS_74F=*HS}2+~-oCXR?8yP>`S!e#_ib%hx;5x9-<~@LKeOeS6rezk zfsB@;V_hvrV}X{}Ld)06E~9&Vr4!a8W-nwbSKg?D-&Cx9rFR{&FYuOq7fChT5! zP615Ty=q1QOwPSVJ^@I}Z6}S!A=&xa1RxbR9Iu6Q2|(uU)iVh|wry)Dwl)60P#ytD zvz-}0eii}9tiA3W0+3gG?F<5#PP;ZeT)ja40L-MluIvFdU|cJAz)tY2FLOY(8Q5BR z19pIG#jF8U@aEb%1Ga-}T^R!^!MNUh0o%a4cD4W?xYm&?U@O?(W~P7&*yL^G2`C5q z>RAHH@&{-a$`P;yY&oO7^D+dKf@j_N0ZPEU&g=jTthwXh3*`n-z?U;RJTEhV7d@-z z1@M4n?W_Q9aOD8W%LyQZXN`;i5?I!k55NV^TndG<0XV^z)56?b0L5TgGZR1&nAXk% z-~d++hP*5QB9@drYQInp00C?{f#+rb;L(y@QttTwGY(roUn$J^i-9tjx4`UxS;W8V$Q+PNvjT3KhyW2F0z`la5CI}U1c(3;AOb{y z2y6fW94T*p_rAeN0L)?kC_7N9P`0B~qHII)p=?E|Kq*HlL)n5-ic*5YP!tp|iU-Aw zBBMwsE)*w9F-j4NnRr0NB|#K9$?pH(0OV8!5g-CYfCvx)B0vO)01+SpM1Tko0V1$T z1Ze#KCV{7Fi2xBG0z`la5CI}U1c(3;AOb{y2y7q$>i^$B*i;n}AOb{y2oM1xKm>>Y z5g-CYfCvzQO(H=3|C@u1`?qD z{|$sqRS^LqKm>>Y5g-CYfCvx)B0vO)01?>Y5g-CYfCy|L0et@NW&+24$NrD~lKp~RVXv^4*bD4=_G9)V_C59;_D}37 z_D%LR_7(QG?DOn1>=W#x?8EE=yO-U~=Gh!O&8C>fZfE0cgblHyte;)S4zM29&i1kf zrm`xwm6b9Nb233$-oU0&RYZUY5CI}U1c(3;AOb{y2oM1xKm<5R^zq#tF!eY@j_*e4 zLg_^5Kxs#5Luo~6L1{+Wi_(PBh_VM|H%bG_E|hwdI+R)z6{QAcCrUNS4wNdC?I@Kf z+faNcTTv=d%2CQtwxE=vl%Oya1;vZvL2;wVC=!Yb#fegkQiS3_5m5wDQz21Mb)i?%io^N=+=sxfHW8u8}Uj9kp z)2=7^ySP7d{l4=<+%4i49D`NwuX_KL3dH{-fz2RrN4vyHJ|A-?n28=sDAD=(Bz>^M z6C*=YBl6VHfzc6}Zjn0$SzqEa@{#eWkwYUBa%AGj*wDmH@(m+5$wTj&y79<3JaKGf ze5$*k&YW6Q9lPo^7`<syKtng63xg2Rj+ zHs)hYYnYNFs^n<0I+9i$MJJ1nAX!%JZ*}|>9VFWBiw-BjzjupMx}lx1#TRCj+tMFM zz-jkrG@D7Pe;+m1>uAXQS8eWQ!bwd{%;{Q%SOHWzuT!6cJE2U0n$L9;bA@R1Se!p`#)7mp3=X7nwkbrjElyC_+HDTwMe@gf&e7 z^#Kz=bmyiyvk79U=xjy}t|9{JrmG8q-?f$r)CwI9slWK#Y!xT9wlb$B^+<>%7t+~z zdWp8O<}AihP+VP12AodmP;0pZW2LqLrcgspe9QJNdI56Ur_w20U=&syMQjS2e?!nX z>z(Swex%MR1p>@XY9;h@XIl9{R#}KCC4W{GRjA~jo%9-@8=mQhm$WW=J+GfYu6R9v zm0VrzO8k^~RO}NO@3Y>A;AhI~ z_x!KtyPnT`vYvyUZSEhr&%5t(-|X&pbHaq5?8738mto0*yFaf8JR4`)0t#K&AexKpFFv1T21`E$WLC(k3Cv*Uyut1L2jgCA*Z?M za`!oqcduRgP{eM?eYXd_{s749bu6aRubH1WCqm8!o&GM6HtI}Dq^2aeiy-xvFV&Pl z?NZRw-D$~guxD`3ZMz4}tysGRq&qCz#Za5tg}(smU2B$YYL})_XqR?c_9};zHPlYa z!VQa*+ON$raYJoNTs72=HOn?7t{SR!?Ix$Gm<=U^d>w{rS-W&od#Z+NF5mQ~L{vjH zfwV$HZ7*M{DFM|`jh5^Tik2qB=wbwR;(gH=jN#&0@9Cy$oK~&O}9eqoGZ^ z*W}dCYGYW+O}=R6Tu?eSw0d^2l$(svTo)n1WpK21G6K1&Q@1!71#9l(g3I7(%^KEv znvUMr1l{LA53XLTd{ff|eYbo4%iwG6d{kV1$@wTq&N}_e)YYmxR%^|9a2G*KEv=sC zR%^{U)Gm3tm%+~#2rc~4T)PCs!Os>AWXR18#9sh8czTV}%?;EvO6co<(R+`Le4ji) zmdJZaH(|v~;v?dR#0jz0`%~{z-h1F@&U>A=+VhI%yyw%NS>RBDkcbGJWaRcawmdm&G9 zc2^%r^{YaSFTLIkd>AKu-KAgV_dRw4%e>j&5&%)XwsR_qq~h~RDxA^UeTM1wchNnX zTgI?SN$Y^4{2*P2qdGyp4o7vAE8U{@;HX_7ufS35Agj<(J3(5ZquQ)WE#z6`s2w1! z#8Itu?-e>q25qH|YOyT0kZX~nnk#Ws)0G^xo$j$RM>T?U9gb=M`8pg`U#@hE+JmFE zfxH4oNg%7xQCmS;p`(0Or55rma#S5iD{)jU-Ftyb8>m;E!X3nTpoH(>pfW16x@@`)1I^f|K#$tAFa?qxjgMf zEA&tqa^B~?f8l-5q{3AsfCP{L5M;IP}6eKhQ)VGj+1H0-8ffQEh=LNxTz&`U!P z4M7^ZX$a8JMT4J)P8vFB*hND-4LfOQqhSXPtu)9qw9wGZ+a;#2uP-z}AW;Y1)TD3f z-?QCV8*DVzb~hMn1NFvQ|2AVSBpGXcTlKZjH9li)pJ*5Cc8OJ|$jJ8btlh`b!HXSD zB4cl13)4J|_t4k>FzFvINB{{S0VIF~kN^@u0!RP}AOR$R1dzaQF#&bl3BLaSEpB0~ z8WKPPNB{{S0VIF~kN^@u0!RP}AOUUu{{ik!8@WWjL_Q3k{cjh4DLx~f6_etK*x-HL z`?U9dZ``}rYxg|w`J(4zo@q~;`@h}KxgU0a*!^zzK6j1q@4`2P&j=Y|TxjM0kN+P3 zH9pUOkiUU%cD?HQiYw=Or)vlIbM7MdFn1@HLFPyR2_OL^fCS#I1juedGU`46p9t)e zVYWYCBOOo3v+u|*oR~b7f(Z>3HvG@~TzB$M<(o!3V3I$dJ~WalA}J*}4PR_FmRwLy z*~9yfjXnFbM}IX_yVMF({Q24#y4b037(@r6nT(P;WpA^yPVP_TAWZES(r3aOnz=O! z-=Q=kk3~Tek0#O+*<;6GUOauzg6{`GnBgxZX@ebC%MZa9k)`e7zn%ymfAf1ksA}2Y z1Cv*U^ofvH%O_(g<>ZQ9s9oxX`Kv-|-5J(Gzeq`}JfW(iIt24qg<8txGaOIFvhfVm zworv}c`wXh6$+Gl%7JJi0pF4kkI4t)P<4CwrCD`hqmKk&CaaK7Ynau^O+^=>jm~Rr z1QUP5Y*yt#9Y{sfP>;ty`7eKU`vZR|@E71KwrrB#3{%NuB0a7sGYKX9sRx;Jv#(q$ z*uLEelUPZO49r`}u&QDrnu*OR8J30AWSF!{q9cQ$q1AsLjKh;(cz`aSWm#K({|=a} zO5K5>m`=g>WzB_O9#9w1eDtymQ&bftF`0~=P%`1?G=D<-1YlY!3C6lIyuP1FB_k(i z<+LhH+xPRD6pDK~vJ+;dlA3svI2KQ*lc{w09}9^sooj_jsiaoTqiX60XkPNW<7vg- z%(9NE>Ap^w5KW@rm0;vPk<3I>r(`O(hu<=G$v!2w!L)u-yQwfeKZ+x52UHHbcfTLz z^OHg*(L^$lkR$O0Ig+KjhUeHp>tLSydOOVO2g%W6QR6z6O=RLhx?@N9qPAma!$-Hn z+Z{7G+Xv+Z1;3ui$vw6)5npx!WWLl9UiMRrYb#?R+I)9(kPKSx> z;!*m=h^u6~VE#TSV5)*nPO}NXqeR#RfHE$Q)EPz9=77qBF93M9-w+ zw?e0(X8`W(fm!^dLDO>%CZd_S^7>Yo%1`sEPU0|pTp3DyQ*UWz=Ud${i(f$RC=S3J zud$UrYgkD|=i{+Le<|26`(YlxfTSf*qCS*>BQgAWt;YgsKTP8nXjgj&dx>;1o`8DM zIz|^Ag<}_5t`Da33uv?8mp;zuVZV5H5JvI`n$*3pC3_i4War}x*?G30 zcRWUi`UljWhbfhh0!B7`>1QWu{^2`6tg3pk6NdT+^f>}bN`7yAAyz1qxjO)(`~!O5 zT%sIKE-osml?=Fxei-9lhTvpIQ4&VEbxe0BjPDQBTGs8xcw(hc=A7+ilVWCrnf&S&N&CDrj@LfSJNQ<2?*uM;mp;&w-{6{(G&hPg&LigJRWBmhq z_glhZYAywc!ynN);yT-Z1z@~?Kp#e5qK$x=AmzfzhJBA82K<-dHk?Ri=E4s?@bt$W zU%I)fcBvc2`(u3!;Z_HFyg;V-KLYtLfz`X{4ngljCqEWQD_hyLlt~q z032Wggtd`hk^dzBL0%`9$;;$lVJ3j*$TQ@h$lsH%lfQ*;26&u&nLG^N5cntLesV9l zi~IpOLq0-2NU~%RW&oHa(F$h{(0gv}sK$r{kN^@u0!RP}AOR$R1dsp{Kmtf$qY2QF z^6I_!U-KjY>ac$rw$so^Ljw)e|9|t_05d=WNB{{S0VIF~kN^@u0!RP}AOR$>(FE}Q|BWV$