from base_form import BaseForm
from widgets import TextField
from cairo import ImageSurface, Context, FontOptions, FORMAT_ARGB32
import math
import datetime
from io import BytesIO

class Page5_1(BaseForm):
    ACTION = "page5_1"
    VIEW = "page5_1.tpl"

    def create_widgets(self):
        panels_data = []
        for row in self.db.select("select ID, NAME, HEIGHT from web_stat_panels order by ID"):
            panels_data += [self._create_panel(str(row[0]), str(row[1], "utf-8"), str(row[2]))]

        tf = TextField("STATISTIC_PANELS", "".join(panels_data))
        self.add_widget(tf)

        tf = TextField("START_TIME", str(round(datetime.datetime.now().timestamp())))
        self.add_widget(tf)

        """
        try:
            self.copy_var_changes_to_mem()
        except Exception as e:
            print(e)
        """

    def _create_panel(self, key, name, height):
        lb1, lb2, lb3, lb4 = ["-- нет --"] * 4
        for row in self.db.select("select v.ID, CONCAT(v.COMM, ' [', v.NAME, ']'), p.SERIES_1, p.SERIES_2, p.SERIES_3, p.SERIES_4 "
                                  "  from web_stat_panels p, core_variables v "
                                  " where (p.SERIES_1 = v.ID "
                                  "     or p.SERIES_2 = v.ID "
                                  "     or p.SERIES_3 = v.ID "
                                  "     or p.SERIES_4 = v.ID)"
                                  "    and p.ID = %s" % (key)):
            sers = row[2:6]
            lab = str(row[1], "utf-8")
            if row[0] == sers[0]:
                lb1 = lab
            elif row[0] == sers[1]:
                lb2 = lab
            elif row[0] == sers[2]:
                lb3 = lab
            elif row[0] == sers[3]:
                lb4 = lab

        f = open("views/stat_panel.tpl", "r")
        tmpl = f.read()
        f.close()
        tmpl = tmpl.replace("@ID@", key)
        tmpl = tmpl.replace("@LABEL@", name)
        tmpl = tmpl.replace("@HEIGHT@", height)
        tmpl = tmpl.replace("@LABEL_1@", lb1)
        tmpl = tmpl.replace("@LABEL_2@", lb2)
        tmpl = tmpl.replace("@LABEL_3@", lb3)
        tmpl = tmpl.replace("@LABEL_4@", lb4)
        return tmpl

    def query(self, query_type):
        if query_type == "append_panel":
            self.db.IUD("insert into web_stat_panels (NAME) values ('%s')" % ("Новая панель"))
            self.db.commit()
            return self._create_panel(str(self.db.lastID()), "Новая панель", "200")
        elif query_type == "del_panel":
            self.db.IUD("delete from web_stat_panels where ID = %s" % (self.param("key")))
            self.db.commit()
            return "OK"
        elif query_type == "panel_img":
            self.content_type = "image/png"
            return self._paint_panel(self.param('key'), self.param('width'), self.param('height'), self.param('panel_h'))
        elif query_type == "panel_cursor":
            sql = ("select * from (select c.VALUE, %s NUM "
                                  "  from core_variable_changes c, web_stat_panels p "
                                  " where p.ID = %s "
                                  "   and p.SERIES_%s = c.VARIABLE_ID "
                                  "   and c.CHANGE_DATE < FROM_UNIXTIME(%s) "
                                  "order by c.CHANGE_DATE desc limit 1) a")
            s = []
            for i in range(1, 5):
                s += [sql % (i, self.param('key'), i, self.param('pos')), " union "]

            s = "".join(s[:-1])

            res = [",", ",", ",", ","]
            for rec in self.db.select("select b.* from (%s) b order by b.NUM " % (s)):
                res[rec[1] - 1] = "%s," % (round(rec[0], 2))

            return "".join(res)

    def _get_one_val(self, series, min_max_vals, min_x, max_x):
        def min_x_val(key):
            for v in min_max_vals:
                if v[0] == key:
                    #print(v[1])
                    return v[1]
            return min_x

        def max_x_val(key):
            for v in min_max_vals:
                if v[0] == key:
                    #print(v[2])
                    return v[2]
            return max_x

        res = [[], [], [], []]
        sql = []
        for i in range(4):
            if series[i] > 0:
                sql_prev = ("select a.* from ("
                            "select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, 1 "
                            "  from core_variable_changes "
                            " where VARIABLE_ID = %s "
                            "   and CHANGE_DATE < FROM_UNIXTIME(%s) "
                            "order by CHANGE_DATE desc limit 1) a" % (series[i], min_x_val(series[i])))

                sql_next = ("select a.* from ("
                            "select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, 2 "
                            "  from core_variable_changes "
                            " where VARIABLE_ID = %s "
                            "   and CHANGE_DATE > FROM_UNIXTIME(%s) "
                            "order by CHANGE_DATE limit 1) a" % (series[i], max_x_val(series[i])))
            if len(sql) > 0:
                sql += [" union "]

            try:
                sql += ["%s union %s" % (sql_prev, sql_next)]
            except:
                pass

        for row in self.db.select("".join(sql)):
            try:
                i = series.index(row[2])
                res[i] += [row]
            except Exception as e:
                #print("{}".format(e.args))
                pass
        return res
    """
    def _get_one_val(self, series, min_x, max_x):
        res = [[], [], [], []]
        sql = []
        for i in range(4):
            if series[i] > 0:
                sql_prev = ("select a.* from ("
                            "select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, 1 "
                            "  from core_variable_changes "
                            " where VARIABLE_ID = %s "
                            "   and CHANGE_DATE < FROM_UNIXTIME(%s) "
                            "order by CHANGE_DATE desc limit 1) a" % (series[i], min_x))

                sql_next = ("select a.* from ("
                            "select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, 2 "
                            "  from core_variable_changes "
                            " where VARIABLE_ID = %s "
                            "   and CHANGE_DATE > FROM_UNIXTIME(%s) "
                            "order by CHANGE_DATE limit 1) a" % (series[i], max_x))
            if len(sql) > 0:
                sql += [" union "]

            try:
                sql += ["%s union %s" % (sql_prev, sql_next)]
            except:
                pass

        for row in self.db.select("".join(sql)):
            try:
                i = series.index(row[2])
                res[i] += [row]
            except:
                pass
        return res
    """

    def _paint_panel(self, key, width, height, panel_h):
        self.db.IUD("update web_stat_panels set HEIGHT = %s where ID = %s" % (panel_h, key))
        self.db.commit()

        color_x_line = (0.7, 0.7, 0.7)
        color_x_line_2 = (0.9, 0.9, 0.9)
        color_y_line = (0.9, 0.9, 0.9)
        color_y_line_date = (0.7, 0.7, 0.7)
        color_border = (0.5, 0.5, 0.5)

        left = 40
        right = 10;
        bottom = 15

        var_ids = "0";
        series = [0, 0, 0, 0]
        typ = 0
        for row in self.db.select("select SERIES_1, SERIES_2, SERIES_3, SERIES_4, TYP "
                                  "  from web_stat_panels "
                                  " where ID = " + str(key)):
            series = row
            var_ids = "%s, %s, %s, %s" % row[0:4]
            typ = row[4]

        width, height = int(width), int(height)
        if width <= 0:
            width = 300
        if height <= 0:
            height = 150

        interval = self.param('range')

        delta_x = 1
        if interval == "-6 hour":
            delta_x = 6 * 3600
        elif interval == "-12 hour":
            delta_x = 12 * 3600
        elif interval == "-1 day":
            delta_x = 24 * 3600
        elif interval == "-3 day":
            delta_x = 3 * 24 * 3600
        elif interval == "-7 day":
            delta_x = 7 * 24 * 3600
        elif interval == "-14 day":
            delta_x = 14 * 24 * 3600
        elif interval == "-30 day":
            delta_x = 30 * 24 * 3600
        elif interval == "-90 day":
            delta_x = 3 * 30 * 24 * 3600
        elif interval == "-180 day":
            delta_x = 6 * 30 * 24 * 3600
        elif interval == "-360 day":
            delta_x = 12 * 30 * 24 * 3600

        min_x = int(self.param('start')) - delta_x // 2
        max_x = min_x + delta_x

        min_x_q = min_x - delta_x# // 100
        max_x_q = max_x + delta_x# // 100

        max_y = -9999
        min_y = 9999

        # Делаем полную выборку данных. Выкидываем подозрительные точки и
        # собираем статистику.
        prev_vals = [-9999] * 4
        chart_data = [[], [], [], []]

        zoom_step = delta_x / (width * 5)
        if zoom_step < 1 or typ != 0:
            zoom_step = 1

        x_min_max_values = []
        mi_x = max_x_q
        ma_x = min_x_q
        tt = -100

        for row in self.db.select("select UNIX_TIMESTAMP(CHANGE_DATE) D, MIN(VALUE) + (MAX(VALUE) - MIN(VALUE)) VALUE, VARIABLE_ID "
                                  "  from core_variable_changes "
                                  " where VARIABLE_ID in (%s) "
                                  "   and CHANGE_DATE >= FROM_UNIXTIME(%s) "
                                  "   and CHANGE_DATE <= FROM_UNIXTIME(%s) "
                                  " group by 3, ROUND(UNIX_TIMESTAMP(CHANGE_DATE) / %s)"
                                  " order by 3, 1 " % (var_ids, min_x_q, max_x_q, zoom_step)):
            ind = series.index(row[2])
            chart_data[ind] += [row]
            if row[0] > min_x and row[0] < max_x:
                max_y = max(max_y, row[1])
                min_y = min(min_y, row[1])

            if tt == -100:
                tt = row[2]

            if tt != row[2]:
                v = [tt, mi_x, ma_x]
                x_min_max_values += [v]
                mi_x = max_x_q
                ma_x = min_x_q
                tt = row[2]

            if row[0] < mi_x:
                mi_x = row[0]
            if row[0] > ma_x:
                ma_x = row[0]

        if tt != -1:
            v = [tt, mi_x, ma_x]
            x_min_max_values += [v]

        #print(x_min_max_values)
        #print(series)

        """
        for row in self.db.select("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID "
                                  "  from core_variable_changes "
                                  " where VARIABLE_ID in (" + var_ids + ") "
                                  "   and CHANGE_DATE >= FROM_UNIXTIME(%s) "
                                  "   and CHANGE_DATE <= FROM_UNIXTIME(%s) "
                                  "order by CHANGE_DATE " % (min_x_q, max_x_q)):
        """
        """
        try:
            self.db.IUD("set @rn := 0")

            sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID "
                   "  from core_variable_changes "
                   " where VARIABLE_ID in (" + var_ids + ") "
                   "   and CHANGE_DATE >= FROM_UNIXTIME(%s) "
                   "   and CHANGE_DATE <= FROM_UNIXTIME(%s) "
                   "order by CHANGE_DATE " % (min_x_q, max_x_q))

            for c in self.db.select("select count(*) c "
                                    "  from core_variable_changes "
                                    " where VARIABLE_ID in (" + var_ids + ") "
                                    "   and CHANGE_DATE >= FROM_UNIXTIME(%s) "
                                    "   and CHANGE_DATE <= FROM_UNIXTIME(%s) " % (min_x_q, max_x_q)):
                cou = c[0]
                ccc = 1000 * 4
                if cou > ccc:
                    sql = ("select UNIX_TIMESTAMP(CHANGE_DATE) D, VALUE, VARIABLE_ID, ID, @rn := @rn + 1 rownum "
                           "  from core_variable_changes "
                           " where VARIABLE_ID in (" + var_ids + ") "
                           "   and CHANGE_DATE >= FROM_UNIXTIME(%s) "
                           "   and CHANGE_DATE <= FROM_UNIXTIME(%s) "
                           "having mod(rownum, %s) = 0 "
                           "order by VARIABLE_ID, CHANGE_DATE " % (min_x_q, max_x_q, math.ceil(cou / ccc)))

            for row in self.db.select(sql):
                ind = series.index(row[2])
                prev_vals[ind] = row[1]

                if abs(prev_vals[ind] - row[1]) < 10:
                    chart_data[ind] += [row]
                    if row[0] > min_x and row[0] < max_x:
                        max_y = max(max_y, row[1])
                        min_y = min(min_y, row[1])
                prev_vals[ind] = row[1]
        except:
            pass
        """

        if min_y is None or max_y is None or min_y == 9999 or max_y == -9999 or min_y == max_y:
            max_y = 1
            min_y = 0

        min_y = math.floor(min_y)
        max_y = math.ceil(max_y)

        if typ == 2:
            if min_y < 0 and max_y < 0:
                max_y = 0
            elif min_y > 0 and max_y > 0:
                min_y = 0

        # Определяем цвета
        colors = [[1, 0, 0], [0, 0.65, 0.31], [0, 0, 1], [1, 0, 1]]

        off_y = (max_y - min_y) / 10
        min_y -= off_y
        max_y += off_y

        try:
            kx = ((max_x - min_x) / (width - left - right))
            ky = ((max_y - min_y) / (height - bottom))
            if ky == 0:
                ky = 1
        except:
            kx, ky = 1, 1

        img = ImageSurface(FORMAT_ARGB32, width, height)
        ctx = Context(img)

        width -= right
        ctx.set_line_width(1)

        # Рисуем сетку

        ctx.set_font_size(12)
        try:
            b_w, b_h = ctx.text_extents("00-00-0000")[2:4]

            # Метки на оси Y
            count = math.ceil(max_y) - math.ceil(min_y)
            space_count = math.ceil(count / ((height - bottom) / (b_h * 1.5)))
            sc = 0
            for i in range(math.ceil(min_y), math.ceil(max_y)):
                if sc == 0:
                    y = height - bottom + (min_y - i) / ky
                    ctx.set_source_rgb(*(color_x_line))
                    ctx.move_to(left, y)
                    ctx.line_to(width, y)
                    ctx.stroke()
                    ctx.set_source_rgb(0, 0, 0)
                    num = str(i)
                    tw, th = ctx.text_extents(num)[2:4]
                    ctx.move_to(left - 5 - tw, y + th // 2)
                    ctx.show_text(num)
                    sc = space_count
                sc -= 1

            # Метки на оси Х

            x_step = 3600
            if (interval == "-6 hour" or
                interval == "-12 hour" or
                interval == "-1 day"):
                # Дополнительно метки часов
                x_step = 3600
                for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step)):
                    x = (i * x_step - min_x) / kx + left
                    ctx.set_source_rgb(*(color_x_line_2))
                    ctx.move_to(x, 0)
                    ctx.line_to(x, height - bottom)
                    ctx.stroke()
                    num = datetime.datetime.fromtimestamp(i * x_step).strftime('%H')
                    tw, th = ctx.text_extents(num)[2:4]
                    ctx.move_to(x + 2, height - bottom - 3)
                    ctx.set_source_rgb(*(color_x_line))
                    ctx.show_text(num)

            x_step = 3600 * 24

            space_count = 1
            count = math.ceil(max_x / x_step) - math.ceil(min_x / x_step)
            try:
                if (width / count) < b_w:
                    space_count = 2
            except:
                pass

            sc = 0
            tz = 3600 * 2
            tx_prev = -100
            for i in range(math.ceil(min_x / x_step), math.ceil(max_x / x_step) + 1):
                if sc == 0:
                    d_i = datetime.datetime.fromtimestamp(i * x_step)
                    x = (i * x_step - min_x - tz) / kx + left
                    ctx.set_source_rgb(0, 0, 0)
                    num = d_i.strftime('%d-%m-%Y %H')

                    x -= (int(d_i.strftime('%H')) * 3600 - tz) / kx

                    tw, th = ctx.text_extents(num)[2:4]
                    tx = x - tw // 2
                    ctx.move_to(tx, height - bottom + th + 5)
                    if tx - tx_prev > tw:
                        ctx.show_text(num)
                        tx_prev = tx
                        ctx.set_source_rgb(*(color_y_line_date))
                    else:
                        ctx.set_source_rgb(*(color_y_line))
                    if x >= left and x < width:
                        ctx.move_to(x, 0)
                        ctx.line_to(x, height - bottom)
                        ctx.stroke()
                    sc = space_count
                sc -= 1
        except Exception as e:
            pass

        # Рисуем верхний и правый бордер

        ctx.set_source_rgb(*color_border)
        ctx.move_to(left, 0)
        ctx.line_to(width, 0)
        ctx.line_to(width, height - bottom)
        ctx.stroke()

        #Рисуем сами графики

        ctx.rectangle(left, 0, width - left, height)
        ctx.clip()

        is_first = True
        currVarID = -1
        prevX = -1;

        if typ == 0: # Линейная
            for ind in range(4):
                """
                if len(chart_data[ind]) > 0:
                    for i in range(len(chart_data[ind]) - 1):
                        chart_data[ind][i] = list(chart_data[ind][i])
                        r1 = chart_data[ind][i]
                        r2 = chart_data[ind][i + 1]
                        chart_data[ind][i][0] += (r2[0] - r1[0]) / 2
                        chart_data[ind][i][1] += (r2[1] - r1[1]) / 2
                """
                ctx.set_source_rgb(*colors[ind])
                is_first = True
                for row in chart_data[ind]:
                    x = (row[0] - min_x) / kx + left
                    y = height - bottom - (row[1] - min_y) / ky

                    if is_first:
                        ctx.move_to(x, y)
                    else:
                        if row[0] - prevX > 100000:
                            ctx.move_to(x, y)
                        else:
                            ctx.line_to(x, y)

                    prevX = row[0]
                    is_first = False
                ctx.stroke()

        elif typ == 1: # Точечная
            for ind in range(4):
                if chart_data[ind]:
                    ctx.set_source_rgb(*colors[ind])
                    for row in chart_data[ind]:
                        x = (row[0] - min_x) / kx + left
                        y = height - bottom - (row[1] - min_y) / ky
                        ctx.rectangle(x - 3, y - 3, 6, 6)
                    ctx.fill()
        elif typ == 2: # Столбчатая
            cy = height - bottom - (-min_y) / ky
            for ind in range(4):
                for row in chart_data[ind]:
                    if currVarID != row[2]:
                        ctx.fill()
                        for i in range(4):
                            if series[i] == row[2]:
                                ctx.set_source_rgb(*colors[i])
                    x = (row[0] - min_x) / kx + left
                    y = height - bottom - (row[1] - min_y) / ky
                    ctx.rectangle(x - 5, y, 10, cy - y)

                    currVarID = row[2]
                ctx.fill()
        else: # Линейчастая
            #one_vals = self._get_one_val(series, min_x_q, max_x_q)
            one_vals = self._get_one_val(series, x_min_max_values, min_x_q, max_x_q)
            for ind in range(4):
                if series[ind]:
                    is_now = True
                    for r in one_vals[ind]:
                        if r[4] == 1:
                            chart_data[ind].insert(0, r)
                        else:
                            chart_data[ind] += [r]
                            is_now = False

                    if is_now:
                        if len(chart_data[ind]) > 0:
                            r = list(chart_data[ind][len(chart_data[ind]) - 1])
                            r[0] = datetime.datetime.now().timestamp()
                            chart_data[ind] += [r]

                color = colors[ind]
                color_fill = color.copy()
                color_fill += [0.3]
                is_first = True
                y0 = height - bottom + min_y / ky
                for row in chart_data[ind]:
                    x = (row[0] - min_x) / kx + left
                    y = height - bottom - (row[1] - min_y) / ky

                    if is_first:
                        is_first = False
                    else:
                        ctx.set_source_rgb(*color)
                        ctx.move_to(prevX, prevY)
                        ctx.line_to(x, prevY)
                        ctx.line_to(x, y)
                        ctx.stroke()
                        ctx.set_source_rgba(*color_fill)
                        rx, ry, rw, rh = prevX, y0, x - prevX, prevY - y0
                        ctx.rectangle(rx, ry, rw, rh)
                        ctx.fill()

                    prevX, prevY = x, y

        # Рисуем оси

        ctx.set_source_rgb(0, 0, 0)
        ctx.move_to(left, 0)
        ctx.line_to(left, height - bottom)
        ctx.line_to(width, height - bottom)
        ctx.stroke()

        # ---------------------------

        del ctx

        byt = BytesIO()
        img.write_to_png(byt)
        byt.seek(0)
        return byt.read()

    def copy_var_changes_to_mem(self):
        min_mem = None
        for rec in self.db.select("select MIN(ID) from core_variable_changes_mem"):
            min_mem = rec[0]

        if min_mem != None:
            min_mem_sql = " where ID < %s " % (min_mem)
        else:
            min_mem_sql = ""

        i = 0
        for rec in self.db.select("select ID, VARIABLE_ID, UNIX_TIMESTAMP(CHANGE_DATE), VALUE "
                                  "  from core_variable_changes "
                                  " %s" % (min_mem_sql)):
            try:
                if rec[3] == None:
                    rec[3] = "null"
                self.db.IUD("insert into core_variable_changes_mem "
                            "   (ID, VARIABLE_ID, CHANGE_DATE, VALUE) "
                            "values "
                            "   (%s, %s, FROM_UNIXTIME(%s), %s)" % rec)
                if i > 100:
                    self.db.commit()
                    i = 0
            except Exception as e:
                print(e)
                print(rec)
            i += 1
        self.db.commit()


