From 770db831f418097b40b524ab64f7be63981e5319 Mon Sep 17 00:00:00 2001 From: ostapkob Date: Tue, 29 Sep 2020 10:31:16 +1000 Subject: [PATCH] test status --- .project_alt.json | 4 + app/functions.py | 128 +++++++---- app/model.py | 2 +- del.py | 511 +++++++++++++++++++++++++++++++++++++++++ tests/data_test.xlsx | Bin 0 -> 60612 bytes tests/functions.py | 105 +++++++++ tests/kran_data.py | 70 ++++++ tests/xlsx_to_array.py | 7 + 8 files changed, 786 insertions(+), 41 deletions(-) create mode 100644 .project_alt.json create mode 100644 del.py create mode 100644 tests/data_test.xlsx create mode 100644 tests/functions.py create mode 100644 tests/kran_data.py create mode 100644 tests/xlsx_to_array.py diff --git a/.project_alt.json b/.project_alt.json new file mode 100644 index 0000000..3ea2b09 --- /dev/null +++ b/.project_alt.json @@ -0,0 +1,4 @@ +{ + "app/*.py": {"alternate": "tests/{}.py"}, + "tests/*.py": {"alternate": "app/{}.py"} +} diff --git a/app/functions.py b/app/functions.py index 5497fe3..d574f87 100644 --- a/app/functions.py +++ b/app/functions.py @@ -1,11 +1,10 @@ from datetime import datetime, timedelta -from flask import render_template, flash +from flask import flash, redirect, url_for from app.model import Post, Mechanism, Work_1C_1 from app import db -from pprint import pprint -from random import choice -HOURS = 10 #your timezone + +HOURS = 10 # your timezone def today_shift_date(): @@ -25,20 +24,24 @@ def today_shift_date(): def all_mechanisms_id(type=None): '''Find all mechanisms id''' - if type == None: + if type is None: return [m.id for m in db.session.query(Mechanism).all()] - return [m.id for m in db.session.query(Mechanism).filter(Mechanism.type == type).all()] + return [m.id for m in db.session.query(Mechanism).filter( + Mechanism.type == type).all()] + def all_mechanisms_type(): '''Find all mechanisms type''' ls = [m.type for m in db.session.query(Mechanism).all()] return set(ls) + def all_number(type, number): '''Need to do then''' return [m.id for m in Mechanism.query.all()] -def multiple_5(date): #not use + +def multiple_5(date): # not use '''Return time multiple 5 minutes and remite microseconds''' global HOURS # date -= timedelta(minutes=5) @@ -49,38 +52,46 @@ def multiple_5(date): #not use def image_mechanism(value, type_mechanism, number, last_time): - dt = datetime.now()- last_time - dt =dt.total_seconds()/60 - if type_mechanism=="usm": + dt = datetime.now() - last_time + dt = dt.total_seconds() / 60 + if type_mechanism == "usm": if dt > 120.0: - return './static/numbers/'+str(type_mechanism)+'/gray/'+str(number)+'.png' + return './static/numbers/'+str( + type_mechanism)+'/gray/'+str(number)+'.png' if dt >= 3.0: - return './static/numbers/'+str(type_mechanism)+'/red/'+str(number)+'.png' - if value<0.1: - return './static/numbers/'+str(type_mechanism)+'/yellow/'+str(number)+'.png' + return './static/numbers/'+str( + type_mechanism)+'/red/'+str(number)+'.png' + if value < 0.1: + return './static/numbers/'+str( + type_mechanism)+'/yellow/'+str(number)+'.png' else: - return './static/numbers/'+str(type_mechanism)+'/green/'+str(number)+'.png' + return './static/numbers/'+str( + type_mechanism)+'/green/'+str(number)+'.png' - if type_mechanism=="kran": + if type_mechanism == "kran": if dt > 120.0: - return './static/numbers/'+str(type_mechanism)+'/gray/'+str(number)+'.png' + return './static/numbers/'+str( + type_mechanism)+'/gray/'+str(number)+'.png' if dt >= 5.0: - return './static/numbers/'+str(type_mechanism)+'/red/'+str(number)+'.png' - if value==1: - return './static/numbers/'+str(type_mechanism)+'/black/'+str(number)+'.png' - if value==2: - return './static/numbers/'+str(type_mechanism)+'/blue/'+str(number)+'.png' + return './static/numbers/'+str( + type_mechanism)+'/red/'+str(number)+'.png' + if value == 1: + return './static/numbers/'+str( + type_mechanism)+'/black/'+str(number)+'.png' + if value == 2: + return './static/numbers/'+str( + type_mechanism)+'/blue/'+str(number)+'.png' else: - return './static/numbers/'+str(type_mechanism)+'/yellow/'+str(number)+'.png' - + return './static/numbers/'+str( + type_mechanism)+'/yellow/'+str(number)+'.png' -# not use -def time_for_shift_list(date_shift, shift): #not use +def time_for_shift_list(date_shift, shift): # not use '''get dict with all minute's values for the period''' # get data from db cursor = db.session.query(Post).filter( - Post.date_shift == date_shift, Post.shift == shift).order_by(Post.mechanism_id).all() + Post.date_shift == date_shift, + Post.shift == shift).order_by(Post.mechanism_id).all() # create dict all works mechanism in shift data_per_shift = {} @@ -122,10 +133,11 @@ def time_for_shift_list(date_shift, shift): #not use break return time_by_minuts + def handle_date(date): day = month = year = None spl_date = date.split('.') - if len(spl_date) >3: + if len(spl_date) > 3: return redirect(url_for('index')) try: day = int(spl_date[0]) @@ -133,43 +145,55 @@ def handle_date(date): year = int(spl_date[2]) except IndexError: print('ERR', day, month, year) - if not year: year=datetime.now().year - if not month: month=datetime.now().month - if not day: day=datetime.now().day + if not year: + year = datetime.now().year + if not month: + month = datetime.now().month + if not day: + day = datetime.now().day try: return datetime(year, month, day).date() - except: + except ValueError: flash('Enter correct shift') return datetime.now().date() + def data_from_1c(date_shift, shift): time_from = datetime.combine(date_shift, datetime.min.time()) - if shift==1: + if shift == 1: time_from += timedelta(hours=8) else: time_from += timedelta(hours=20) time_to = time_from + timedelta(hours=12) - cursor = db.session.query(Work_1C_1).filter(Work_1C_1.data_nach>=time_from, Work_1C_1.data_nach<=time_to).all() + cursor = db.session.query(Work_1C_1).filter( + Work_1C_1.data_nach >= time_from, + Work_1C_1.data_nach <= time_to).all() data_1C = [x.get() for x in cursor] return data_1C + def data_from_1c_by_id(date_shift, shift, id_mech): time_from = datetime.combine(date_shift, datetime.min.time()) - if shift==1: + if shift == 1: time_from += timedelta(hours=8) else: time_from += timedelta(hours=20) time_to = time_from + timedelta(hours=12) - cursor = db.session.query(Work_1C_1).filter(Work_1C_1.data_nach>=time_from, Work_1C_1.data_nach= time_from, + Work_1C_1.data_nach < time_to, + Work_1C_1.inv_num == id_mech).all() data_1C = [x.get() for x in cursor] return data_1C + def fio_to_fi(item): fio = item[3].split() if not fio: return None return f'{fio[0].capitalize()} {fio[1][0]}.' + def add_fio(data_kran_period, date_shift, shift): ''' add fio and grab if it exec''' if not data_kran_period: @@ -177,10 +201,10 @@ def add_fio(data_kran_period, date_shift, shift): for key, value in data_kran_period.items(): id_mech = data_kran_period[key]['id'] data_by_id_mech = data_from_1c_by_id(date_shift, shift, id_mech) - if len(data_by_id_mech)<1: + if len(data_by_id_mech) < 1: data_kran_period[key]['fio'] = None data_kran_period[key]['grab'] = None - elif len(data_by_id_mech)==1: + elif len(data_by_id_mech) == 1: data_kran_period[key]['fio'] = fio_to_fi(data_by_id_mech[0]) if data_by_id_mech[0][2] == 0: data_kran_period[key]['grab'] = None @@ -191,7 +215,31 @@ def add_fio(data_kran_period, date_shift, shift): data_kran_period[key]['fio'] = 'Two operators' return data_kran_period + def get_state(): - state = ['work', 'stay', 'no_power', 'long_not_work'] - return choice(state) + return 'work' + + +def state_mech(args): + values = list(x.value == -1 for x in args.values()) + result = all(values[1:]) + print(values, result) + if result: + return 'no_power' + + values = list(x.value <= .1 for x in args.values()) + result = all(values[1:]) + if result: + return 'stay' + + return 'work' + +def alarm_mech(args): + """state = ['work', 'stay', 'no_power', 'long_not_work', 'bad_work']""" + # for x in args.values(): + # print(x.value, x.timestamp) + values = list(x.value for x in args.values()) + if sum(values) <= 1: + return False + return True diff --git a/app/model.py b/app/model.py index 9d5fccb..fe9b778 100644 --- a/app/model.py +++ b/app/model.py @@ -80,7 +80,7 @@ def __init__(self, mechanism_id, latitude=0, longitude=0, value=None, value2=Non f.write(d) def __repr__(self): - return f'{self.value}' + return f'{self.timestamp} {self.value} ' def add_post(self): print(super().get_tables_for_bind()) diff --git a/del.py b/del.py new file mode 100644 index 0000000..522a32f --- /dev/null +++ b/del.py @@ -0,0 +1,511 @@ +a =[[(0, None), + (1, None), + (2, None), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + False], + [(0, None), + (1, None), + (2, None), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, None), + (2, 1), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, None), + (2, 1), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, 1), + (2, None), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, 1), + (2, None), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, 1), + (2, 1), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, 1), + (2, 1), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, None), + (2, None), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, None), + (2, None), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, None), + (2, 1), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, None), + (2, 1), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, 1), + (2, None), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, 1), + (2, None), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, 1), + (2, 1), + (3, None), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, 1), + (1, 1), + (2, 1), + (3, 1), + (4, 1), + (5, None), + (6, None), + (7, None), + (8, None), + (9, 0), + (10, None), + (11, None), + (12, None), + (13, None), + (14, 0), + True], + [(0, None), + (1, None), + (2, None), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + False], + [(0, None), + (1, None), + (2, 1), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, None), + (1, 1), + (2, None), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, None), + (1, 1), + (2, 1), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, 1), + (1, None), + (2, None), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, 1), + (1, None), + (2, 1), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, 1), + (1, 1), + (2, None), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, 1), + (1, 1), + (2, 1), + (3, 1), + (4, None), + (5, None), + (6, None), + (7, None), + (8, 0), + (9, None), + (10, None), + (11, None), + (12, None), + (13, 0), + (14, None), + True], + [(0, None), + (1, None), + (2, 1), + (3, None), + (4, None), + (5, None), + (6, None), + (7, 0), + (8, None), + (9, None), + (10, None), + (11, None), + (12, 0), + (13, None), + (14, None), + False], + [(0, None), + (1, 1), + (2, 1), + (3, None), + (4, None), + (5, None), + (6, None), + (7, 0), + (8, None), + (9, None), + (10, None), + (11, None), + (12, 0), + (13, None), + (14, None), + True], + [(0, 1), + (1, None), + (2, 1), + (3, None), + (4, None), + (5, None), + (6, None), + (7, 0), + (8, None), + (9, None), + (10, None), + (11, None), + (12, 0), + (13, None), + (14, None), + True], + [(0, 1), + (1, 1), + (2, 1), + (3, None), + (4, None), + (5, None), + (6, None), + (7, 0), + (8, None), + (9, None), + (10, None), + (11, None), + (12, 0), + (13, None), + (14, None), + True], + [(0, None), + (1, 1), + (2, None), + (3, None), + (4, None), + (5, None), + (6, 0), + (7, None), + (8, None), + (9, None), + (10, None), + (11, 0), + (12, None), + (13, None), + (14, None), + False], + [(0, 1), + (1, 1), + (2, None), + (3, None), + (4, None), + (5, None), + (6, 0), + (7, None), + (8, None), + (9, None), + (10, None), + (11, 0), + (12, None), + (13, None), + (14, None), + True], + [(0, 1), + (1, None), + (2, None), + (3, None), + (4, None), + (5, 0), + (6, None), + (7, None), + (8, None), + (9, None), + (10, 0), + (11, None), + (12, None), + (13, None), + (14, None), + False]] + + +n_data = [] +for i in a: + v = i[:-1] + r = i[-1] + el = [] + for j in v: + if j[1] is not None: + el.append(j) + n_data.append([el, r]) + +from pprint import pprint + +pprint(n_data) diff --git a/tests/data_test.xlsx b/tests/data_test.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..14427924a4141ccc2164a9f74d3c2b2857aea683 GIT binary patch literal 60612 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 literal 0 HcmV?d00001 diff --git a/tests/functions.py b/tests/functions.py new file mode 100644 index 0000000..e0fe9f2 --- /dev/null +++ b/tests/functions.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import unittest +from app import db +from app.functions import alarm_mech +from datetime import datetime, timedelta +from app.model import Post +from tests.kran_data import value_minutes + + +class Data(): + + def __init__(self, timestamp, value): + self.timestamp = timestamp + self.value = value + + def __str__(self): + return f"{self.timestamp}, {self.value}" + + def timestamp(self): + return self.timestamp + + def value(self): + return self.value + + +class GetState(unittest.TestCase): + + def get_data_kran(self, arg, delta=0): + data = {} + time = datetime.now() - timedelta(minutes=15) + for e, (v, m) in enumerate(arg): + data[e] = Data(time, v) + time = datetime.now() - timedelta(minutes=m) + # print(e, v, m, time) + return data + + def get_data(self, arg, delta=0): + dt = sum([1 for _ in arg]) + data = {} + for e, (v, m) in enumerate(arg): + dt -= m + time = datetime.now() - timedelta(minutes=dt) + data[e] = Data(time, v) + print(e, v, m, time) + return data + +# def test_11111111111(self): +# values = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +# minutes = 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1 +# assert len(values) == len(minutes), 'Not equal lens' +# data = self.get_data(list(zip(values, minutes))) +# result = state_mech(data) +# self.assertEqual(result, 'work') + +# def test_10000000000(self): +# values = 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +# minutes = 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1 +# assert len(values) == len(minutes), 'Not equal lens' +# data = self.get_data(list(zip(values, minutes))) +# result = state_mech(data) +# self.assertEqual(result, 'stay') + +# def test_10000000001(self): +# values = 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 +# minutes = 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1 +# assert len(values) == len(minutes), 'Not equal lens' +# data = self.get_data(list(zip(values, minutes))) +# result = state_mech(data) +# self.assertEqual(result, 'work') + +# def test_1m1m1m1m1m1(self): +# values = 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 +# minutes = 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1 +# assert len(values) == len(minutes), 'Not equal lens' +# data = self.get_data(list(zip(values, minutes))) +# result = state_mech(data) +# self.assertEqual(result, 'no_power') + +# def test_1m1m1m_1_1m1m1(self): +# values = 1, -1, -1, -1, -1, 0, -1, -1, -1, -1, -1 +# minutes = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +# assert len(values) == len(minutes), 'Not equal lens' +# data = self.get_data(list(zip(values, minutes))) +# result = state_mech(data) +# self.assertEqual(result, 'stay') + + def test_kran(self): + for i in value_minutes: + values = i[0] + minutes = i[1][::-1] + result_1 = i[2] + # print(values, minutes, result_1) + with self.subTest(True): + data = self.get_data_kran(list(zip(values, minutes))) + result_2 = alarm_mech(data) + self.assertEqual(result_1, result_2) + + +if __name__ == '__main__': + last = db.session.query(Post).filter(Post.mechanism_id == 32711).order_by( + Post.timestamp.desc()).limit(11) + # for i in last: + # print('->', i.timestamp, i.value) + unittest.main() diff --git a/tests/kran_data.py b/tests/kran_data.py new file mode 100644 index 0000000..bf261be --- /dev/null +++ b/tests/kran_data.py @@ -0,0 +1,70 @@ +kran_data = [[[(4, 1), (9, 0), (14, 0)], False], # kran data for test + [[(3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(2, 1), (4, 1), (9, 0), (14, 0)], True], + [[(2, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(1, 1), (4, 1), (9, 0), (14, 0)], True], + [[(1, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(1, 1), (2, 1), (4, 1), (9, 0), (14, 0)], True], + [[(1, 1), (2, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (2, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (2, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (1, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (1, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (1, 1), (2, 1), (4, 1), (9, 0), (14, 0)], True], + [[(0, 1), (1, 1), (2, 1), (3, 1), (4, 1), (9, 0), (14, 0)], True], + [[(3, 1), (8, 0), (13, 0)], False], + [[(2, 1), (3, 1), (8, 0), (13, 0)], True], + [[(1, 1), (3, 1), (8, 0), (13, 0)], True], + [[(1, 1), (2, 1), (3, 1), (8, 0), (13, 0)], True], + [[(0, 1), (3, 1), (8, 0), (13, 0)], True], + [[(0, 1), (2, 1), (3, 1), (8, 0), (13, 0)], True], + [[(0, 1), (1, 1), (3, 1), (8, 0), (13, 0)], True], + [[(0, 1), (1, 1), (2, 1), (3, 1), (8, 0), (13, 0)], True], + [[(2, 1), (7, 0), (12, 0)], False], + [[(1, 1), (2, 1), (7, 0), (12, 0)], True], + [[(0, 1), (2, 1), (7, 0), (12, 0)], True], + [[(0, 1), (1, 1), (2, 1), (7, 0), (12, 0)], True], + [[(1, 1), (6, 0), (11, 0)], False], + [[(0, 1), (1, 1), (6, 0), (11, 0)], True], + [[(0, 1), (5, 0), (10, 0)], False]] + + +value_minutes = [[[1, 0, 0], [4, 9, 14], False], + [[1, 1, 0, 0], [3, 4, 9, 14], True], + [[1, 1, 0, 0], [2, 4, 9, 14], True], + [[1, 1, 1, 0, 0], [2, 3, 4, 9, 14], True], + [[1, 1, 0, 0], [1, 4, 9, 14], True], + [[1, 1, 1, 0, 0], [1, 3, 4, 9, 14], True], + [[1, 1, 1, 0, 0], [1, 2, 4, 9, 14], True], + [[1, 1, 1, 1, 0, 0], [1, 2, 3, 4, 9, 14], True], + [[1, 1, 0, 0], [0, 4, 9, 14], True], + [[1, 1, 1, 0, 0], [0, 3, 4, 9, 14], True], + [[1, 1, 1, 0, 0], [0, 2, 4, 9, 14], True], + [[1, 1, 1, 1, 0, 0], [0, 2, 3, 4, 9, 14], True], + [[1, 1, 1, 0, 0], [0, 1, 4, 9, 14], True], + [[1, 1, 1, 1, 0, 0], [0, 1, 3, 4, 9, 14], True], + [[1, 1, 1, 1, 0, 0], [0, 1, 2, 4, 9, 14], True], + [[1, 1, 1, 1, 1, 0, 0], [0, 1, 2, 3, 4, 9, 14], True], + [[1, 0, 0], [3, 8, 13], False], + [[1, 1, 0, 0], [2, 3, 8, 13], True], + [[1, 1, 0, 0], [1, 3, 8, 13], True], + [[1, 1, 1, 0, 0], [1, 2, 3, 8, 13], True], + [[1, 1, 0, 0], [0, 3, 8, 13], True], + [[1, 1, 1, 0, 0], [0, 2, 3, 8, 13], True], + [[1, 1, 1, 0, 0], [0, 1, 3, 8, 13], True], + [[1, 1, 1, 1, 0, 0], [0, 1, 2, 3, 8, 13], True], + [[1, 0, 0], [2, 7, 12], False], + [[1, 1, 0, 0], [1, 2, 7, 12], True], + [[1, 1, 0, 0], [0, 2, 7, 12], True], + [[1, 1, 1, 0, 0], [0, 1, 2, 7, 12], True], + [[1, 0, 0], [1, 6, 11], False], + [[1, 1, 0, 0], [0, 1, 6, 11], True], + [[1, 0, 0], [0, 5, 10], False]] + + + + + + diff --git a/tests/xlsx_to_array.py b/tests/xlsx_to_array.py new file mode 100644 index 0000000..4aebde7 --- /dev/null +++ b/tests/xlsx_to_array.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import openpyxl + +book = openpyxl.load_workbook('data_test.xlsx') +sheet = book.active