Программа "Анализатор выборки"

Программа должна определять количественные соотношения диапазонов значений в указанной последовательности.

Основное окно программы

Интерфейс программы на Python "Анализатор выборки"

Генератор выборки

Интерфейс генератора выборки

Исходный код

# Версия для Python 3.
 
#Программа "Анализатор выборки" подготовлена для ученического проекта.
#Не содержит код для обработки ошибок ввода пользователя.
#Автор: Светлана Шапошникова (http://pythoner.name).
#Программа распространяется по условиям GNU General Public License.
 
######################### ФУНКЦИИ ИНТЕРФЕЙСА ##################
# Блокировка радиокнопок-тип_данных.
# Вызывается из func_check_type при снятии флажка.
# Вызывается из clear_interface, чтобы не дублировать код.
def check_type_lock():
    button_analysis.config(state=NORMAL)
    radio_int.config(state=DISABLED)
    radio_float.config(state=DISABLED)
    radio_symb.config(state=DISABLED)
    radio_word.config(state=DISABLED)
    label_accuracy.config(state=DISABLED)
    entry_accuracy.config(state=DISABLED)
    var_radio_type.set(4)
 
def func_check_type():
    if var_check_type.get() == 1:
        label_autoformat.config(text='')
        button_analysis.config(state=DISABLED)
        radio_symb.config(state=NORMAL)
        radio_word.config(state=NORMAL)
        if var_format == 'Целые числа' or var_format == 'Вещественные числа':
            radio_int.config(state=NORMAL)
            radio_float.config(state=NORMAL)
        if var_radio_type.get() == 1:
            label_accuracy.config(state=NORMAL)
            entry_accuracy.config(state=NORMAL)
    else:
        check_type_lock()
        func_analysis()
 
# Блокирует виджеты в зависимости от типа данных.
# Вызывается из func_analysis (при автоматическом определении типа).
# Вызывается из func_radio_type (при ручном определении типа).
# Вызывается из clear_interface, чтобы не дублировать код.
def func_type_lock(a):
    l_min.config(state=a)
    label_min.config(state=a)
    l_max.config(state=a)
    label_max.config(state=a)
    check_min.config(state=a)
    check_max.config(state=a)
    var_check_min.set(0)
    var_check_max.set(0)
    entry_min.config(state=DISABLED)
    entry_max.config(state=DISABLED)
    l_range.config(state=a)
    radio_range_size.config(state=a)
    radio_range_qty.config(state=a)
    radio_range_manually.config(state=a)
    label_qty_range.config(state=a)
    entry_qty_range.config(state=a)
    var_radio_range.set(1)
    label_size.config(state=DISABLED)
    entry_size.config(state=DISABLED)
    label_size_from.config(state=DISABLED)
    entry_size_from.config(state=DISABLED)
    label_size_to.config(state=DISABLED)
    entry_size_to.config(state=DISABLED)
    button_addrange.config(state=DISABLED)
    button_delete.config(state=DISABLED)
    list_range.config(state=DISABLED, bg='lightgray')
    label_accuracy.config(state=DISABLED)
    entry_accuracy.config(state=DISABLED)
 
# Переопределяет список данных, если пользователь указывает тип вручную.
def func_radio_type():
    string = text_data.get(1.0,END)
    string = string.split()
    global sample
    sample = []
    global var_format
    if var_radio_type.get() == 0:
        var_format = 'Целые числа'
        for i in string:
            i = int(round(float(i)))
            sample.append(i)
        func_type_lock(NORMAL) 
    elif var_radio_type.get() == 1:
        var_format = 'Вещественные числа'
        for i in string:
            i = float(i)
            sample.append(i)
        func_type_lock(NORMAL) 
        label_accuracy.config(state=NORMAL)
        entry_accuracy.config(state=NORMAL)
    elif var_radio_type.get() == 2:
        var_format = 'Символы'
        sample = text_data.get(1.0,END)
        func_type_lock(DISABLED)          
    elif var_radio_type.get() == 3:
        var_format = 'Слова'
        for i in string:
                sample.append(i)
        func_type_lock(DISABLED) 
    len_min_max(sample)
 
def func_check_min():
    if var_check_min.get() == 1:
        entry_min.config(state=NORMAL)
        label_min.config(state=DISABLED)
    else:
        entry_min.config(state=DISABLED)
        label_min.config(state=NORMAL)
 
def func_check_max():
    if var_check_max.get() == 1:
        entry_max.config(state=NORMAL)
        label_max.config(state=DISABLED)
    else:
        entry_max.config(state=DISABLED)
        label_max.config(state=NORMAL)
 