from flask import Flask, render_template, request, redirect, url_for
import json
import re
import os

app = Flask(__name__)

global n
if os.path.exists('ind.txt') == False:
    f_ind = open('ind.txt', 'w')
    f_ind.write('0')
    f_ind.close()

n = int(open('ind.txt', 'r').read().strip())

if os.path.exists('jsndata.txt') == False:
    f_jsn = open('jsndata.txt', 'w', encoding='UTF-8')
    f_jsn.close()

if os.path.exists('comments.txt') == False:
    f_com = open('comments.txt', 'w', encoding='UTF-8')
    f_com.close()

#global jsnd
#jsnd = [] #jsondata storage

def kdict(): #dictionary for resulting tab with keyz as GET_FORM shortcuts and vals as actual tests
    d = {}
    for ln in open('kyz.txt', 'r'):
        d[ln.split(':')[0]] = ln.split(':')[1].rstrip()
    return d

kd = kdict()

def srch_keyz_dict():
    d = {}
    for ln in open('srch-kyz.txt', 'r'):
        d[ln.split(':')[0]] = ln.split(':')[1].rstrip()
    return d

srch_kd = srch_keyz_dict()

def wr(data, n):
    f = open('expdata.txt', 'a', encoding='UTF-8')
    f.write('expid:' + str(n) + '\n')
    data
    for el in data:
        f.write(el + ':' + data[el] + '\n')
    f.write('#\n')
    f.close()
    return 0

