fix: error merge

This commit is contained in:
risen 2024-04-22 14:26:40 +03:00
commit 8a2f8af09a
14 changed files with 596 additions and 3 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
/venv
/.idea
/build
/dist
Calc3D.spec

122
Calc3D.py Normal file
View File

@ -0,0 +1,122 @@
import datetime
import json
import os
import PySimpleGUI as Sgi
import gettext
import requests
from calculating import calculating, amortization, cost_prise
from setts import window_setts, language, currency_setts
from texts import calc, about, new_marge, ver, not_connect
from update import upd_check
now = datetime.datetime.now()
lang = gettext.translation('locale', localedir='locale', languages=[language()])
lang.install()
_ = lang.gettext
def create_window():
with open(os.path.expanduser('setts.json')) as f:
theme = json.load(f)['settings']['theme']
Sgi.theme(theme)
menu_def = [
[_('Файл'), [_('Настройки')], [_('Выход')]],
[_('Помощь'), [_('Как рассчитывается стоимость'), _('Обо мне'), _('Проверить обновления')]],
]
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(currency_setts(), 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(currency_setts(), 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(f'{currency_setts()} ')],
[Sgi.Text(_('Постобработка')), Sgi.Push(), Sgi.InputText('0', size=(10, 20), justification='right', ),
Sgi.Text(f'{currency_setts()} ')],
[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():
window = create_window()
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('setts.json')) as f:
params = json.load(f)["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(abs(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()

38
Calc3D.spec Normal file
View File

@ -0,0 +1,38 @@
# -*- mode: python ; coding: utf-8 -*-
a = Analysis(
['Calc3D.py'],
pathex=[],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.datas,
[],
name='Calc3D',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
icon=['test.ico'],
)

View File

@ -6,4 +6,4 @@ Permission is hereby granted, free of charge, to any person obtaining a copy of
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,2 +0,0 @@
# Calc3D_by_Risen

49
calculating.py Normal file
View File

@ -0,0 +1,49 @@
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) # вес детали
if float(d) < 1:
d = 1
else:
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 = ((abs(p) / 1000) * (abs(t) / 60) * abs(h) * abs(x)) + (abs(md) * abs(d) * (abs(st) / abs(mk) * abs(x)) + abs(am) + abs(post) * abs(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)

26
lists.py Normal file
View File

@ -0,0 +1,26 @@
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']
lang_list = ['Русский', 'English']
currency_list = ['руб.', '$', '']

Binary file not shown.

Binary file not shown.

BIN
logo.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 227 KiB

15
setts.json Normal file
View File

@ -0,0 +1,15 @@
{
"settings": {
"theme": "Dark",
"p": "270",
"h": "3",
"d": "0",
"st": "1500",
"mk": "1000",
"a": "0",
"spi": "0",
"marge": "0",
"locale": "Ru",
"currency": "\u0440\u0443\u0431."
}
}

174
setts.py Normal file
View File

@ -0,0 +1,174 @@
import json
import PySimpleGUI as Sgi
import gettext
import os
from texts import amortization_calc, new_sets
from lists import themes_list, lang_list, currency_list
def language():
with open(os.path.expanduser('setts.json')) as file:
old_data = json.load(file)
if old_data['settings']["locale"] == 'English':
locale = 'en_US'
else:
locale = 'ru_RU'
return locale
lang = gettext.translation('locale', localedir='locale', languages=[language()])
lang.install()
_ = lang.gettext
def currency_setts():
with open('setts.json') as file:
old_data = json.load(file)
try:
if old_data['settings']["currency"] == 'руб.':
currency = 'руб.'
elif old_data['settings']["currency"] == '$':
currency = '$'
else:
currency = ''
except KeyError:
if old_data['settings']["locale"] == "рус.":
currency = 'руб.'
else:
currency = '$'
return currency
def window_setts():
with open('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"]
locale = old_data['settings']["locale"]
try:
currency = old_data['settings']["currency"]
except KeyError:
currency = "руб."
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(_('Стоимость катушки, ')+f'{currency_setts()}'), 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(_('Стоимость вашего принтера, ')+f'{currency_setts()}'), 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)],
[Sgi.Text(_("Язык")), Sgi.Push(), Sgi.Combo(lang_list, size=(20, 20), default_value=locale)],
[Sgi.Text(_("Валюта")), Sgi.Push(), Sgi.Combo(currency_list, size=(20, 20), default_value=currency_setts())],
]
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[9] == locale:
new_locale = locale
else:
new_locale = values[9]
if values[10] == currency:
new_currency = currency
else:
new_currency = values[10]
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('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,
"locale": new_locale,
"currency": new_currency
}
}
json.dump(data, file, indent=2)
window.close()
if event == "Exit" or event == Sgi.WIN_CLOSED:
break

76
texts.py Normal file
View File

@ -0,0 +1,76 @@
import gettext
import json
import os
if not os.path.isfile('setts.json'):
with open('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",
"locale": "Ru",
"currency": "руб."}}
json.dump(data, file, indent=2)
with open('setts.json') as file:
old_data = json.load(file)
if old_data['settings']["locale"] == 'English':
locale = 'en_US'
else:
locale = 'ru_RU'
lang = gettext.translation('locale', localedir='locale', languages=[locale])
lang.install()
_ = lang.gettext
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 = (_("По вопросам и предложениям писать в телеграм на @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.6.4'

90
update.py Normal file
View File

@ -0,0 +1,90 @@
import requests
import webbrowser
import json
import PySimpleGUI as Sgi
import gettext
from texts import ver
from setts import language
lang = gettext.translation('locale', localedir='locale', languages=[language()])
lang.install()
_ = lang.gettext
def upd_check():
with open('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Ваша версия: ')+f'{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('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