# Блокировка виджет в зависимости от способа формирования диапазонов
def func_radio_range():
    def disabled():
        label_size_from.config(state=DISABLED)
        entry_size_from.config(state=DISABLED)
        label_size_to.config(state=DISABLED)
        entry_size_to.config(state=DISABLED)
        button_addrange.config(state=DISABLED)
        button_delete.config(state=DISABLED)
        list_range.config(state=DISABLED,bg='lightgray')
    if var_radio_range.get() == 0:
        label_size.config(state=NORMAL)
        entry_size.config(state=NORMAL)
        label_qty_range.config(state=DISABLED)
        entry_qty_range.config(state=DISABLED)
        disabled()
    elif var_radio_range.get() == 1:
        label_size.config(state=DISABLED)
        entry_size.config(state=DISABLED)
        label_qty_range.config(state=NORMAL)
        entry_qty_range.config(state=NORMAL)
        disabled()
    elif var_radio_range.get() == 2:
        label_size.config(state=DISABLED)
        entry_size.config(state=DISABLED)
        label_qty_range.config(state=DISABLED)
        entry_qty_range.config(state=DISABLED)
        label_size_from.config(state=NORMAL)
        entry_size_from.config(state=NORMAL)
        label_size_to.config(state=NORMAL)
        entry_size_to.config(state=NORMAL)
        button_addrange.config(state=NORMAL)
        button_delete.config(state=NORMAL)
        list_range.config(state=NORMAL,bg='white')
 
def clear_interface():    
    # поля надо привести в нормальное состояние, иначе не очистить
    entry_accuracy.config(state=NORMAL)
    entry_min.config(state=NORMAL)
    entry_max.config(state=NORMAL)
    entry_size.config(state=NORMAL)
    entry_qty_range.config(state=NORMAL)
    entry_size_from.config(state=NORMAL)
    entry_size_to.config(state=NORMAL)
    list_range.config(state=NORMAL)
 
    label_autoformat.config(text='#####')
    var_check_type.set(0)
    label_qty.config(text='#####')
    label_min.config(text='#####')
    label_max.config(text='#####')
    entry_accuracy.delete(0, END)
    entry_min.delete(0, END)
    entry_max.delete(0, END)
    entry_size.delete(0, END)
    entry_qty_range.delete(0, END)
    entry_size_from.delete(0, END)
    entry_size_to.delete(0, END)
    list_range.delete(0, END)
    check_type.config(state=DISABLED)
    check_type_lock()
    func_type_lock(NORMAL)    
    text_result.delete(1.0,END)
    canvas.delete('all')
    button_analysis.focus_set()
 
################ ИНТЕРФЕЙС  ##########################
from tkinter import *
from tkinter.filedialog import *
import random
import math
 
win = Tk()
win.title('Анализатор выборки')
win.geometry('+50+50')
win.resizable(False,False)
 
Frame(bg='darkgray',width=546,height=30).grid(row=0,column=0,columnspan=10)
Label(text="Ввод данных и диапазонов",font="Arial 12",bg='darkgray').grid(row=0,column=0,columnspan=10)
 
Label(text='Признак:').grid(row=1,column=0,padx=10,pady=10,sticky=E)
entry_sing = Entry(width=25)
entry_sing.grid(row=1,column=1,columnspan=9,sticky=W)
 
Label(text='Выборка/данные:').grid(row=2,column=0,sticky=E,padx=10)
button_upload = Button(text='Загрузить')
button_upload.grid(row=3,column=0,padx=10,sticky=E+S)
button_generate = Button(text='Сгенерировать')
button_generate.grid(row=4,column=0,padx=10,sticky=E+N)
button_analysis = Button(text='Обработать')
button_analysis.grid(row=5,rowspan=8,column=0,padx=10,sticky=E+N)
text_data = Text(height=8,width=40)
text_data.grid(row=2,column=1,rowspan=10,columnspan=4,sticky=W)
scroll_data = Scrollbar(command=text_data.yview)
scroll_data.grid(row=2,column=5,rowspan=10,sticky=NS+W)
text_data.config(yscrollcommand=scroll_data.set)
Frame(height=10).grid(row=12,column=0)
Label(text='Тип данных:').grid(row=13,column=0,padx=10,sticky=E)
label_autoformat = Label(text='#####',width=20,bg='white')
label_autoformat.grid(row=13,column=1,columnspan=2,sticky=W)
var_check_type = IntVar()
check_type = Checkbutton(text="Указать",variable=var_check_type,command=func_check_type, state=DISABLED)
check_type.grid(row=13,column=3,columnspan=7,sticky=W)
var_radio_type = IntVar()
var_radio_type.set(4)
radio_int = Radiobutton(text="Целые числа",variable=var_radio_type,value=0,state=DISABLED,command=func_radio_type)
radio_float = Radiobutton(text="Вещественные числа",variable=var_radio_type,value=1,state=DISABLED,command=func_radio_type)
radio_symb = Radiobutton(text="Символы",variable=var_radio_type,value=2,state=DISABLED,command=func_radio_type)
radio_word = Radiobutton(text="Слова",variable=var_radio_type,value=3,state=DISABLED,command=func_radio_type)
radio_int.grid(row=14,column=1,columnspan=4,sticky=W)
radio_float.grid(row=15,column=1,columnspan=4,sticky=W)
radio_symb.grid(row=16,column=1,columnspan=4,sticky=W)
radio_word.grid(row=17,column=1,columnspan=4,sticky=W)
label_accuracy = Label(text='Точность:',state=DISABLED)
label_accuracy.grid(row=15,column=4,sticky=W)
entry_accuracy = Entry(width=3,state=DISABLED)
entry_accuracy.grid(row=15,column=5,columnspan=3,sticky=W)
 