def indxing(num):
    f = open('ind.txt', 'w')
    f.write(str(num))
    f.close()

def jsn_upd(data, n):
    f = open('jsndata.txt', 'a', encoding='UTF-8')
    f.write('Experiment: ' + str(n) + ';' + json.dumps(data, ensure_ascii=False) + '#')
    f.close()
    return 0

def exp_srch(key):
    f = open('expdata.txt', 'r', encoding='UTF-8').read()
    res = re.findall(key+':(.*?)[\s]', f)
    return ';'.join(res)

def res_parse():
    out = []
    out.append(exp_srch('expid'))
    sk = open('sktch.txt', 'r')
    for ln in sk: #itering tests
        for k in kd:
            if kd[k] == ln.strip(): #now entering experiment data; KEY as an arg
                out.append(exp_srch(k))
    #print(out)
    return out

def dict_srch(y, stype):
    out = []
    if stype == 's':
        for el in y:
            for k in kd:
                if k == el:
                    out.append(kd[k])
        return out

    else:
        chksum = 0
        for k in srch_kd:
            for el in y.split():
                for wd in srch_kd[k].split():
                    if el.lower().strip() == wd.lower():
                        chksum += 1
                        if chksum == len(y.split()):
                            return k
        return None

def srch(x):
    f = open('expdata.txt', 'r', encoding='UTF-8').read()
    stype = x['srch_t']
    itm = x['trgt']
    if stype == 's': #searching for the SOUND
        itm = re.sub('\[|\]', '', itm.strip())
        res = re.findall(r'(.*?):\['+itm+'\][\s]', f)
        return dict_srch(res, 's'), '['+itm+']'
    else:
        def keyword_check(itm, k):
            for el in k.split():
                if el.lower() in itm.lower():
                    flag = True
                else:
                    return False
            return flag

        ky = dict_srch(itm, 'ph')
        #print(ky)
        if ky != None and keyword_check(itm, kd[ky]) == True:
            res = re.findall(ky+':(.*?)[\s]', f)
        else:
            return [], itm
        return res, srch_kd[ky]

def reqargcheck(z):
    #print(z)
    i = 0
    for k in z:
        if z[k] != '' and '_com' not in k:
            i += 1
    if i < 13:
        return False
    else:
        return True

def cmnt_wr(x, n):
    f = open('comments.txt', 'a', encoding='UTF-8')
    f.write('Experiment: ' + str(n) + '\n')
    for k in x:
        if '_com' in k:
            f.write(k + ':' + x[k] + '\n')
    f.write('#\n')
    f.close()
    return 0

@app.route('/')
def mform():
    global n

    if len(request.args) == 0:
        return render_template('mform.html')
    else:
        feedstat = reqargcheck(request.args) #if a survey is badly passed
        if feedstat == True:
            n += 1
            indxing(n)
            wr(request.args, n)
            jsn_upd(request.args, n)
            cmnt_wr(request.args, n)
        return redirect(url_for('form_msg', status=feedstat))

@app.route('/json')
def jsn():
    return render_template('jform2.html', jsnd=open('jsndata.txt', 'r', encoding='UTF-8').read())

@app.route('/stats')
def stform():
    if os.path.isfile('expdata.txt') == True:
        out = res_parse()
        #print(out)
        return render_template('stform2.html', reslst=out)
    else:
        return render_template('errlog.html')

@app.route('/search')
def srchform():
    if os.path.isfile('expdata.txt') == True:
        if len(request.args) == 0:
            return render_template('srchform.html')
        else:
            global trgt
            trgt = srch(request.args)
            #print(trgt)
            return redirect(url_for('resform'))
    else:
        return render_template('errlog.html')

@app.route('/results')
def resform():
    return render_template('resform.html', req=trgt[1], trgt=trgt[0])

@app.route('/ipa')
def ipachrt():
    return render_template('ipachrt.html')

@app.route('/feed/<status>')
def form_msg(status):
    #print(status)
    if status == 'True':
        return render_template('feed.html')
    else:
        return render_template('badfeed.html')

if __name__ == '__main__':
    app.run(debug=False)


#coding=utf-8

from MyMatrix import Matrix
from copy import deepcopy
from MatrixAlghoritms import toTriangleShape, addColumn, getCol, printMatr, count
from collections import deque

class Gauss:
    def __init__(self, a, b):
        assert isinstance(a, Matrix) and len(a) == len(b)
        self.A = deepcopy(a)
        self.B = deepcopy(b)

    def getValues(self, matr):
        res = Matrix([])
        for i in range(len(matr))[::-1]:
            zero_zount = count(matr[i], 0.0)
            temp = []
            for j in range(zero_zount + 1, len(matr[i])):
                temp.append(matr[i][j])
            res.append(temp)
        return res

    def getResult(self):
        matr = toTriangleShape(addColumn(self.A, self.B))
        values = self.getValues(matr)
        res = deque(values[0])
        for i in range(1, len(values)):
            temp = 0.
            for j in range(1, len(values[i])):
                temp += res[j - 1] * values[i][j - 1]
            res.appendleft( values[i][-1] - temp )
        return list(res)

    @classmethod
    def getResultStatic(self, A, B):
        res = Gauss(A, B)
        return res.getResult()

if __name__ == '__main__':
    A = Matrix([ [1, 2, 3], [3, 2, 4], [2, -1, 0] ])
    B = Matrix([1, 2, -1])
    print(Gauss.getResultStatic(A, B))


#!/usr/bin/env python3

import time
import random
import sys
import datetime
import time as time_
import argparse
from influxdb import InfluxDBClient

gstart_time = 0
gend_time = 0
ginterval = 0
gsilent = False
ghostname = "localhost"
gport = "8086"

def str2bool(v):
    if v.lower() in ('yes', 'true', 't', 'y', '1'):
        return True
    elif v.lower() in ('no', 'false', 'f', 'n', '0'):
        return False
    else:
        raise argparse.ArgumentTypeError('Boolean value expected.')

