diff --git a/Calc3D.py b/Calc3D.py new file mode 100644 index 0000000..40a49f5 --- /dev/null +++ b/Calc3D.py @@ -0,0 +1,121 @@ +import datetime +import json +import os +import requests +import PySimpleGUI as Sgi + +from calculating import calculating, amortization, cost_prise +from setts import window_setts, mk_dir_json +from text_ru import calc, about, not_connect, new_marge, ver +from update import upd_start, upd_check + +now = datetime.datetime.now() + + +def create_window(): + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json')) as file: + theme = json.load(file)['settings']['theme'] + Sgi.theme(theme) + menu_def = [ + ['File', ['Настройки'], ['Выход']], + ['Help', ['Как рассчитывается стоимость', 'Обо мне', 'Проверить обновления']], + ] + + layout = [ + [Sgi.Menu(menu_def)], + [Sgi.Txt('_' * 46)], + [Sgi.Text('0', size=(7, 1), font=('Consolas', 32), + text_color='white', key='result', auto_size_text=True, justification='right', expand_x=True), + Sgi.Text('руб.', font=('Consolas', 32), text_color='white', key='result')], + [Sgi.Text('Себестоимость:', font=12, text_color='white'), + Sgi.Text('0', size=(7, 1), font=12, text_color='white', key='cost', auto_size_text=True, + justification='right', expand_x=True), + Sgi.Text('руб.', font=('Consolas', 12), text_color='white', key='cost')], + [Sgi.Txt('_' * 46, pad=(10, 5))], + [Sgi.Text('Время печати'), Sgi.Push(), Sgi.InputText('0', size=(5, 20)), Sgi.Text('ч.'), + Sgi.InputText('0', size=(5, 0)), Sgi.Text('мин. ')], + [Sgi.Text('Вес детали'), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ), + Sgi.Text('гр. ')], + [Sgi.Text('Количество экземпляров'), Sgi.Push(), Sgi.InputText('1', size=(10, 20), justification='right', ), + Sgi.Text('шт. ')], + [Sgi.Txt('_' * 46)], + [Sgi.Text('Моделирование'), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ), + Sgi.Text('руб. ')], + [Sgi.Text('Постобработка'), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ), + Sgi.Text('руб. ')], + [Sgi.Txt('_' * 46)], + [Sgi.Txt(' ' * 15), Sgi.ReadFormButton('Расчитать', size=(10, 2)), Sgi.Cancel('Выход', size=(10, 2))] + + ] + return Sgi.Window(f'Calc3D by Risen ver.{ver}', layout, icon='logo.ico') + + +def main(): + mk_dir_json() + window = create_window() + try: + upd_start() + except requests.exceptions.ConnectionError: + Sgi.popup_ok(not_connect) + + while True: + event, values = window.read() + + if event == "Настройки": + window_setts() + window.close() + window = create_window() + + elif event == "Как рассчитывается стоимость": + Sgi.popup_ok(calc) + + elif event == "Обо мне": + Sgi.popup(about) + + elif event == "Проверить обновления": + try: + upd_check() + except requests.exceptions.ConnectionError: + Sgi.popup_ok(not_connect) + + elif event == 'Расчитать': + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json')) as file: + params = json.load(file)["settings"] + try: + hours = float(values[1]) + except ValueError: + hours = 0 + try: + minutes = float(values[2]) + except ValueError: + minutes = 0 + + if minutes > 60: + hours = hours + minutes // 60 + minutes = minutes % 60 + t = hours * 60 + minutes + + try: + md = values[3] + except ValueError: + md = 0 + + am = amortization(params['a'], t, params['spi'], now.year) # a, t, spi, year + + cost = cost_prise(params['p'], t, params['h'], md, params['d'], params['st'], params['mk'], am, + values[6], values[4]) # p, t, h, md, d, st, mk, am, post, x + + try: + result = calculating(cost, values[5], params['marge']) # cost, mod, marg + except KeyError: + Sgi.popup_ok(new_marge) + result = 0 + window.find_element('result').Update(result) + window.find_element('cost').Update(cost) + + elif event in (Sgi.WIN_CLOSED, 'Выход'): + break + + +if __name__ == "__main__": + main() diff --git a/calculating.py b/calculating.py new file mode 100644 index 0000000..bddf01b --- /dev/null +++ b/calculating.py @@ -0,0 +1,46 @@ +def cost_prise(p, t, h, md, d, st, mk, am, post, x): + p = int(p) # номинальная мощность принтера + t = int(t) # время печати, в минутах!!! + h = float(h) # тариф электроэнергии + md = float(md) # вес детали + d = float(d) # коэффициент выбраковки + st = float(st) # стоимость катушки + mk = float(mk) # вес катушки + am = float(am) # амортизация + try: + post = float(post) # постобработка + except ValueError: + post = 0 + try: + x = int(x) # количество экземпляров + except ValueError: + x = 1 + result = (p / 1000 * t / 60 * h) + (md * d * (st / mk) + am + post) * x + return round(result, 2) + + +def calculating(cost, mod, marg): + try: + mod = float(mod) # моделирование + except ValueError: + mod = 0 + try: + margin = float(marg) # процент наценки + except ValueError: + margin = 0 + result = (cost / 100 * margin + cost) + mod + return round(result, 2) + + +def amortization(a, t, spi, year): + if (year % 400 == 0) or (year % 100 != 0) and (year % 4 == 0): + minutes_in_year = 527040 / 2 + else: + minutes_in_year = 525600 / 2 + try: + year_norm = 100 / float(spi) + except ZeroDivisionError: + year_norm = 100 / 1 + year_am = float(a) / 100 * round(year_norm, 1) + am_per_minute = year_am / minutes_in_year * t + return round(am_per_minute, 2) diff --git a/logo.ico b/logo.ico new file mode 100644 index 0000000..14c2dbf Binary files /dev/null and b/logo.ico differ diff --git a/setts.py b/setts.py new file mode 100644 index 0000000..8a5f479 --- /dev/null +++ b/setts.py @@ -0,0 +1,134 @@ +import json +import PySimpleGUI as Sgi +import os.path + +from text_ru import amortization_calc, new_sets +from themes_list import themes_list + + +def mk_dir_json(): + if not os.path.exists(os.path.expanduser('~\Documents\Calc3DbyRisen')): + os.makedirs(os.path.expanduser('~\Documents\Calc3DbyRisen')) + + if not os.path.isfile(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json')): + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json'), 'w') as file: + data = {"settings": {"theme": "Dark", + "p": "270", + "h": "3", + "d": "1.5", + "st": "1500", + "mk": "1000", + "a": "0", + "spi": "3", + "marg": "0"}} + json.dump(data, file, indent=2) + + +def window_setts(): + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json')) as file: + old_data = json.load(file) + theme = old_data["settings"]["theme"] + p = old_data["settings"]["p"] + h = old_data["settings"]["h"] + d = old_data["settings"]["d"] + st = old_data["settings"]["st"] + mk = old_data["settings"]["mk"] + a = old_data["settings"]["a"] + try: + spi = old_data["settings"]["spi"] + except KeyError: + Sgi.popup_ok(new_sets) + spi = 0 + try: + marg = old_data["settings"]["marge"] + except KeyError: + marg = 0 + + layout1 = [ + [Sgi.Text("ВНИМАНИЕ! Перед установкой параметра\n'Коэффициент выбраковки' прочитайте раздел\n" + "Help, с описанием формулы расчета!\n", text_color="red")], + [Sgi.Text('Мощность принтера, Вт'), Sgi.Push(), Sgi.InputText(p, size=(10, 10), justification='right')], + [Sgi.Text('Тариф электроэнергии, кВт/ч'), Sgi.Push(), Sgi.InputText(h, size=(10, 10), justification='right')], + [Sgi.Text('Коэффициент выбраковки'), Sgi.Push(), Sgi.InputText(d, size=(10, 10), justification='right')], + [Sgi.Text('Стоимость катушки, руб.'), Sgi.Push(), Sgi.InputText(st, size=(10, 10), justification='right')], + [Sgi.Text('Вес катушки, гр.'), Sgi.Push(), Sgi.Combo(['225', '250', '450', '500', '750', '850', '1000', '2250', + '2500'], size=(8, 20), default_value=mk)], + [Sgi.Text('Наценка, %.'), Sgi.Push(), Sgi.InputText(marg, size=(10, 10), justification='right')], + [Sgi.Text('')] + ] + layout2 = [ + [Sgi.Text('Стоимость вашего принтера, руб.'), Sgi.Push(), Sgi.InputText(a, size=(10, 10), + justification='right')], + [Sgi.Text('Срок полезного использования, лет.'), Sgi.Push(), Sgi.InputText(spi, size=(10, 10), + justification='right')], + [Sgi.Text('_' * 45)], [Sgi.Text(amortization_calc)], + [Sgi.Text('')] + ] + layout3 = [ + [Sgi.Text('Оформление')], + [Sgi.Text("Выбор темы"), Sgi.Push(), Sgi.Combo(themes_list, size=(20, 20), default_value=theme)], + ] + + tab_group = [ + [Sgi.TabGroup( + [[Sgi.Tab('Основные настройки', layout1), Sgi.Tab('Амортизация', layout2), Sgi.Tab('Оформление', layout3)]] + ), [Sgi.Push(), Sgi.Button('Применить')]]] + + window = Sgi.Window("Настройки", tab_group, modal=True) + while True: + event, values = window.read() + if event == 'Применить': + if values[8] == theme: + new_theme = theme + else: + new_theme = values[8] + if values[0] == p: + new_p = p + else: + new_p = values[0] + if values[1] == h: + new_h = h + else: + new_h = values[1].replace(',', '.') + if values[2] == d: + new_d = d + else: + new_d = values[2].replace(',', '.') + if values[3] == st: + new_st = st + else: + new_st = values[3] + if values[4] == mk: + new_mk = mk + else: + new_mk = values[4] + if values[5] == marg: + new_marg = marg + else: + new_marg = values[5].replace(',', '.') + if values[6] == a: + new_a = a + else: + new_a = values[6] + if values[7] == spi: + new_spi = spi + else: + new_spi = values[7] + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json'), 'w') as file: + data = {"settings": {"theme": new_theme, + "p": new_p, + "h": new_h, + "d": new_d, + "st": new_st, + "mk": new_mk, + "a": new_a, + "spi": new_spi, + "marge": new_marg + } + } + json.dump(data, file, indent=2) + + window.close() + + if event == "Exit" or event == Sgi.WIN_CLOSED: + break diff --git a/text_ru.py b/text_ru.py new file mode 100644 index 0000000..e9c5c04 --- /dev/null +++ b/text_ru.py @@ -0,0 +1,49 @@ +calc = ("Формула расчета стоимости печати выглядит так:\n\n" + "S = ((p/1000*t/60*h)+(md*d*st/mk)+am+post))*x+mod\n\n" + "где:\n" + "S - стоимость печати, руб.\n" + "p - мощность принтера, Вт\n" + "t - время печати, мин.\n" + "h - тариф на электроэнергию, кВт/ч\n" + "md - вес детали, гр.\n" + "st - стоимость катушки пластика, руб.\n" + "mk - вес пластика в катушке, гр.\n" + "d - коэффициент выбраковки\n" + "am - амортизация, руб.\n" + "post - стоимость постобработки, руб.\n" + "х - количество печатаемых дубликатов, шт.\n" + "mod - стоимость моделирования, руб.\n\n" + "При этом в расчете вес детали, умножается на 1.5,\n" + "это сделано для выбраковки и тестовой печати," + "т.е. при калькуляции вес одной детали для печати\n" + "считается как 1,5 детали " + "Можете изменить этот пункт в настройках.\n\n") + +about = ("Программа написана потому, что мне было скучно\n" + "Использовать её или нет дело ваше, мне все равно\n" + "Распространяется по принципу 'как есть'\n" + "По вопросам и предложениям писать в телеграм на @RisenYT\n\n") + +amortization_calc = ('Как считается амортизация:\n\n' + 'Отчисления записываются \n' + 'частями в зависимости от времени \n' + 'печати конкретного изделия\n' + 'Рекомендую задавать СПИ (это время\n' + 'окупаемости принтера) 3 года.\n' + 'Калькулятор считает амортизацию в\n' + 'минуту и умножает на количество минут,\n' + 'которые принтер будет печатать.') + +not_connect = ('Невозможно проверить обновление.\n\n' + 'Отсутствует подключение к интернету\n' + 'или программа заблокирована фаерволом.\n\n' + 'Для продолжения работы нажмите "Ok"') + +new_sets = ('Задайте стоимость принтера, \n' + 'срок полезного использования\n' + 'в настройках амортизации\n') + +new_marge = ('Задайте процент желаемой наценки\n' + 'в настройках (можно просто проставить ноль)') + +ver = '0.5.3b' diff --git a/themes_list.py b/themes_list.py new file mode 100644 index 0000000..e34b7a3 --- /dev/null +++ b/themes_list.py @@ -0,0 +1,23 @@ +themes_list = ['Black', 'BlueMono', 'BluePurple', 'BrightColors', 'BrownBlue', 'Dark', 'Dark2', 'DarkAmber', + 'DarkBlack', 'DarkBlack1', 'DarkBlue', 'DarkBlue1', 'DarkBlue10', 'DarkBlue11', 'DarkBlue12', + 'DarkBlue13', 'DarkBlue14', 'DarkBlue15', 'DarkBlue16', 'DarkBlue17', 'DarkBlue2', 'DarkBlue3', + 'DarkBlue4', 'DarkBlue5', 'DarkBlue6', 'DarkBlue7', 'DarkBlue8', 'DarkBlue9', 'DarkBrown', + 'DarkBrown1', 'DarkBrown2', 'DarkBrown3', 'DarkBrown4', 'DarkBrown5', 'DarkBrown6', 'DarkBrown7', + 'DarkGreen', 'DarkGreen1', 'DarkGreen2', 'DarkGreen3', 'DarkGreen4', 'DarkGreen5', 'DarkGreen6', + 'DarkGreen7', 'DarkGrey', 'DarkGrey1', 'DarkGrey10', 'DarkGrey11', 'DarkGrey12', 'DarkGrey13', + 'DarkGrey14', 'DarkGrey15', 'DarkGrey2', 'DarkGrey3', 'DarkGrey4', 'DarkGrey5', 'DarkGrey6', + 'DarkGrey7', 'DarkGrey8', 'DarkGrey9', 'DarkPurple', 'DarkPurple1', 'DarkPurple2', 'DarkPurple3', + 'DarkPurple4', 'DarkPurple5', 'DarkPurple6', 'DarkPurple7', 'DarkRed', 'DarkRed1', 'DarkRed2', + 'DarkTanBlue', 'DarkTeal', 'DarkTeal1', 'DarkTeal10', 'DarkTeal11', 'DarkTeal12', 'DarkTeal2', + 'DarkTeal3', 'DarkTeal4', 'DarkTeal5', 'DarkTeal6', 'DarkTeal7', 'DarkTeal8', 'DarkTeal9', 'Default', + 'Default1', 'DefaultNoMoreNagging', 'GrayGrayGray', 'Green', 'GreenMono', 'GreenTan', 'HotDogStand', + 'Kayak', 'LightBlue', 'LightBlue1', 'LightBlue2', 'LightBlue3', 'LightBlue4', 'LightBlue5', + 'LightBlue6', 'LightBlue7', 'LightBrown', 'LightBrown1', 'LightBrown10', 'LightBrown11', + 'LightBrown12', 'LightBrown13', 'LightBrown2', 'LightBrown3', 'LightBrown4', 'LightBrown5', + 'LightBrown6', 'LightBrown7', 'LightBrown8', 'LightBrown9', 'LightGray1', 'LightGreen', + 'LightGreen1', 'LightGreen10', 'LightGreen2', 'LightGreen3', 'LightGreen4', 'LightGreen5', + 'LightGreen6', 'LightGreen7', 'LightGreen8', 'LightGreen9', 'LightGrey', 'LightGrey1', 'LightGrey2', + 'LightGrey3', 'LightGrey4', 'LightGrey5', 'LightGrey6', 'LightPurple', 'LightTeal', 'LightYellow', + 'Material1', 'Material2', 'NeutralBlue', 'Purple', 'Python', 'PythonPlus', 'Reddit', 'Reds', + 'SandyBeach', 'SystemDefault', 'SystemDefault1', 'SystemDefaultForReal', 'Tan', 'TanBlue', + 'TealMono', 'Topanga'] diff --git a/update.py b/update.py new file mode 100644 index 0000000..89ad178 --- /dev/null +++ b/update.py @@ -0,0 +1,82 @@ +import requests +import webbrowser +import json +import PySimpleGUI as Sgi +import os + +from text_ru import ver + + +def upd_check(): + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json')) as json_file: + data = json.load(json_file) + set_theme = data["settings"]["theme"] + + version_new = requests.get('https://risenhome.xyz/feed/Risen.json').json()["version"]["ver"] + version_old = ver + + if version_new > version_old: + + Sgi.theme(set_theme) + layout = [ + [Sgi.Text("Обновление")], + [Sgi.Text("Вышла новая версия программы\nНужно обновиться")], + [Sgi.Button(' Скачать '), Sgi.Push(), Sgi.Button(' Отмена ')] + ] + + window = Sgi.Window("Проверка обновления", layout, modal=True) + + while True: + event, button = window.read() + if event == ' Скачать ': + webbrowser.open('https://risenhome.xyz/calc.html', new=2, autoraise=True) + window.close() + elif event == ' Отмена ': + window.close() + elif event == "Exit" or event == Sgi.WIN_CLOSED: + break + else: + Sgi.theme(set_theme) + layout = [ + [Sgi.Text(f"Последняя версия: {version_new}\nВаша версия: {version_old}\n\nОбновление не требуется")], + [Sgi.Button(' Закрыть ')] + ] + + window = Sgi.Window("Проверка обновления", layout, modal=True) + + while True: + event, button = window.read() + if event == ' Закрыть ': + window.close() + elif event == "Exit" or event == Sgi.WIN_CLOSED: + break + + +def upd_start(): + with open(os.path.expanduser('~\Documents\Calc3DbyRisen\setts.json')) as json_file: + data = json.load(json_file) + set_theme = data["settings"]["theme"] + + version_new = requests.get('https://risenhome.xyz/feed/Risen.json').json()["version"]["ver"] + version_old = ver + + if version_new > version_old: + + Sgi.theme(set_theme) + layout = [ + [Sgi.Text("Обновление")], + [Sgi.Text("Вышла новая версия программы\nНужно обновиться")], + [Sgi.Button(' Скачать '), Sgi.Push(), Sgi.Button(' Отмена ')] + ] + + window = Sgi.Window("Вышла новая версия!", layout, modal=True) + + while True: + event, button = window.read() + if event == ' Скачать ': + webbrowser.open('https://risenhome.xyz', new=2, autoraise=True) + window.close() + elif event == ' Отмена ': + window.close() + elif event == "Exit" or event == Sgi.WIN_CLOSED: + break