Label(text='Количество элементов:').grid(row=18,column=0,ipady=10,ipadx=10,sticky=E)
label_qty = Label(text='#####',width=10,bg='white')
label_qty.grid(row=18,column=1,sticky=W)
 
l_min = Label(text='Минимум:')
l_min.grid(row=19,column=0,sticky=E,ipadx=10)
label_min = Label(text='#####',width=10,bg='white')
label_min.grid(row=19,column=1,sticky=W)
var_check_min = IntVar()
check_min = Checkbutton(text="Указать",variable=var_check_min,command=func_check_min)
check_min.grid(row=19,column=2,sticky=W)
entry_min = Entry(width=10,state=DISABLED)
entry_min.grid(row=19,column=3,columnspan=2,sticky=W)
 
l_max = Label(text='Максимум:')
l_max.grid(row=20,column=0,sticky=E,ipadx=10,ipady=10)
label_max = Label(text='#####',width=10,bg='white')
label_max.grid(row=20,column=1,sticky=W)
var_check_max = IntVar()
check_max = Checkbutton(text="Указать",variable=var_check_max,command=func_check_max)
check_max.grid(row=20,column=2,sticky=W)
entry_max = Entry(width=10,state=DISABLED)
entry_max.grid(row=20,column=3,columnspan=2,sticky=W)
 
Frame(bg='lightgray',width=550,height=5).grid(row=21,column=0,columnspan=10,pady=10)
l_range = Label(text='Способ формирования диапазонов:')
l_range.grid(row=22,column=0,columnspan=2,sticky=E,padx=10)
var_radio_range = IntVar()
var_radio_range.set(1)
radio_range_size = Radiobutton(text="Длина одного диапазона",variable=var_radio_range,value=0,command=func_radio_range)
radio_range_qty = Radiobutton(text="Количество диапазонов",variable=var_radio_range,value=1,command=func_radio_range)
radio_range_manually = Radiobutton(text="Вручную",variable=var_radio_range,value=2,command=func_radio_range)
radio_range_size.grid(row=23,column=2,columnspan=6,sticky=W)
radio_range_qty.grid(row=22,column=2,columnspan=6,sticky=W)
radio_range_manually.grid(row=24,column=2,columnspan=6,sticky=W)
 
label_size = Label(text='Длина диапазона:',state=DISABLED)
label_size.grid(row=26,column=0,sticky=E,padx=10,pady=10)
entry_size = Entry(width=10,state=DISABLED)
entry_size.grid(row=26,column=1,columnspan=2,sticky=W)
label_qty_range = Label(text='Количество диапазонов:')
label_qty_range.grid(row=25,column=0,sticky=E,padx=10)
entry_qty_range = Entry(width=10)
entry_qty_range.grid(row=25,column=1,columnspan=2,sticky=W)
Frame(height=10).grid(row=28,column=0)
label_size_from = Label(text='От:',state=DISABLED)
label_size_from.grid(row=29,column=0,sticky=E,padx=10)
entry_size_from = Entry(width=10,state=DISABLED)
entry_size_from.grid(row=29,column=1,sticky=W)
label_size_to = Label(text='До:',state=DISABLED)
label_size_to.grid(row=30,column=0,sticky=E,padx=10)
entry_size_to = Entry(width=10,state=DISABLED)
entry_size_to.grid(row=30,column=1,sticky=W)
button_addrange = Button(text='Добавить',state=DISABLED)
button_addrange.grid(row=31,column=1,sticky=W)
button_delete = Button(text='Удалить',state=DISABLED)
button_delete.grid(row=32, column=1,sticky=W)
list_range = Listbox(height=7,width=15,state=DISABLED,bg='lightgray')
list_range.grid(row=29,column=2,columnspan=2,rowspan=19)
scroll_range = Scrollbar(command=list_range.yview)
scroll_range.grid(row=29,column=4,rowspan=19,sticky=NS+W)
list_range.config(yscrollcommand=scroll_range.set)
 