#Parse command line arguments
argParser = argparse.ArgumentParser(description = 'Prime and start pages_db for influxdb/kapacitor demo.')
argParser.add_argument("--silent", type=str2bool, metavar='',help='Do not print excess records to console')
argParser.add_argument("--hostname", metavar='',help='Hostname of target influxdb')
argParser.add_argument("--port", metavar='', help='Port of target influxdb')
subparsers = argParser.add_subparsers(help='sub-commmand prime', dest='command')
parser_prime = subparsers.add_parser('prime', description = 'Prime the influxdb with datapoints in the past.')
parser_run = subparsers.add_parser('run', description = 'Start the generator to write datapoints ever 15s continuously. Exit with CTRL+C')
parser_pnr = subparsers.add_parser('pnr', description = 'Prime the db and Run generator to write datapoints ever 15s continuously. Exit with CTRL+C')
parser_prime.add_argument('--start', metavar='', help='start time of the dataset, point in the past, e.g. 1d (ago), 12h (ago), etc.', required=True)
parser_prime.add_argument('--end', metavar='', help='end time of the dataset, point in the past or 0d (now), 1h (ago), etc. (default 0h)', default='0h')
parser_prime.add_argument('--step', metavar='', help='interval between datapoints. e.g. 5s, 1m, 10m, 100ms (default 15s)', default='15s')
parser_run.add_argument('--step', metavar='', help='interval between datapoints. e.g. 5s, 1m, 10m, 100ms (default 15s)', default='15s')
parser_pnr.add_argument('--start', metavar='', help='start time of the dataset, point in the past, e.g. 1d (ago), 12h (ago), etc.', required=True)
parser_pnr.add_argument('--end', metavar='', help='end time of the dataset, point in the past or 0d (now), 1h (ago), etc. (default 0h)', default='0h')
parser_pnr.add_argument('--step', metavar='', help='interval between datapoints. e.g. 5s, 1m, 10m, 100ms (default 15s)', default='15s')

args = argParser.parse_args()

if hasattr(args, 'hostname'):
    ghostnamae = args.hostname

if hasattr(args, 'port'):
    gport = args.port

if hasattr(args, 'silent'):
    gsilent = args.silent

database_name = "pages"
client = InfluxDBClient("localhost","8086")
client.create_database(database_name)
print("Created database ", database_name)

### A class for a simple datapoint
class simpleDP:
    def __init__(self, measurement, tags, fields):
        self.measurement = measurement
        self.tags = tags
        self.fields = fields

    def toJson(self):
        json = []
        json.append({'measurement': self.measurement,
                     'tags': self.tags,
                     'fields': self.fields })
        return json;

    def toLineWithTime(self, time):
        if time == -1:
            time = int(time_.time() * 1000)
        line = self.measurement
        for tag in self.tags:
            line = line + "," + tag + "=" + self.tags[tag]

        line = line + " "
        for i,field in enumerate(self.fields):
            if( i == 0):
                line = line + field + "=" + str(self.fields[field])
            else:
                line = line + "," + field + "=" + str(self.fields[field])

        line = line + " " + str(time * 1000000)
        return line

    def toJsonWithTime(self, time):
        json = []
        if time == -1:
            time = int(time_.time() * 1000)
        json.append({'measurement': self.measurement,
                     'tags': self.tags,
                     'fields': self.fields,
                     'time': time * 1000000})
        return json

    def walk_integer(self, field_name, max_val, min_val, max_change, min_change):
        change = random.randint(min_change, max_change);
        self.fields[field_name] = self.fields[field_name] + change
        if self.fields[field_name] > max_val:
            self.fields[field_name] = max_val
        elif self.fields[field_name] < min_val:
            self.fields[field_name] = min_val