Frame(height=10).grid(row=48,column=0)
Frame(width=546,height=50,bg='darkgray').grid(row=49,column=0,columnspan=10)
button_make = Button(width=15,text='Вычислить')
button_make.grid(row=49,column=0,columnspan=10)
 
Frame(width=15,height=775,bg='darkgray').grid(row=0,column=10,rowspan=50)
 
Frame(width=550,height=30).grid(row=0,column=11,columnspan=9)
Frame(bg='darkgray',width=546,height=30).grid(row=0,column=11,columnspan=9)
Label(text="Результат",bg='darkgray',font="Arial 12").grid(row=0,column=11,columnspan=9)
 
labal_range_view = Label(text="Диапазон").grid(row=1,column=14)
Label(text="Количество(шт.)").grid(row=1,column=15)
Label(text="Проценты(%)").grid(row=1,column=16)
text_result = Text(height=16,width=50)
text_result.grid(row=2,column=14,rowspan=15,columnspan=3,sticky=N)
scroll_result = Scrollbar(command=text_result.yview)
scroll_result.grid(row=2,column=17,rowspan=15,sticky=NS+W)
text_result.config(yscrollcommand=scroll_result.set)
 
canvas = Canvas(width=500,height=360,bg='white')
canvas.grid(row=18,column=11,rowspan=31,columnspan=9,sticky=N)
 
Frame(width=546,height=50,bg='darkgray').grid(row=49,column=11,columnspan=9)
button_savetxt = Button(text='Сохранить данные')
button_savetxt.grid(row=49,column=11,columnspan=4,sticky=E)
button_savegraph = Button(text='Сохранить рисунок')
button_savegraph.grid(row=49,column=15,columnspan=3,sticky=W)
button_about = Button(text='About&Help',font='Times 10')
button_about.grid(row=49,column=16,sticky=E,columnspan=4,padx=4)
 
################ РАБОТА ПРОГРАММЫ ######################
def func_fileload(): # загрузка данных из файла в текстовое поле
    fname = askopenfilename()
    ffile = open(fname,'r')
    text_data.delete(0.1,END)
    global string
    for i in ffile:
        text_data.insert(END,i)
        string = i
    clear_interface()
button_upload.config(command=func_fileload)
 
def len_min_max(sample):
    length = len(sample)
    label_qty.config(text=str(length))
    if var_format != 'Символы' and var_format != 'Слова':
        global minimum
        minimum = min(sample)
        global maximum
        maximum = max(sample)
        label_min.config(text=str(minimum))
        label_max.config(text=str(maximum))
 
def func_analysis(): # анализ данных из текстового поля
    check_type.config(state=NORMAL)
    string = text_data.get(1.0,END)
    string = string.split()
    global var_format
    global sample 
    sample = [] # список значений
    try:
        for i in string:
            i = int(i)
            sample.append(i)
        var_format = 'Целые числа'
        func_type_lock(NORMAL) 
    except:
        try:
            for i in string:
                i = float(i)
                sample.append(i)
            var_format = 'Вещественные числа'
            func_type_lock(NORMAL) 
        except:
            func_type_lock(DISABLED) 
            if len(string) < 3:
                var_format = 'Символы'
                sample = text_data.get(1.0,END)
            else:
                for i in string:
                    sample.append(i)
                var_format = 'Слова'   
    label_autoformat.config(text=var_format)
    len_min_max(sample)
button_analysis.config(command=func_analysis)
 
def func_color(): # случайный цвет
    r = int(random.random() * 100)+155
    g = int(random.random() * 100)+155
    b = int(random.random() * 100)+155
    rgb = "#%02x%02x%02x" % (r,g,b)# перевод десятичного представления
    return rgb                     # в шестнадцатеричное
 
def make_analysis(uranges): # анализ элементов выборки целых и дробных чисел на принадлежность диапазонам
    analysis = [] # количество значений в диапазонах
    length = len(uranges) # сколько диапазонов
    i = 0
    while i < length: # Колич. значений в каждом диапазоне...
        analysis.append(0) # устанавливается в 0.
        i += 1
    for i in sample: # Проверка каждого элемента в списке значений...
        j = 0
        for k in uranges: # на принадлежность к каждому диапазону.
            if k[0] <= i <= k[1]:
                analysis[j] = analysis[j] + 1
                #break элемент может входить в несколько диапазонов
            j += 1 # переход к следующему диапазону
    return analysis
 
def func_result(analysis,uranges=None,minimum=None,maximum=None): # обработка и вывод результатов
    text_result.delete(1.0,END)
    canvas.delete('all')
    canvas.create_text(2,2,text='Проценты',anchor='nw')
    canvas.create_text(498,358,text=entry_sing.get(),anchor='se')
    canvas.create_line(20,358,20,20)
    canvas.create_line(2,320,490,320)
    if var_format == 'Целые числа':
        size_one = 400 / (maximum - minimum + 1) # сколько единиц холста приходится на каждую точку диапазона
    elif var_format == 'Вещественные числа':
        size_one = (400 / (maximum - minimum))  * 1/(10**accuracy) 
    elif var_format == 'Слова' or var_format == 'Символы':
        size_one = 400 / len(analysis)
    size_pct = 300 / 100 # сколько единиц холста приходится на один процент
    k = 0
    if var_format == 'Целые числа' or var_format == 'Вещественные числа': 
        for i,j in uranges: 
            pct = round((analysis[k]/len(sample))*100,accuracy)
            index=float(str(k+1)+'.0')
            text_result.insert(index,str(round(i,accuracy))+'-'+str(round(j,accuracy)))
            l = len(str(i)+'-'+str(j))
            space = ' ' *(20-l)
            text_result.insert(END,space+str(analysis[k]))
            l = len(str(analysis[k]))
            space = ' ' * (40 - 20 - l)
            l = len(str(pct))
            space2 = ' ' * (50 - 40 - l)
            text_result.insert(END,space+str(round(pct, accuracy))+space2+'\n')
            color = func_color()
            text_result.tag_add(str(i),str(k+1)+'.0',str(k+1)+'.end')
            text_result.tag_config(str(i),background=color)
            k += 1
            if var_format == "Целые числа":
                x1 = 20 + size_one * (i - minimum)
                x2 = 20 + size_one * (j - minimum) + size_one-1      
            elif var_format == 'Вещественные числа':
                x1 = 20 + size_one * (i/(1/(10**accuracy)) - minimum/(1/(10**accuracy)))
                x2 = 20 + size_one * (j/(1/(10**accuracy)) - minimum/(1/(10**accuracy))) - 1
            canvas.create_rectangle(x1,320-pct*size_pct,x2,320,fill=color)
            canvas.create_text(x1,330,text=str(i),anchor='w',font='Times 10')
    elif var_format == 'Слова' or var_format == 'Символы':
        x1 = 20
        for i in analysis: 
            pct = round((analysis[i]/len(sample))*100,2)
            index=float(str(k+1)+'.0')
            text_result.insert(index,str(i))
            l = len(str(i))
            space = ' ' *(20-l)
            text_result.insert(END,space+str(analysis[i]))
            l = len(str(analysis[i]))
            space = ' ' * (40 - 20 - l)
            l = len(str(pct))
            space2 = ' ' * (50 - 40 - l)
            text_result.insert(END,space+str(pct)+space2+'\n')
            color = func_color()
            text_result.tag_add(str(i),str(k+1)+'.0',str(k+1)+'.end')
            text_result.tag_config(str(i),background=color)
            k += 1
            x2 = x1 + size_one - 1
            canvas.create_rectangle(x1,320-pct*size_pct,x2,320,fill=color)
            canvas.create_text(x1,330,text=str(i),anchor='w',font='Times 10')
            x1 = x2 + 1
    y = 320
    i = 20
    while y > 50:
        y = y - 20 * size_pct
        canvas.create_text(10,y,text=str(i),font='Times 8')
        canvas.create_line(20,y,480,y,fill='gray',width=1)
        i += 20
 
def func_integers(): # определение диапазонов для целых чисел
    global accuracy
    accuracy = 3
    def make_urange(urange,uranges): # заполняет список диапазонов
        i = minimum
        while i <= maximum:
            l = []
            l.append(i)
            i = i + urange
            if i <= maximum:
                l.append(i-1)
            else:
                i = maximum + 1
                l.append(maximum)
            uranges.append(l)
    uranges = []
    if var_radio_range.get() == 0:
        urange=int(entry_size.get())
        make_urange(urange,uranges)
    elif var_radio_range.get() == 1:
        qty_range = int(entry_qty_range.get())
        urange=round((maximum-minimum+1)/qty_range)
        make_urange(urange,uranges)
    elif var_radio_range.get() == 2:
        a = list_range.get(0,END)
        for i in a:
            i = i.split()
            i[0] = int(i[0])
            i[1] = int(i[1])
            uranges.append(i)
    analysis = make_analysis(uranges)
    func_result(analysis,uranges,minimum,maximum)
 