testDPs = [ simpleDP('errors', {'page': 'page-01'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-01'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-02'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-02'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-03'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-03'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-04'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-04'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-05'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-05'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-06'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-06'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-07'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-07'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-08'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-08'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-09'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-09'}, {'value': random.randint(100,900)}),
            simpleDP('errors', {'page': 'page-10'},{'value': random.randint(0,10)}),
            simpleDP('views', {'page': 'page-10'}, {'value': random.randint(100,900)})]

#Prime the database - all args should be int milliseconds e.g. 1525953716980
def prime_db(start_time, end_time, step):
    current_time = start_time
    points = []
    while current_time < end_time:
        for dp in testDPs:
            if dp.measurement == 'errors':
                dp.walk_integer('value', 10, 0, 3, -3)
            else:
                dp.walk_integer('value', 1000, 1, 100, -100)
            if not gsilent:
                print(dp.toLineWithTime(current_time))
            points.append(dp.toLineWithTime(current_time))
        client.write_points(points, database=database_name, protocol='line', batch_size=1000)
        if not gsilent:
            sys.stdout.flush()
        del points[:]
        current_time = current_time + step

def run_live():
    points = []
    while True:
        time.sleep(15)
        for dp in testDPs:
            if dp.measurement == 'errors':
                dp.walk_integer('value', 10, 0, 3, -3)
            else:
                dp.walk_integer('value', 1000, 1, 100, -100)
            if not gsilent:
                print(dp.toJsonWithTime(-1))
                print(dp.toLineWithTime(-1))
            points.append(dp.toLineWithTime(-1))
        if gsilent:
            print('.', end='', flush=True)
        client.write_points(points,database=database_name,protocol='line')
        sys.stdout.flush()
        del points[:]

milliseconds_per_unit = {"s": 1000, "m": 60000, "h": 3600000, "d": 86400000, 'w': 604800000}

def convert_to_milliseconds(t):
    return int(t[:-1]) * milliseconds_per_unit[t[-1]]

def prime():
    if args.start[-2:] != "ms":
        gstart_time = convert_to_milliseconds(args.start)
    else:
        gstart_time = args.start[:-2]

    if args.end[-2:] != "ms":
        gend_time = convert_to_milliseconds(args.end)
    else:
        gend_time = args.end[:-2]

    if args.step[-2:] != "ms":
        ginterval = convert_to_milliseconds(args.step)
    else:
        ginterval = args.step[:-2]

    now = int(time_.time()) * 1000
    # if gend_time is 0 then now
    gstart_time = now - gstart_time
    gend_time = now - gend_time

    prime_db(gstart_time, gend_time, ginterval)

def run():
    run_live()

if args.command == 'prime':
    print("starting prime")
    prime()
elif args.command == 'run':
    print("starting run")
    run()
elif args.command == 'pnr':
    print("priming and running")
    prime()
    print("data primed\ngenerator now running. CTRL+C to stop")
    run()
else:
    argParser.print_usage()


from typing import Set, Any, Dict, List
import collections

import data_algebra.expr_rep
import data_algebra.pipe
import data_algebra.env
import data_algebra.pending_eval

have_black = False
try:
    # noinspection PyUnresolvedReferences
    import black
    have_black = True
except ImportError:
    pass

have_sqlparse = False
try:
    # noinspection PyUnresolvedReferences
    import sqlparse
    have_sqlparse = True
except ImportError:
    pass

class ViewRepresentation(data_algebra.pipe.PipeValue):
    """Structure to represent the columns of a query or a table.
       Abstract base class."""

    column_names: List[str]
    column_set: Set[str]
    column_map: data_algebra.env.SimpleNamespaceDict
    sources: List[Any]  # actually ViewRepresentation

    def __init__(self, column_names, *, sources=None):
        self.column_names = [c for c in column_names]
        for ci in self.column_names:
            if not isinstance(ci, str):
                raise Exception("non-string column name(s)")
        if len(self.column_names) < 1:
            raise Exception("no column names")
        self.column_set = set(self.column_names)
        if not len(self.column_names) == len(self.column_set):
            raise Exception("duplicate column name(s)")
        column_dict = {
            ci: data_algebra.expr_rep.ColumnReference(self, ci)
            for ci in self.column_names
        }
        self.column_map = data_algebra.env.SimpleNamespaceDict(**column_dict)
        if sources is None:
            sources = []
        for si in sources:
            if not isinstance(si, ViewRepresentation):
                raise Exception("all sources must be of class ViewRepresentation")
        self.sources = [si for si in sources]
        data_algebra.pipe.PipeValue.__init__(self)

    # characterization

    def get_tables(self, tables=None):
        """get a dictionary of all tables used in an operator DAG,
        raise an exception if the values are not consistent"""
        if tables is None:
            tables = {}
        for s in self.sources:
            tables = s.get_tables(tables)
        return tables

    def columns_used_from_sources(self, using=None):
        """Give column names used from source nodes when this node is exececuted
        with the using columns (None means all)."""
        raise Exception("base method called")

    def columns_used_implementation(self, *, columns_used, using=None):
        cu_list = self.columns_used_from_sources(using)
        for i in range(len(self.sources)):
            self.sources[i].columns_used_implementation(
                columns_used=columns_used, using=cu_list[i]
            )

    def columns_used(self):
        """Determine which columns are used from source tables."""
        tables = self.get_tables()
        columns_used = {ki: set() for ki in tables.keys()}
        self.columns_used_implementation(columns_used=columns_used, using=None)
        return columns_used

    # collect as simple structures for YAML I/O and other generic tasks

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        raise Exception("base method called")

    def collect_representation(self, *, pipeline=None, dialect='Python'):
        """Collect a representation of the operator DAG as simple serializable objects.
                   These objects can be saved/loaded in YAML format and also can rebuild the
                   pipeline via data_algebra.yaml.to_pipeline()."""
        self.get_tables()  # for table consistency check/raise
        return self.collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    # printing

    def to_python_implementation(self, *, indent=0, strict=True):
        return "ViewRepresentation(" + self.column_names.__repr__() + ")"

    def to_python(self, *, indent=0, strict=True, pretty=False, black_mode=None):
        global have_black
        self.get_tables()  # for table consistency check/raise
        if pretty:
            strict = True
        python_str = self.to_python_implementation(indent=indent, strict=strict)
        if pretty and have_black:
            if black_mode is None:
                black_mode = black.FileMode()
            python_str = black.format_str(python_str, mode=black_mode)
        return python_str

    def __repr__(self):
        return self.to_python(strict=True)

    def __str__(self):
        return self.to_python(strict=True)

    # query generation

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        raise Exception("base method called")

    def to_sql(self, db_model,
               *,
               pretty=False,
               encoding=None,
               sqlparse_options=None):
        global have_sqlparse
        if sqlparse_options is None:
            sqlparse_options = {'reindent': True,
                                'keyword_case': 'upper'}
        self.get_tables()  # for table consistency check/raise
        temp_id_source = [0]
        sql_str = self.to_sql_implementation(
            db_model=db_model, using=None, temp_id_source=temp_id_source
        )
        if pretty and have_sqlparse:
            sql_str = sqlparse.format(sql_str, encoding=encoding, **sqlparse_options)
        return sql_str

    # Pandas realization

    def eval_pandas(self, data_map):
        """
        Evaluate pipeline taking tables by name from data_map
        :param data_map: Dict[str, pandas.DataFrame]
        :return: pandas.DataFrame
        """
        raise Exception("base method called")

    # define builders for all non-leaf node types on base class

    def extend(self, ops, *, partition_by=None, order_by=None, reverse=None):
        return ExtendNode(
            source=self,
            ops=ops,
            partition_by=partition_by,
            order_by=order_by,
            reverse=reverse,
        )

    def project(self, ops, *, group_by=None, order_by=None, reverse=None):
        raise Exception("not implmented yet")
        # return ProjectNode(
        #     source=self,
        #     ops=ops,
        #     group_by=group_by,
        #     order_by=order_by,
        #     reverse=reverse,
        # )

    def natural_join(self, b, *, by=None, jointype="INNER"):
        if not isinstance(b, ViewRepresentation):
            raise Exception(
                "expected b to be a data_algebra.dat_ops.ViewRepresentation"
            )
        return NaturalJoinNode(a=self, b=b, by=by, jointype=jointype)

    def select_rows(self, expr):
        return SelectRowsNode(source=self, expr=expr)

    def drop_columns(self, column_deletions):
        return DropColumnsNode(source=self, column_deletions=column_deletions)

    def select_columns(self, columns):
        return SelectColumnsNode(source=self, columns=columns)

    def rename_columns(self, column_remapping):
        return RenameColumnsNode(source=self, column_remapping=column_remapping)

    def order_rows(self, columns, *, reverse=None, limit=None):
        return OrderRowsNode(source=self, columns=columns, reverse=reverse, limit=limit)

class TableDescription(ViewRepresentation):
    """Describe columns, and qualifiers, of a table.

       If outer namespace is set user values are visible and
       _-side effects can be written back.

       Example:
           from data_algebra.data_ops import *
           import data_algebra.env
           with data_algebra.env.Env(globals()) as env:
               d = TableDescription('d', ['x', 'y'])
           print(_) # should be a SimpleNamespaceDict, not d/ViewRepresentation
           print(d)
    """

    table_name: str
    qualifiers: Dict[str, str]
    key: str

    def __init__(self, table_name, column_names, *, qualifiers=None):
        ViewRepresentation.__init__(self, column_names=column_names)
        if (table_name is not None) and (not isinstance(table_name, str)):
            raise Exception("table_name must be a string")
        self.table_name = table_name
        self.column_names = column_names.copy()
        if qualifiers is None:
            qualifiers = {}
        if not isinstance(qualifiers, dict):
            raise Exception("qualifiers must be a dictionary")
        self.qualifiers = qualifiers.copy()
        key = ""
        if len(self.qualifiers) > 0:
            keys = [k for k in self.qualifiers.keys()]
            keys.sort()
            key = "{"
            for k in keys:
                key = key + "(" + k + ", " + str(self.qualifiers[k]) + ")"
            key = key + "}."
        self.key = key + self.table_name

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "TableDescription"
        od["table_name"] = self.table_name
        od["qualifiers"] = self.qualifiers.copy()
        od["column_names"] = self.column_names
        od["key"] = self.key
        pipeline.insert(0, od)
        return pipeline

    def to_python_implementation(self, *, indent=0, strict=True):
        nc = min(len(self.column_names), 20)
        if (not strict) and (nc < len(self.column_names)):
            cols_str = (
                "["
                + ", ".join([self.column_names[i].__repr__() for i in range(nc)])
                + ", + "
                + str(len(self.column_names) - nc)
                + " more]"
            )
        else:
            cols_str = self.column_names.__repr__()
        s = (
            "TableDescription("
            + "table_name="
            + self.table_name.__repr__()
            + ", column_names="
            + cols_str
        )
        if len(self.qualifiers) > 0:
            s = s + ", qualifiers=" + self.qualifiers.__repr__()
        s = s + ")"
        return s

    def get_tables(self, tables=None):
        """get a dictionary of all tables used in an operator DAG,
        raise an exception if the values are not consistent"""
        if tables is None:
            tables = {}
        if self.key in tables.keys():
            other = tables[self.key]
            if self.column_set != other.column_set:
                raise Exception(
                    "Two tables with key " + self.key + " have different column sets."
                )
        else:
            tables[self.key] = self
        return tables

    def eval_pandas(self, data_map):
        if len(self.qualifiers) > 0:
            raise Exception(
                "table descriptions used with eval_pandas() must not have qualifiers"
            )
        # make an index-free copy of the data to isolate side-effects and not deal with indices
        res = data_map[self.table_name]
        res = res.copy()
        res.reset_index(drop=True, inplace=True)
        return res

    def columns_used_from_sources(self, using=None):
        return []  # no inputs to table description

    def columns_used_implementation(self, *, columns_used, using=None):
        cset = columns_used[self.key]
        if using is None:
            using = self.column_set
        unexpected = using - self.column_set
        if len(unexpected) > 0:
            raise Exception("asked for undefined columns: " + str(unexpected))
        cset.update(using)

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.table_def_to_sql(self, using=using)

    # comparable to other table descriptions
    def __lt__(self, other):
        if not isinstance(other, TableDescription):
            return True
        return self.key.__lt__(other.key)

    def __eq__(self, other):
        if not isinstance(other, TableDescription):
            return False
        return self.key.__eq__(other.key)

    def __hash__(self):
        return self.key.__hash__()

def describe_pandas_table(d, table_name):
    return TableDescription(table_name, [c for c in d.columns])

class ExtendNode(ViewRepresentation):
    ops: Dict[str, data_algebra.expr_rep.Expression]

    def __init__(self, source, ops, *, partition_by=None, order_by=None, reverse=None):
        ops = data_algebra.expr_rep.check_convert_op_dictionary(
            ops, source.column_map.__dict__
        )
        if len(ops) < 1:
            raise Exception("no ops")
        self.ops = ops
        if partition_by is None:
            partition_by = []
        if isinstance(partition_by, str):
            partition_by = [partition_by]
        self.partition_by = partition_by
        if order_by is None:
            order_by = []
        if isinstance(order_by, str):
            order_by = [order_by]
        self.order_by = order_by
        if reverse is None:
            reverse = []
        if isinstance(reverse, str):
            reverse = [reverse]
        self.reverse = reverse
        column_names = source.column_names.copy()
        consumed_cols = set()
        for (k, o) in ops.items():
            o.get_column_names(consumed_cols)
        unknown_cols = consumed_cols - source.column_set
        if len(unknown_cols) > 0:
            raise Exception("referred to unknown columns: " + str(unknown_cols))
        known_cols = set(column_names)
        for ci in ops.keys():
            if ci not in known_cols:
                column_names.append(ci)
        if len(partition_by) != len(set(partition_by)):
            raise Exception("Duplicate name in partition_by")
        if len(order_by) != len(set(order_by)):
            raise Exception("Duplicate name in order_by")
        if len(reverse) != len(set(reverse)):
            raise Exception("Duplicate name in reverse")
        unknown = set(partition_by) - known_cols
        if len(unknown) > 0:
            raise Exception("unknown partition_by columns: " + str(unknown))
        unknown = set(order_by) - known_cols
        if len(unknown) > 0:
            raise Exception("unknown order_by columns: " + str(unknown))
        unknown = set(reverse) - set(order_by)
        if len(unknown) > 0:
            raise Exception("reverse columns not in order_by: " + str(unknown))
        bad_overwrite = set(ops.keys()).intersection(
            set(partition_by).union(order_by, reverse)
        )
        if len(bad_overwrite) > 0:
            raise Exception("tried to change: " + str(bad_overwrite))
        ViewRepresentation.__init__(self, column_names=column_names, sources=[source])

    def columns_used_from_sources(self, using=None):
        columns_we_take = self.sources[0].column_set.copy()
        if using is None:
            return [columns_we_take]
        subops = {k: op for (k, op) in self.ops.items() if k in using}
        if len(subops) <= 0:
            return [columns_we_take]
        columns_we_take = using.union(self.partition_by, self.order_by, self.reverse)
        columns_we_take = columns_we_take - subops.keys()
        for (k, o) in subops.items():
            o.get_column_names(columns_we_take)
        return [columns_we_take]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "Extend"
        od["ops"] = {ci: vi.to_source(dialect=dialect) for (ci, vi) in self.ops.items()}
        od["partition_by"] = self.partition_by
        od["order_by"] = self.order_by
        od["reverse"] = self.reverse
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        s = (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "extend({"
            + ", ".join(
                [
                    k.__repr__() + ": " + opi.to_python().__repr__()
                    for (k, opi) in self.ops.items()
                ]
            )
            + "}"
        )
        if len(self.partition_by) > 0:
            s = s + ", partition_by=" + self.partition_by.__repr__()
        if len(self.order_by) > 0:
            s = s + ", order_by=" + self.order_by.__repr__()
        if len(self.reverse) > 0:
            s = s + ", reverse=" + self.reverse.__repr__()
        s = s + ")"
        return s

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.extend_to_sql(self, using=using, temp_id_source=temp_id_source)

    def eval_pandas(self, data_map):
        window_situation = (len(self.partition_by) > 0) or (len(self.order_by) > 0)
        if window_situation:
            # check these are forms we are prepared to work with
            for (k, op) in self.ops.items():
                if len(op.args) > 1:
                    raise Exception(
                        "non-trivial windows expression: " + str(k) + ": " + str(op)
                    )
                if len(op.args) == 1:
                    if not isinstance(
                        op.args[0], data_algebra.expr_rep.ColumnReference
                    ):
                        raise Exception(
                            "windows expression argument must be a column: "
                            + str(k)
                            + ": "
                            + str(op)
                        )
        res = self.sources[0].eval_pandas(data_map)
        res.reset_index(inplace=True, drop=True)
        if not window_situation:
            for (k, op) in self.ops.items():
                res[k] = res.eval(op.to_pandas())
        else:
            for (k, op) in self.ops.items():
                # work on a slice of the data frame
                col_list = [c for c in set(self.partition_by)]
                for c in self.order_by:
                    if c not in col_list:
                        col_list = col_list + [c]
                value_name = None
                if len(op.args) > 0:
                    value_name = op.args[0].to_pandas()
                    if value_name not in set(col_list):
                        col_list = col_list + [value_name]
                ascending = [c not in set(self.reverse) for c in col_list]
                subframe = res[col_list].copy()
                subframe.reset_index(inplace=True, drop=True)
                subframe['_data_algebra_orig_index'] = [i for i in range(subframe.shape[0])]
                subframe.sort_values(by=col_list, ascending=ascending, inplace=True)
                subframe.reset_index(inplace=True, drop=True)
                if len(self.partition_by) > 0:
                    opframe = subframe.groupby(self.partition_by)
                    #  Groupby preserves the order of rows within each group.
                    # https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.groupby.html
                else:
                    opframe = subframe
                if len(op.args) == 0:
                    if op.op == "row_number":
                        subframe[k] = opframe.cumcount() + 1
                    else:  # TODO: more of these
                        raise Exception("not implemented: " + str(k) + ": " + str(op))
                else:
                    # len(op.args) == 1
                    subframe[k] = opframe[value_name].transform(op.op)
                subframe.reset_index(inplace=True, drop=True)
                subframe.sort_values(by=['_data_algebra_orig_index'], inplace=True)
                subframe.reset_index(inplace=True, drop=True)
                res[k] = subframe[k]
        return res

class SelectRowsNode(ViewRepresentation):
    expr: data_algebra.expr_rep.Expression
    decision_columns: Set[str]

    def __init__(self, source, expr):
        ops = data_algebra.expr_rep.check_convert_op_dictionary(
            {"expr": expr}, source.column_map.__dict__
        )
        if len(ops) < 1:
            raise Exception("no ops")
        self.expr = ops["expr"]
        self.decision_columns = set()
        self.expr.get_column_names(self.decision_columns)
        ViewRepresentation.__init__(
            self, column_names=source.column_names, sources=[source]
        )

    def columns_used_from_sources(self, using=None):
        columns_we_take = self.sources[0].column_set.copy()
        if using is None:
            return [columns_we_take]
        columns_we_take = columns_we_take.intersection(using)
        columns_we_take = columns_we_take.union(self.decision_columns)
        return [columns_we_take]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "SelectRows"
        od["expr"] = self.expr.to_source(dialect=dialect)
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        s = (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "select_rows("
            + self.expr.to_python().__repr__()
            + ")"
        )
        return s

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.select_rows_to_sql(
            self, using=using, temp_id_source=temp_id_source
        )

    def eval_pandas(self, data_map):
        res = self.sources[0].eval_pandas(data_map)
        res = res.query(self.expr.to_pandas())
        res.reset_index(inplace=True, drop=True)
        return res

class SelectColumnsNode(ViewRepresentation):
    column_selection: List[str]

    def __init__(self, source, columns):
        column_selection = [c for c in columns]
        self.column_selection = column_selection
        # TODO: check column conditions
        ViewRepresentation.__init__(
            self, column_names=column_selection, sources=[source]
        )

    def columns_used_from_sources(self, using=None):
        cols = set(self.column_selection.copy())
        if using is None:
            return [cols]
        return [cols.intersection(using)]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "SelectColumns"
        od["columns"] = self.column_selection
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        s = (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "select_columns("
            + self.column_selection.__repr__()
            + ")"
        )
        return s

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.select_columns_to_sql(
            self, using=using, temp_id_source=temp_id_source
        )

    def eval_pandas(self, data_map):
        res = self.sources[0].eval_pandas(data_map)
        return res[self.column_selection]

class DropColumnsNode(ViewRepresentation):
    column_deletions: List[str]

    def __init__(self, source, column_deletions):
        column_deletions = [c for c in column_deletions]
        self.column_deletions = column_deletions
        remaining_columns = [c for c in source.column_names if c not in column_deletions]
        # TODO: check column conditions
        ViewRepresentation.__init__(
            self, column_names=remaining_columns, sources=[source]
        )

    def columns_used_from_sources(self, using=None):
        if using is None:
            using = set(self.sources[0].column_names)
        return [set([c for c in using if c not in self.column_deletions])]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "DropColumns"
        od["column_deletions"] = self.column_deletions
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        s = (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "drop_columns("
            + self.column_deletions.__repr__()
            + ")"
        )
        return s

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.drop_columns_to_sql(
            self, using=using, temp_id_source=temp_id_source
        )

    def eval_pandas(self, data_map):
        res = self.sources[0].eval_pandas(data_map)
        column_selection = [c for c in res.columns if c not in self.column_deletions]
        return res[column_selection]

class OrderRowsNode(ViewRepresentation):
    order_columns: List[str]
    reverse: List[str]

    def __init__(self, source, columns, *, reverse=None, limit=None):
        self.order_columns = [c for c in columns]
        if reverse is None:
            reverse = []
        self.reverse = [c for c in reverse]
        self.limit = limit
        # TODO: check column conditions
        ViewRepresentation.__init__(
            self, column_names=source.column_names, sources=[source]
        )

    def columns_used_from_sources(self, using=None):
        cols = set(self.column_names.copy())
        if using is None:
            return [cols]
        cols = cols.intersection(using).union(self.order_columns)
        return [cols]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "Order"
        od["order_columns"] = self.order_columns
        od["reverse"] = self.reverse
        od["limit"] = self.limit
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        s = (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "order_rows("
            + self.order_columns.__repr__()
        )
        if len(self.reverse) > 0:
            s = s + ", reverse=" + self.reverse.__repr__()
        if self.limit is not None:
            s = s + ", limit=" + self.limit.__repr__()
        s = s + ")"
        return s

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.order_to_sql(self, using=using, temp_id_source=temp_id_source)

    def eval_pandas(self, data_map):
        res = self.sources[0].eval_pandas(data_map)
        ascending = [False if ci in set(self.reverse) else True for ci in self.order_columns]
        res.sort_values(by=self.order_columns, ascending=ascending)
        return res

class RenameColumnsNode(ViewRepresentation):
    column_remapping: Dict[str, str]
    reverse_mapping: Dict[str, str]
    mapped_columns: Set[str]

    def __init__(self, source, column_remapping):
        self.column_remapping = column_remapping.copy()
        self.reverse_mapping = {v: k for (k, v) in self.column_remapping.items()}
        self.mapped_columns = set(self.column_remapping.keys()).union(
            set(self.reverse_mapping.keys())
        )
        column_names = [
            (k if k not in self.reverse_mapping.keys() else self.reverse_mapping[k])
            for k in source.column_names
        ]
        # TODO: check column conditions, don't allow name collisions
        ViewRepresentation.__init__(self, column_names=column_names, sources=[source])

    def columns_used_from_sources(self, using=None):
        if using is None:
            using = self.column_names
        cols = [
            (k if k not in self.column_remapping.keys() else self.column_remapping[k])
            for k in using
        ]
        return [set(cols)]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "Rename"
        od["column_remapping"] = self.column_remapping
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        s = (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "rename_columns("
            + self.column_remapping.__repr__()
            + ")"
        )
        return s

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.rename_to_sql(self, using=using, temp_id_source=temp_id_source)

    def eval_pandas(self, data_map):
        res = self.sources[0].eval_pandas(data_map)
        return res.rename(columns=self.reverse_mapping)

class NaturalJoinNode(ViewRepresentation):
    by: List[str]
    jointype: str

    def __init__(self, a, b, *, by=None, jointype="INNER"):
        sources = [a, b]
        column_names = sources[0].column_names.copy()
        for ci in sources[1].column_names:
            if ci not in sources[0].column_set:
                column_names.append(ci)
        if isinstance(by, str):
            by = [by]
        by_set = set(by)
        if len(by) != len(by_set):
            raise Exception("duplicate column names in by")
        missing_left = by_set - a.column_set
        if len(missing_left) > 0:
            raise Exception("left table missing join keys: " + str(missing_left))
        missing_right = by_set - b.column_set
        if len(missing_right) > 0:
            raise Exception("right table missing join keys: " + str(missing_right))
        self.by = by
        self.jointype = jointype
        ViewRepresentation.__init__(self, column_names=column_names, sources=sources)

    def columns_used_from_sources(self, using=None):
        if using is None:
            return [self.sources[i].column_set.copy() for i in range(2)]
        using = using.union(self.by)
        return [self.sources[i].column_set.intersection(using) for i in range(2)]

    def collect_representation_implementation(self, *, pipeline=None, dialect='Python'):
        if pipeline is None:
            pipeline = []
        od = collections.OrderedDict()
        od["op"] = "NaturalJoin"
        od["by"] = self.by
        od["jointype"] = self.jointype
        od["b"] = self.sources[1].collect_representation_implementation(dialect=dialect)
        pipeline.insert(0, od)
        return self.sources[0].collect_representation_implementation(pipeline=pipeline, dialect=dialect)

    def to_python_implementation(self, *, indent=0, strict=True):
        return (
            self.sources[0].to_python_implementation(indent=indent, strict=strict)
            + " .\\\n"
            + " " * (indent + 3)
            + "natural_join(b=\n"
            + " " * (indent + 6)
            + self.sources[1].to_python_implementation(indent=indent + 6, strict=strict)
            + ",\n"
            + " " * (indent + 6)
            + "by="
            + self.by.__repr__()
            + ", jointype="
            + self.jointype.__repr__()
            + ")"
        )

    def to_sql_implementation(self, db_model, *, using, temp_id_source):
        return db_model.natural_join_to_sql(
            self, using=using, temp_id_source=temp_id_source
        )


import argparse
from facenet_pytorch import MTCNN, InceptionResnetV1
from get_file_img import interp_pair
import os.path
import torchvision.transforms as transforms
import torch
import numpy as np
from PIL import Image
import time
import pickle

parser = argparse.ArgumentParser(description='Get Embeddings from the Adience Dataset')

parser.add_argument('--data_dir',default = 'adience', metavar='DIR', type=str,
                    help='Root to Adience dataset')
parser.add_argument('--model', default = 'facenet' ,metavar='MOD', type=str,
                    help='Model to use (senet or facenet or sphereface)')

args = parser.parse_args()

for p in vars(args).items():
    print('  ',p[0]+': ',p[1])
print('\n')

root = args.data_dir

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print('Model on ' + str(device))

# Define the model

if args.model == 'facenet':
# ================ code for facenet ===========================
    model = InceptionResnetV1(pretrained='vggface2').to(device).eval()
    modelName = 'facenet'
    model_input_size = (160,160)

elif args.model == 'facenet-webface':
# ================ code for facenet ===========================
    model = InceptionResnetV1(pretrained='casia-webface').to(device).eval()
    modelName = 'facenet-webface'
    model_input_size = (160,160)

elif args.model == 'sphereface':

# ================ code for sphereface ===========================
    import models.net_sphere
    model = getattr(models.net_sphere,'sphere20a')()
    model.load_state_dict(torch.load('sphereface.pth'))
    model.to(device).eval()
    modelName = 'sphereface'
    model_input_size = (112,96)

elif args.model == 'senet':
    from models.sennet_VGG import senet50_scratch_dag
    model = senet50_scratch_dag('senet50_scratch_dag.pth').to(device).eval()
    modelName = 'senet'
    model_input_size = (244,244)
else:
    raise ValueError('Invalid model choice')

# ethnicities = ['Asian','African','Caucasian','Indian']

embedding_path = os.path.join(root,'embeddings')
embedding_dict = {}

if not os.path.exists(embedding_path):
    os.makedirs(embedding_path)

PILtoTensor = transforms.Compose([transforms.Resize(model_input_size),transforms.ToTensor()])
PILtoTensor_flip = transforms.Compose([transforms.Resize(model_input_size),transforms.RandomHorizontalFlip(1),transforms.ToTensor()])

root = 'adience'

info_path = os.path.join(root,'adience_data.csv')

info = open(info_path,'r')

init_info = open(info_path,'r')

for line in init_info:
    path,age,gender = interp_pair(root,line,dataset = 'adience',aligned = True)
    embedding_dict[path] = None

for i,line in enumerate(info):

    if i % 1000 == 0:
        print('Completed {} images'.format(i))

    if i == 0:
        continue

    path,age,gender = interp_pair(root,line,dataset = 'adience',aligned = True)

    img = Image.open(path)

    with torch.no_grad():
        if args.model == 'sphereface':
            ten = PILtoTensor(img).unsqueeze(0).to(device)
            ten_flip = PILtoTensor_flip(img).unsqueeze(0).to(device)

            input = torch.vstack([ten,ten_flip])
            output = model(input)

            embedding = output[0].unsqueeze(0)

        else:

            input = PILtoTensor(img).unsqueeze(0).to(device)
            output = model(input)

            embedding = output[0].unsqueeze(0)

            if args.model == 'senet':
                embedding = torch.linalg.norm(embedding[1],dim = (2,3))

        embedding_dict[path] = embedding.cpu()

# End get embedding loop

dict_filename = os.path.join(embedding_path,'{}_embeddings.pickle'.format(modelName))
with open(dict_filename,'wb+') as dict_file:
    pickle.dump(embedding_dict,dict_file,protocol=pickle.HIGHEST_PROTOCOL)

#
# if args.save_embed:
#     for line in init_dict_pairs:
#         fold,path1,path2,same,id1,id2,att1,att2,g1,g2,e1,e2  = interp_pair(root,line,dataset = 'adience')
#         embedding_dict[path1] = None
#         embedding_dict[path2] = None


'''
script for dealing with word embeddings
'''

import torch
from torch import nn
import numpy as np
from tqdm import tqdm

'''
initialize embedding tensor with values from the uniform distribution

input param:
    input_embedding: embedding tensor
'''
def init_embedding(input_embedding):
    bias = np.sqrt(3.0 / input_embedding.size(1))
    nn.init.uniform_(input_embedding, -bias, bias)

'''
load pre-trained word embeddings (Glove) for words in the word map

input params:
    emb_file: path to the file containing embeddings (stored in Glove format)
    word_map: word map

return:
    embeddings in the same order as the words in the word map, dimension of embeddings
'''
def load_embeddings(emb_file, word_map):

    # find embedding dimension
    with open(emb_file, 'r') as f:
        emb_size = len(f.readline().split(' ')) - 1
        num_lines = len(f.readlines())

    vocab = set(word_map.keys())

    # create tensor to hold embeddings, initialize
    embeddings = torch.FloatTensor(len(vocab), emb_size)
    init_embedding(embeddings)

    # read embedding file
    for line in tqdm(open(emb_file, 'r'), total = num_lines, desc = 'Loading embeddings'):
        line = line.split(' ')

        emb_word = line[0]
        embedding = list(map(lambda t: float(t), filter(lambda n: n and not n.isspace(), line[1:])))

        # ignore word if not in train_vocab
        if emb_word not in vocab:
            continue

        embeddings[word_map[emb_word]] = torch.FloatTensor(embedding)

    return embeddings, emb_size


import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
import matplotlib.pyplot as plt
data3=pd.read_csv('Iris.csv')
data3
figcls,axcls =  plt.subplots(1,2)
axcls[0].boxplot(data3['SepalLengthCm'])
axcls[1].boxplot(data3['SepalWidthCm'])
axcls[0].set_title('SepalLengthCm')
axcls[1].set_title('SepalWidthCm')
plt.show()
figcls,axcls =  plt.subplots(1,2)
axcls[0].boxplot(data3['PetalLengthCm'])
axcls[1].boxplot(data3['PetalWidthCm'])
axcls[0].set_title('PetalLengthCm')
axcls[1].set_title('PetalWidthCm')
plt.show()
q1cls=data3['SepalWidthCm'].quantile(0.25)
q3cls=data3['SepalWidthCm'].quantile(0.75)
iqrcls=q3cls-q1cls
mincls=q1cls-(1*iqrcls)
maxcls=q3cls+(1*iqrcls)
print(mincls,maxcls)
data3=data3[data3['SepalWidthCm']>=mincls]
data3=data3[data3['SepalWidthCm']<=maxcls]
#data3
figcls,axcls =  plt.subplots(1,2)
axcls[0].boxplot(data3['SepalLengthCm'])
axcls[1].boxplot(data3['SepalWidthCm'])
axcls[0].set_title('SepalLengthCm')
axcls[1].set_title('SepalWidthCm')
plt.show()
figcls,axcls =  plt.subplots(1,2)
axcls[0].boxplot(data3['PetalLengthCm'])
axcls[1].boxplot(data3['PetalWidthCm'])
axcls[0].set_title('PetalLengthCm')
axcls[1].set_title('PetalWidthCm')
plt.show()
clsxtrain,clsxtest,clsytrain,clsytest=train_test_split(data3.iloc[:,1:-1].values,
                                                      data3.iloc[:,-1:],test_size=0.3,random_state=1)
cls1=DecisionTreeClassifier().fit(clsxtrain,clsytrain)
cls1
predcls=cls1.predict(clsxtest)
acc1 = round(metrics.accuracy_score(clsytest, predcls),3)
print('decision tree pred : ',acc1)
sda=tree.export_text(cls1,feature_names=['SepalLengthCm'	,'SepalWidthCm'	,'PetalLengthCm'	,'PetalWidthCm'	])
print(sda)
figcls = plt.figure(figsize=(21,16))
tree.plot_tree(cls1,feature_names=['SepalLengthCm'	,'SepalWidthCm'	,'PetalLengthCm'	,'PetalWidthCm'	],filled=True)
plt.show()


from django.shortcuts import render
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.views.generic import ListView, DetailView
from django.http import HttpResponse
from django.shortcuts import render, redirect
from .forms import PostForm
from .models import Event, Photo, Comment
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm
import uuid
import boto3

# Create your views here.

class EventCreate(CreateView):
    model = Event
    fields = ['title', 'date', 'time', 'location',
            'attendees', 'infolink', 'category', 'description']

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super().form_valid(form)

def events_index(request):
    #   events = Event.objects.filter()
    #   events = request.user.event_set.all()
    events = Event.objects.all()
    return render(request, 'events/index.html', {'events': events})

def category_index(request, event_category):
    events = Event.objects.filter(category=event_category)
    return render(request, 'events/index.html', {'events': events, 'category': event_category})

def events_detail(request, event_id):
    event = Event.objects.get(id=event_id)
    # Instantiate FeedingForm to be rendered in the template
    print(event.id)
    post_form = PostForm()
    return render(request, 'events/detail.html', {
        # Pass the cat and feeding_form as context
        'event': event,
    })

def events_rsvp(request, event_id):
    event = Event.objects.filter(id=event_id)
    print('event  : ', event.values())
    event.values().user = request.user
    print("event after update: ", event.values())
    return redirect('/')
    # return render(request, 'events/detail.html', {
    #     # Pass the cat and feeding_form as context
    #     'event': event,
    # })

def events_comment(request, event_id):
    event = Event.objects.get(id=event_id)
    comment_text = request.POST.__getitem__('comment')
    user = request.user
    new_comment = Comment(event=event, user=user, text=comment_text)
    new_comment.save()
    return redirect('events_detail', event_id=event_id)

def upload_photo(request, event_id):
    event = Event.objects.get(id=event_id)
    return render(request, 'main_app/event_upload_photo.html', {
        # Pass the cat and feeding_form as context
        'event': event
    })

def landing(request):
    return render(request, 'index.html', {'arr': ['Outdoors', 'Entertainment', 'Food', 'Tech', 'Education', 'Health']})

def user(request):

    events = Event.objects.all()
    return render(request, 'user/profile.html', {'contact_name': request.user.first_name, 'events': events})

def events(request):
    return render(request, 'events/index.html', )

def signup(request):
    error_message = ''
    if request.method == 'POST':
        form = UserCreationForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect('/')
        else:
            error_message = 'Invalid Sign up - Try again'
    form = UserCreationForm()
    context = {'form': form, 'error_message': error_message}
    return render(request, 'registration/signup.html', context)

class EventUpdate(UpdateView):
  model = Event
  fields = ['title', 'date', 'time', 'location', 'description', 'attendees', 'infolink', 'category']

class EventDelete(DeleteView):
  model = Event
  success_url = '/events/'

def add_photo(request, event_id):
    event = Event.objects.get(id=event_id)
    S3_BASE_URL = 'https://s3-us-west-1.amazonaws.com/'
    BUCKET = 'dog-sitter'
    # photo-file will be the "name" attribute on the <input type="file">
    photo_file = request.FILES.get('photo-file', None)
    if photo_file:
        s3 = boto3.client('s3')
        # need a unique "key" for S3 / needs image file extension too
        key = uuid.uuid4().hex[:6] + photo_file.name[photo_file.name.rfind('.'):]
        # just in case something goes wrong
        try:
            s3.upload_fileobj(photo_file, BUCKET, key)
            # build the full url string
            url = f"{S3_BASE_URL}{BUCKET}/{key}"
            # we can assign to cat_id or cat (if you have a cat object)
            photo = Photo(url=url, event_id=event_id)
            photo.save()
        except:
            print('An error occurred uploading file to S3')
    return redirect('events_detail', event_id=event_id)


import json
from urllib.request import pathname2url

from django.conf import settings
from django.contrib.sites.models import Site
from django.contrib.syndication.views import Feed
from django.db.models.expressions import F
from django.shortcuts import get_object_or_404
from django.views.generic import ListView, DetailView
from django.http import HttpResponse, Http404

from .models import PodcastIssue
from .tasks import download_and_convert_task

class PodcastFeed(Feed):
    title = "SiliconValleyVoice"
    link = "/"
    feed_url = "/feed/"
    description = "SiliconValleyVoice в MP3".encode("utf-8")
    author_name = "Mikhail Portnov"
    item_enclosure_mime_type = "audio/mpeg"

    def items(self):
        return PodcastIssue.objects.exclude(title__isnull=True).exclude(title__exact="").exclude(skip_feed=True)\
            .exclude(file__exact="").exclude(file__isnull=True)[:50]

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.short_description

    def item_enclosure_url(self, item):
        return "http://{}{}".format(Site.objects.get_current(), item.get_direct_file_url)

    def item_enclosure_length(self, item):
        return item.file.size

    def item_pubdate(self, item):
        return item.pub_date

class PodcastListView(ListView):
    paginate_by = settings.ISSUES_PER_PAGE
    queryset = PodcastIssue.objects.exclude(title__isnull=True).exclude(title__exact="")

class PodcastDetailView(DetailView):
    def get_object(self, queryset=None):
        obj = super().get_object(queryset)
        if obj.file and obj.celery_task:
            obj.celery_task = ""
            obj.save()
        agent = self.request.META.get('HTTP_USER_AGENT', '').lower()
        bots = ('googlebot', 'yandex.com/bots', 'bingbot', 'adidxbot', 'msnbot', 'bingpreview')
        if not [bot for bot in bots if bot in agent]:
            PodcastIssue.objects.filter(pk=obj.pk).update(views=F('views') + 1)
        return obj

    def get_context_data(self, object):
        prev = next = None
        for pk in [item[0] for item in self.queryset.values_list('pk')]:
            if next:
                next = pk
                break
            if pk == object.pk:
                next = True
            else:
                prev = pk
        context = {'prev': prev, 'next': next}
        return super().get_context_data(**context)

    queryset = PodcastIssue.objects.exclude(title__isnull=True).exclude(title__exact="")

def order_converting(request, pk):
    obj = get_object_or_404(PodcastIssue, pk=pk)
    data = {"result": "ok"}
    if not obj.file:
        obj.celery_task = download_and_convert_task.delay(obj.pk, skip_feed=True)
        obj.save()
    return HttpResponse(json.dumps(data), content_type='application/json')

def check_converting_status(request, pk):
    obj = get_object_or_404(PodcastIssue, pk=pk)
    data = {}
    if obj.celery_task:
        result = download_and_convert_task.AsyncResult(obj.celery_task)
        if result.ready():
            if result.failed():
                if not obj.file:
                    data["result"] = "error"
                else:
                    data["result"] = "ok"
                    data["url"] = obj.file.url
                obj.celery_task = ""
                obj.save()
            else:
                data["result"] = "ok"
                data["url"] = obj.file.url
                obj.celery_task = ""
                obj.save()
        else:
            data["result"] = "not_ready"
    else:
        if not obj.file:
            data["result"] = "error"
        else:
            data["result"] = "ok"
            data["url"] = obj.file.url
    return HttpResponse(json.dumps(data), content_type='application/json')

def serve_file(request, pk):
    obj = get_object_or_404(PodcastIssue, pk=pk)
    if not obj.file:
        raise Http404
    PodcastIssue.objects.filter(pk=pk).update(views=F('views') + 1)
    response = HttpResponse()
    response["Content-Type"] = "audio/mpeg"
    response["Content-Disposition"] = "attachment; filename*=UTF-8*''{0}".format(pathname2url(obj.pretty_file_name.encode("utf-8")))
    response['X-Accel-Redirect'] = obj.file.url
    return response


"""

s = UserSession(ub)
s.bind_to_env(env)

u = s.user()
s.setuser(u)

"""
from werkzeug.utils import dump_cookie, parse_cookie
import random
import string
import datetime

class UserSessionMiddleware(object):
    def __init__(self, app, userbase,
                 cookie_name='user_session',
                 cookie_age=None,
                 cookie_expires=None,
                 cookie_path='/',
                 cookie_domain=None,
                 cookie_secure=None,
                 cookie_httponly=False,
                 environ_key='userbase'):

        self.app = app
        self.userbase = userbase
        self.cookie_name = cookie_name
        self.cookie_age = cookie_age
        self.cookie_expires = cookie_expires
        self.cookie_path = cookie_path
        self.cookie_domain = cookie_domain
        self.cookie_secure = cookie_secure
        self.cookie_httponly = cookie_httponly
        self.environ_key = environ_key

    def __call__(self, environ, start_response):

        cookie = parse_cookie(environ)
        user_cookie = cookie.get(self.cookie_name, None)

        usersession = UserSession(self.userbase)
        usersession.set_cookie_value(user_cookie)

        environ[self.environ_key + ".session"] = usersession
        environ[self.environ_key + ".userbase"] = self.userbase

        def injecting_start_response(status, headers, exc_info=None):

            cookie_value = usersession.get_cookie_value()

            cookie_str = dump_cookie(
                self.cookie_name,
                cookie_value if cookie_value is not None else "",
                self.cookie_age,
                None if cookie_value is not None else datetime.datetime.now() - datetime.timedelta(days=1),
                self.cookie_path,
                self.cookie_domain,
                self.cookie_secure,
                self.cookie_httponly)

            headers.append(('Set-Cookie', cookie_str))

            self.userbase.store_changes()

            return start_response(status, headers, exc_info)

        return self.app(environ, injecting_start_response)

class UserSession(object):

    def __init__(self, userbase):
        self.userbase = userbase
        self._user = None
        self._cookie = None

    def set_cookie_value(self, cookie):
        self._cookie = cookie

    def get_cookie_value(self):
        return self._cookie

    def user(self):

        if self._user is None:
            self.__find_user()

        return self._user

    def setuser(self, user):
        self._user = user
        self.update_user_key()

    def clear(self):
        self._cookie = None
        self._user = None

    def update_user_key(self):
        key = self.__generate_key()
        self._user.setfield('sessionkey', key)
        self.__format_cookie(self._user.uid(), key)

    def __find_user(self):
        uid, key = self.__parse_cookie()

        if uid is None:
            self._user = None
            return

        user = self.userbase.getuser(uid)

        if user is None:
            return

        user_key = user.field('sessionkey')

        if user_key == key:
            self._user = user

            #print "Changing user key"
            #self.update_user_key()

        else:
            self._user = None

    def __parse_cookie(self):
        if self._cookie is None:
            return (None, None)

        parts = self._cookie.rsplit(":",1)

        if len(parts) == 2:
            uid = parts[0]
            key = parts[1]
            return uid, key

        else:
            return (None, None)

    def __format_cookie(self, uid, key):
        self._cookie = "%s:%s" % (uid, key)

    def __generate_key(self):
        pool = string.letters + string.digits
        key = ''.join(random.choice(pool) for i in xrange(40))
        return key