def func_floats(): # определение диапазонов для вещественных чисел
    global accuracy
    try:
        accuracy = int(entry_accuracy.get())
    except:
        accuracy = 3
    def make_urange(urange,uranges): # заполняет список диапазонов
        i = minimum
        while i <= maximum:
            l = []
            l.append(round(i,accuracy))
            i = i + urange
            if i <= maximum:
                l.append(round((i-1/(10**accuracy)),accuracy))
            else:
                i = maximum + 1
                l.append(round(maximum,accuracy))
            uranges.append(l)
    uranges = []
    if var_radio_range.get() == 0:
        urange=float(entry_size.get())
        make_urange(urange,uranges)
    elif var_radio_range.get() == 1:
        qty_range = int(entry_qty_range.get())
        urange=(maximum-minimum)/qty_range
        make_urange(urange,uranges)
    elif var_radio_range.get() == 2:
        a = list_range.get(0,END)
        for i in a:
            i = i.split()
            i[0] = float(i[0])
            i[1] = float(i[1])
            uranges.append(i)
    analysis = make_analysis(uranges)
    func_result(analysis,uranges,minimum,maximum)
 
def func_words_symbols(): # определение количества встречаемости слов или символов
    analysis = {} # количество каждого слова
    for i in sample:
        if i in analysis:
            analysis[i] += 1
        else:
            analysis[i] = 1
    func_result(analysis)
 
def what_func(): # выбор вызываемой функции в зависимости от типа данных
    global minimum
    global maximum
    if var_format == 'Целые числа':
        if var_check_min.get() == 1:
            minimum = int(entry_min.get())
        if var_check_max.get() == 1:
            maximum = int(entry_max.get())
        func_integers()
    elif var_format == 'Вещественные числа':
        if var_check_min.get() == 1:
            minimum = float(entry_min.get())
        if var_check_max.get() == 1:
            maximum = float(entry_max.get())
        func_floats()
    elif var_format == 'Слова' or var_format == 'Символы':
        func_words_symbols()
button_make.config(command=what_func)
 
def func_addrange():
    a = entry_size_from.get() + ' ' + entry_size_to.get()
    list_range.insert(END,a)
    entry_size_from.delete(0,END)
    entry_size_to.delete(0,END)
    entry_size_from.focus_set()
button_addrange.config(command=func_addrange)
def func_delrange():
    list_range.delete(ACTIVE)
button_delete.config(command=func_delrange)
 
def func_savetxt():
    fname = asksaveasfilename(defaultextension='.txt')
    ffile = open(fname,'w')
    entry = entry_sing.get() + '\n'
    sing = 'Диапазон            '+'Количество          '+'Проценты(%)\n' 
    result =entry + sing + text_result.get(1.0,END)
    ffile.write(result)
    ffile.close()
button_savetxt.config(command=func_savetxt)
 
def func_saveimg():
    fname = asksaveasfilename(defaultextension='.ps')
    canvas.update()
    canvas.postscript(file=fname,colormode='color')
button_savegraph.config(command=func_saveimg)
 
################ ГЕНЕРАТОР ####################
def generator():
 
    def list_random_integers():
        qty = int(entry_qty.get())
        minimum = int(entry_from.get())
        maximum = int(entry_to.get())
        sample = []
 
        if var_prob.get() == 0:
            for i in range(qty):
                sample.append(int(random.random() * (maximum - minimum + 1)) + minimum)
        else:    
            choice = int(random.random() * 2)  # получаем либо ноль, либо единицу
            if choice == 0:
                qty_range = int(random.random() * 4) + 3 # количество диапазонов от 3 до 6
                size_qty = int((maximum - minimum + 1) / qty_range) # размер диапазона
                x = qty
                lower = minimum # нижняя граница диапазона
                for i in range(qty_range-1):
                    n = int(x*random.random()) # количество элементов в текущем диапазоне
                    x = x - n # сколько элементов осталось для других диапазонов
                    upper = lower + size_qty - 1 # верхняя граница диапазона
                    for i in range(n):
                        b = int(random.random() * (upper - lower + 1)) + lower
                        sample.append(b)
                    lower = upper + 1
                for i in range(x): # для последнего диапазона
                    b = int(random.random() * (maximum - lower + 1)) + lower
                    sample.append(b) 
            else:
                def my_random(m):
                    n = math.sin(random.random() * m) # m - коэффициент смещения
                    n = int(n * (maximum - minimum + 1)) + minimum
                    return n
                coef  = [0.85, 0.9,  1, 1.1, 1.2, 1.3, 1.4, 1.5]
                r = int(random.random() * 8) # случайный индекс 
                r = coef[r] # извлекаем коэффициент
                for i in range(qty):
                    sample.append(my_random(r))                
 
        return sample
 
    def list_random_floats():
        qty = int(entry_qty.get())
        minimum = float(entry_from.get())
        maximum = float(entry_to.get())
        sample = []
        if var_prob.get() == 0:
            for i in range(qty):
                num = random.random() * (maximum - minimum) + minimum
                num = round(num,3)
                sample.append(num)
        else:     
            choice = int(random.random() * 2)  # получаем либо ноль, либо единицу
            if choice == 0:           
                qty_range = int(random.random() * 4) + 3 # количество диапазонов от 3 до 6
                size_qty = (maximum - minimum) / qty_range # размер диапазона
                x = qty
                lower = minimum # нижняя граница диапазона
                for i in range(qty_range-1):
                    n = int(x*random.random()) # количество элементов в текущем диапазоне
                    x = x - n # сколько элементов осталось для других диапазонов
                    upper = lower + size_qty - 0.001 # верхняя граница диапазона
                    for i in range(n):
                        b = random.random() * (upper - lower) + lower
                        b = round(b, 3)
                        sample.append(b)
                    lower = upper + 0.001
                for i in range(x): # для последнего диапазона
                    b = random.random() * (maximum - lower ) + lower
                    b = round(b, 3)
                    sample.append(b)
            else:
                def my_random(m):
                    n = math.sin(random.random() * m) # m - коэффициент смещения
                    n = n * (maximum - minimum) + minimum
                    n = round(n, 3)
                    return n
                coef  = [0.85, 0.9,  1, 1.1, 1.2, 1.3, 1.4, 1.5]
                r = int(random.random() * 8) # случайный индекс 
                r = coef[r] # извлекаем коэффициент
                for i in range(qty):
                    sample.append(my_random(r))                
 
        return sample
 
    def str_random_symbols():
        qty = int(entry_qty.get())
        variant = int(entry_variant.get())
        symbols = ''
        for i in range(qty):
            num = int(random.random() * variant) + 97
            symbols = symbols + chr(num)
        return symbols
 
    def list_random_strings():
        qty = int(entry_qty.get())
        variant = int(entry_variant.get())
        sample = []
        words = []
        for i in range(variant):
            string = ''
            num = int(random.random() * 5) + 1 #случайная длина слова от одного символа до 6
            j = 0
            while j < num:
                char = chr(int(random.random() * 22) + 97)
                string = string + char
                j += 1
            words.append(string)
        for i in range(qty):
            num = int(random.random() * variant)  # случайный индекс 
            sample.append(words[num])
        return sample    
 
    def get_sample():
        if var_type.get() == 0:
            sample = list_random_integers()
        elif var_type.get() == 1:
            sample = list_random_floats()
        elif var_type.get() == 2:
            sample = str_random_symbols()
        elif var_type.get() == 3:
            sample = list_random_strings()
        text_data.delete(0.1,END)
        if var_type.get() != 2:
            for i in sample:
                text_data.insert(END,str(i)+' ')
        else:
            text_data.insert(END,sample)
        wg.destroy()
        clear_interface()
 
    def interface():
        if 0 <= var_type.get() <= 1:
            lab_range.config(state=NORMAL)
            lab_max.config(state=NORMAL)
            lab_min.config(state=NORMAL)
            entry_from.config(state=NORMAL)
            entry_to.config(state=NORMAL)
            lab_word.config(state=DISABLED)
            entry_variant.config(state=DISABLED)  
            lab_probability.config(state=NORMAL)  
            equ_radio.config(state=NORMAL)
            nonequ_radio.config(state=NORMAL)
        else:
            lab_range.config(state=DISABLED)
            lab_max.config(state=DISABLED)
            lab_min.config(state=DISABLED)
            entry_from.config(state=DISABLED)
            entry_to.config(state=DISABLED)
            lab_word.config(state=NORMAL)
            entry_variant.config(state=NORMAL)  
            lab_probability.config(state=DISABLED)  
            equ_radio.config(state=DISABLED)
            nonequ_radio.config(state=DISABLED)            
 
    wg = Toplevel()
 
    wg.title('Генератор последовательностей')
    wg.geometry('+200+200')
    wg.resizable(False,False)
 
    Label(wg,text='Количество элементов', justify=RIGHT).grid(row=0, column=0, sticky=E, padx=10, pady=10)
    Label(wg,text='Тип элементов', justify=RIGHT).grid(row=1, column=0, sticky=E, padx=10)
    Frame(wg, height=10).grid(row=5, column=0)
    lab_range = Label(wg,text='Диапазон', justify=RIGHT)
    lab_range.grid(row=6, column=0, sticky=E, padx=10)
    lab_word = Label(wg,text='Количество различных\nсимволов или слов', justify=RIGHT, state=DISABLED)
    lab_word.grid(row=8, column=0,  sticky=E, padx=10)
    Frame(wg, height=10).grid(row=9, column=0)
    lab_probability = Label(wg,text='Частота встречаемости\nэлементов', justify=RIGHT)
    lab_probability.grid(row=10, column=0, rowspan=2,sticky=N+E, padx=10)
    Button(wg, text='Сгенерировать', command=get_sample).grid(row=12, column=0, columnspan=4, pady=10)
    entry_qty = Entry(wg,width=10, bg='white')
    entry_qty.grid(row=0, column=1,columnspan=2,sticky=W)
    var_type = IntVar()
    var_type.set(0)
    int_type = Radiobutton(wg,text="Целые числа",variable=var_type,value=0, command=interface)
    float_type = Radiobutton(wg,text="Вещественные числа",variable=var_type,value=1, command=interface)
    symb_type = Radiobutton(wg,text="Символы",variable=var_type,value=2, command=interface)
    word_type = Radiobutton(wg,text="Слова",variable=var_type,value=3, command=interface)
    int_type.grid(row=1, column=1, columnspan=2, sticky=W)
    float_type.grid(row=2, column=1, columnspan=2, sticky=W)
    symb_type.grid(row=3, column=1, columnspan=2, sticky=W)
    word_type.grid(row=4, column=1, columnspan=2, sticky=W)
    lab_min = Label(wg,text='min', justify=RIGHT)
    lab_min.grid(row=6, column=1)
    lab_max = Label(wg,text='max', justify=RIGHT)
    lab_max.grid(row=7, column=1)
    entry_from = Entry(wg,width=10, bg='white')
    entry_from.grid(row=6,column=2, sticky=W)
    entry_to = Entry(wg,width=10, bg='white')
    entry_to.grid(row=7,column=2, sticky=W)
    entry_variant = Entry(wg,width=10, bg='white', state=DISABLED)
    entry_variant.grid(row=8, column=1,columnspan=2,sticky=W)
    var_prob = IntVar()
    var_prob.set(0)
    equ_radio = Radiobutton(wg,text="равновероятная",variable=var_prob,value=0)
    nonequ_radio = Radiobutton(wg,text="неравновероятная",variable=var_prob,value=1)
    equ_radio.grid(row=10, column=1, columnspan=2, sticky=W)
    nonequ_radio.grid(row=11, column=1, columnspan=2, sticky=W)   
    Frame(wg, width=10).grid(row=0, column=4) 
 
    wg.focus_set()
    wg.grab_set()
    wg.wait_window()
 
button_generate.config(command=generator)
 
############### ABOUT&HELP ##################
def about_help():
    wah = Toplevel()
    wah.title('About&Help')
    wah.geometry('+600+250')
    wah.resizable(False,False)
    about = 'Программа "Анализатор выборки" подготовлена для ученического проекта.\n\
Не содержит код для обработки ошибок ввода пользователя.\n\
Автор: Светлана Шапошникова (<a href="http://pythoner.name" title="http://pythoner.name">http://pythoner.name</a>).\n\
Программа распространяется по условиям GNU General Public License.'
    Label(wah, text="О программе:",  font='Times 14', fg='darkblue').grid(row=0, column=0, sticky=W, padx=5)
    Label(wah,  text = about, justify=LEFT).grid(row=1, column=0, sticky=W, padx=20)
    help_string = '1. В поле "Признак" введите название выборки. Строка отобразится на графике, а также \
будет добавлена в файл при сохранении данных.\n\n\
2. В текстовое поле загрузите, вставьте или сгенерируйте данные. Данные должны быть разделены пробелом \
или символом новой строки.\n\n\
3. Нажмите на кнопку "Обработать". Программа определит тип данных и их количество. В случае \
числовых типов также будут определены минимальное и максимальное значения.\n\n\
4. Тип данных можно изменить, установив соответствующий флажок. После этого станут доступны радиокнопки \
для ручного указания типа. Для вещественного типа данных можно указать точность представления числа.\n\n\
5. В случае необходимости укажите иные минимальные и максимальные значения.\n\n\
6. Для чисел выберите способ формирования диапазонов. Укажите либо количество диапазонов, либо их длину \
(интервал), либо задайте границы диапазонов вручную.\n\n\
7. Нажмите на кнопку "Вычислить". Справа в текстовом поле построчно отобразятся диапазоны, количество \
элементов, попавших в каждый диапазон, также будет вычислено процентное соотношение диапазонов. \
На холсте будет отображена столбчатая гистограмма.\n\n\
8. При необходимости данные можно сохранить.'
    Label(wah, text="Как пользоваться программой:",  font='Times 14', fg='darkblue').grid(row=2, column=0, sticky=W, padx=5)
    text = Text(wah, width=70, height=28, wrap=WORD)
    text.grid(row=3, column=0, padx=20)
    text.insert(1.0, help_string)
    Frame(wah, height=10).grid(row=4, column=0)
    wah.focus_set()
    wah.grab_set()
    wah.wait_window()
 
button_about.config(command=about_help)
 
##########################################
win.mainloop()

 

Создано