# encoding: utf-8

'''

@author: ZiqiLiu

@file: attention_ctc.py

@time: 2017/5/18 上午11:04

@desc:
'''

# !/usr/bin/python
# -*- coding:utf-8 -*-

import tensorflow as tf
import math
import librosa
from utils.common import describe
from positional_encoding import positional_encoding_op
from utils.stft import tf_frame
from utils.mfcc import mfcc

def self_attention(inputs, config, is_training, scope_name='self_attention'):
    # inputs - [batch_size, time_steps, model_size]
    # return - [batch_size, time_steps, model_size]
    assert (config.hidden_size % config.multi_head_num == 0)
    head_size = config.hidden_size // config.multi_head_num
    with tf.variable_scope(scope_name):
        combined = tf.layers.conv2d(
            tf.expand_dims(inputs, 2), 3 * config.hidden_size,
            (1, 1), name="qkv_transform")
        q, k, v = tf.split(
            tf.squeeze(combined, 2),
            [config.hidden_size, config.hidden_size, config.hidden_size],
            axis=2)

        q_ = tf.concat(tf.split(q, config.multi_head_num, axis=2),
                       axis=0)  # (h * B, T, N / h)
        k_ = tf.concat(tf.split(k, config.multi_head_num, axis=2),
                       axis=0)  # (h * B, T, N / h)
        v_ = tf.concat(tf.split(v, config.multi_head_num, axis=2),
                       axis=0)  # (h * B, T, N / h)

        a = tf.matmul(q_, tf.transpose(k_, [0, 2, 1]))  # (h * B, T, T)
        a = tf.nn.softmax(a / math.sqrt(head_size))
        if is_training:
            a = tf.nn.dropout(a, config.keep_prob)
        a = tf.matmul(a, v_)  # [h * B, T, N / h]

        outputs = tf.concat(tf.split(a, config.multi_head_num, axis=0),
                            axis=2)  # [B, T, N]

    return outputs

def feed_forward(inputs, config, scope_name='feed_forward'):
    # inputs - [batch_size, time_steps, model_size]
    # return - [batch_size, time_steps, model_size]
    with tf.variable_scope(scope_name):
        inners = tf.layers.conv2d(
            tf.expand_dims(inputs, 2), config.feed_forward_inner_size,
            (1, 1), activation=tf.nn.relu, name="conv1")  # [B, T, 1, F]
        outputs = tf.layers.conv2d(
            inners, config.hidden_size, (1, 1), name="conv2")  # [B, T, 1, F]
    return tf.squeeze(outputs, 2)

def inference(inputs, seqLengths, config, is_training, batch_size=None):
    if not batch_size:
        batch_size = config.batch_size
    # positional encoding
    max_length = tf.shape(inputs)[1]
    if config.combine_frame > 1:
        padding = tf.zeros([1, 1, config.freq_size])
        padding = tf.tile(padding,
                          [batch_size,
                           config.combine_frame - tf.mod(max_length,
                                                         config.combine_frame),
                           1])
        inputs = tf.concat([inputs, padding], 1)
        inputs = tf.reshape(inputs, [batch_size, -1,
                                     config.freq_size * config.combine_frame])
        seqLengths = seqLengths // config.combine_frame + 1
        max_length = max_length // config.combine_frame + 1

    inputs = tf.layers.conv2d(
        tf.expand_dims(inputs, 2), config.hidden_size, (1, 1),
        name='input_linear_trans')  # [B, T, 1, F]
    inputs = tf.squeeze(inputs, 2)  # [B, T, F]

    pe = positional_encoding_op.positional_encoding(
        max_length, config.hidden_size)
    inputs = inputs + pe

    layer_inputs = inputs
    for j in range(config.num_layers):
        with tf.variable_scope('layer_%d' % j):
            # self attention sub-layer
            attention_outputs = self_attention(layer_inputs, config,
                                               is_training)
            if is_training:
                attention_outputs = tf.nn.dropout(
                    attention_outputs, config.keep_prob)
            # add and norm
            feed_forward_inputs = tf.contrib.layers.layer_norm(
                attention_outputs + layer_inputs)
            # feed forward sub-layer
            feed_forward_outputs = feed_forward(feed_forward_inputs, config)
            if is_training:
                feed_forward_outputs = tf.nn.dropout(
                    feed_forward_outputs, config.keep_prob)
            # add and norm
            layer_outputs = tf.contrib.layers.layer_norm(
                feed_forward_outputs + feed_forward_inputs)
            layer_inputs = layer_outputs

    outputs = tf.layers.conv2d(
        tf.expand_dims(layer_outputs, 2), config.num_classes,
        (1, 1), name='output_linear_trans')  # [B, T, 1, F]
    outputs = tf.squeeze(outputs, 2)  # [B, T, F]
    if config.use_relu:
        outputs = tf.nn.relu(outputs)
    return outputs, seqLengths

class Attention(object):
    def __init__(self, config, input, is_train):
        self.config = config
        if is_train:
            stager, self.stage_op, self.input_filequeue_enqueue_op = input
            # we only use 1 gpu
            self.inputX, self.label_values, self.label_indices, self.label_dense_shape, self.seqLengths = stager.get()
            self.label_batch = tf.SparseTensor(
                self.label_indices,
                tf.cast(self.label_values, tf.int32),
                self.label_dense_shape)
            self.build_graph(config, is_train)
        else:
            stager, self.stage_op, self.input_filequeue_enqueue_op = input
            self.inputX, self.seqLengths, self.correctness, self.labels = stager.get()
            self.build_graph(config, is_train)

    @describe
    def build_graph(self, config, is_train):

        self.nn_outputs, self.new_seqLengths = inference(self.inputX,
                                                         self.seqLengths,
                                                         config, is_train)
        self.ctc_input = tf.transpose(self.nn_outputs, perm=[1, 0, 2])

        if is_train:
            self.label_dense = tf.sparse_tensor_to_dense(self.label_batch)
            self.ctc_loss = tf.nn.ctc_loss(inputs=self.ctc_input,
                                           labels=self.label_batch,
                                           sequence_length=self.new_seqLengths,
                                           ctc_merge_repeated=True,
                                           preprocess_collapse_repeated=False,
                                           time_major=True)
            self.loss = tf.reduce_sum(self.ctc_loss) / config.batch_size
            self.global_step = tf.Variable(0, trainable=False)
            self.reset_global_step = tf.assign(self.global_step, 1)

            initial_learning_rate = tf.Variable(
                config.learning_rate, trainable=False)

            self.learning_rate = tf.train.exponential_decay(
                initial_learning_rate, self.global_step, self.config.decay_step,
                self.config.lr_decay, name='lr')
            if config.warmup:
                self.warmup_lr = tf.train.polynomial_decay(5e-3,
                                                           self.global_step,
                                                           40000, 1.35e-3, 0.5)
                self.post_lr = tf.train.exponential_decay(
                    1.5e-3, self.global_step, self.config.decay_step,
                    self.config.lr_decay, name='lr')
                self.learning_rate = tf.minimum(self.warmup_lr, self.post_lr)

            if config.optimizer == 'adam':
                self.optimizer = tf.train.AdamOptimizer(self.learning_rate)
            elif config.optimizer == 'nesterov':
                self.optimizer = tf.train.MomentumOptimizer(self.learning_rate,
                                                            0.9,
                                                            use_nesterov=True)
            else:
                raise Exception('optimizer not defined')

            self.vs = tf.trainable_variables()
            grads_and_vars = self.optimizer.compute_gradients(self.loss,
                                                              self.vs)
            self.grads = [grad for (grad, var) in grads_and_vars]
            self.vs = [var for (grad, var) in grads_and_vars]
            if config.max_grad_norm > 0:
                self.grads, _ = tf.clip_by_global_norm(
                    self.grads, config.max_grad_norm)
            self.train_op = self.optimizer.apply_gradients(
                zip(self.grads, self.vs),
                global_step=self.global_step)
        else:
            self.ctc_input = tf.transpose(self.ctc_input, perm=[1, 0, 2])
            self.softmax = tf.nn.softmax(self.ctc_input, name='softmax')
            # self.ctc_decode_input = tf.log(self.softmax, name='ctc_input')
            # self.ctc_decode_result, self.ctc_decode_log_prob = tf.nn.ctc_beam_search_decoder(
            #     self.ctc_decode_input, self.new_seqLengths,
            #     beam_width=config.beam_size, top_paths=1)
            # self.dense_output = tf.sparse_tensor_to_dense(
            #     self.ctc_decode_result[0], default_value=-1,
            #     name='dense_output')

class DeployModel(object):
    def __init__(self, config):
        """
        In deployment, we use placeholder to get input. Only inference part
        are built. seq_lengths, rnn_states, rnn_outputs, ctc_decode_inputs
        are exposed for streaming decoding. All operators are placed in CPU.
        Padding should be done before data is fed.
        """

        # input place holder
        config.keep_prob = 1

        # with tf.device('/cpu:0'):
        #
        # self.inputX = tf.placeholder(dtype=tf.float32,
        #                              shape=[None, config.fft_size],
        #                              name='inputX')
        #
        # complex_tensor = tf.complex(
        #     self.inputX,
        #     imag=tf.zeros_like(self.inputX, dtype=tf.float32),
        #     name='complex_tensor')
        # abs = tf.abs(
        #     tf.fft(complex_tensor, name='fft'))
        # print(abs)

        self.inputX = tf.placeholder(dtype=tf.float32,
                                     shape=[None, ],
                                     name='inputX')
        self.inputX = tf.expand_dims(self.inputX, 0)
        self.frames = tf_frame(self.inputX, 400, 160, name='frame')

        self.linearspec = tf.abs(tf.spectral.rfft(self.frames, [400]))

        if config.mfcc:
            self.melspec = mfcc(self.linearspec, config,batch_size=1)
        else:
            self.mel_basis = librosa.filters.mel(
                sr=config.samplerate,
                n_fft=config.fft_size,
                fmin=config.fmin,
                fmax=config.fmax,
                n_mels=config.freq_size).T
            self.mel_basis = tf.constant(value=self.mel_basis, dtype=tf.float32)
            self.mel_basis = tf.expand_dims(self.mel_basis, 0)

            self.melspec = tf.matmul(self.linearspec, self.mel_basis, name='mel')

        # self.melspec = tf.expand_dims(self.melspec, 0)

        self.fuck = tf.identity(self.melspec, name='fuck')

        self.seqLengths = tf.expand_dims(tf.shape(self.melspec)[1], 0)
        self.nn_outputs, self.new_seqLengths = inference(self.melspec,
                                                         self.seqLengths,
                                                         config,
                                                         is_training=False,
                                                         batch_size=1)

        self.softmax = tf.nn.softmax(self.nn_outputs, name='softmax')

if __name__ == "__main__":
    pass


import plyfile
import argparse
import torch
import numpy as np
import skimage.measure
import scipy
import mrcfile
import os

N_CHANNELS = 22

def create_samples(N=256, voxel_origin=[0, 0, 0], cube_length=2.0):
    # NOTE: the voxel_origin is actually the (bottom, left, down) corner, not the middle
    voxel_origin = np.array(voxel_origin) - cube_length/2
    voxel_size = cube_length / (N - 1)

    overall_index = torch.arange(0, N ** 3, 1, out=torch.LongTensor())
    samples = torch.zeros(N ** 3, 3)

    # transform first 3 columns
    # to be the x, y, z index
    samples[:, 2] = overall_index % N
    samples[:, 1] = (overall_index.float() / N) % N
    samples[:, 0] = ((overall_index.float() / N) / N) % N

    # transform first 3 columns
    # to be the x, y, z coordinate
    samples[:, 0] = (samples[:, 0] * voxel_size) + voxel_origin[2]
    samples[:, 1] = (samples[:, 1] * voxel_size) + voxel_origin[1]
    samples[:, 2] = (samples[:, 2] * voxel_size) + voxel_origin[0]

    num_samples = N ** 3

    return samples.unsqueeze(0), voxel_origin, voxel_size

def sample_generator(generator, z, max_batch=24000, voxel_resolution=256, voxel_origin=[0,0,0], cube_length=2.0, psi=0.5):
    head = 0
    samples, voxel_origin, voxel_size = create_samples(voxel_resolution, voxel_origin, cube_length)
    samples = samples.to(z.device)
    sigmas = torch.zeros((samples.shape[0], samples.shape[1], 1), device=z.device)

    transformed_ray_directions_expanded = torch.zeros((samples.shape[0], max_batch, 3), device=z.device)
    transformed_ray_directions_expanded[..., -1] = -1

    # generator.generate_avg_frequencies()
    avg_frequencies_geo, avg_phase_shifts_geo, avg_frequencies_app, avg_phase_shifts_app = generator.generate_avg_frequencies()
    with torch.no_grad():
        raw_frequencies_geo, raw_phase_shifts_geo = generator.siren.geo_mapping_network(z)
        raw_frequencies_app, raw_phase_shifts_app = generator.siren.app_mapping_network(z)
        truncated_frequencies_geo = avg_frequencies_geo + psi * (raw_frequencies_geo - avg_frequencies_geo)
        truncated_phase_shifts_geo = avg_phase_shifts_geo + psi * (raw_phase_shifts_geo - avg_phase_shifts_geo)
        truncated_frequencies_app = avg_frequencies_app + psi * (raw_frequencies_app - avg_frequencies_app)
        truncated_phase_shifts_app = avg_phase_shifts_app + psi * (raw_phase_shifts_app - avg_phase_shifts_app)
    with torch.no_grad():
        while head < samples.shape[1]:
            coarse_output = generator.siren.forward_with_frequencies_phase_shifts(samples[:, head:head+max_batch], truncated_frequencies_geo, truncated_frequencies_app, truncated_phase_shifts_geo, truncated_phase_shifts_app, ray_directions=transformed_ray_directions_expanded[:, :samples.shape[1]-head]).reshape(samples.shape[0], -1, N_CHANNELS)
            sigmas[:, head:head+max_batch] = coarse_output[:, :, -1:]
            head += max_batch

    sigmas = sigmas.reshape((voxel_resolution, voxel_resolution, voxel_resolution)).cpu().numpy()

    return sigmas

def sample_generator_wth_frequencies_phase_shifts(generator, meta, max_batch=100000, voxel_resolution=256, voxel_origin=[0,0,0], cube_length=2.0, psi=0.5):
    head = 0
    samples, voxel_origin, voxel_size = create_samples(voxel_resolution, voxel_origin, cube_length)
    samples = samples.to(generator.device)
    sigmas = torch.zeros((samples.shape[0], samples.shape[1], 1), device=generator.device)

    transformed_ray_directions_expanded = torch.zeros((samples.shape[0], max_batch, 3), device=generator.device)
    transformed_ray_directions_expanded[..., -1] = -1
    truncated_frequencies_geo, truncated_frequencies_app, truncated_phase_shifts_geo, truncated_phase_shifts_app = meta['truncated_frequencies_geo'], meta['truncated_frequencies_app'], meta['truncated_phase_shifts_geo'], meta['truncated_phase_shifts_app']
    # generator.generate_avg_frequencies()
    with torch.no_grad():
        while head < samples.shape[1]:
            coarse_output = generator.siren.forward_with_frequencies_phase_shifts(samples[:, head:head+max_batch], truncated_frequencies_geo, truncated_frequencies_app, truncated_phase_shifts_geo, truncated_phase_shifts_app, ray_directions=transformed_ray_directions_expanded[:, :samples.shape[1]-head]).reshape(samples.shape[0], -1, N_CHANNELS)
            sigmas[:, head:head+max_batch] = coarse_output[:, :, -1:]
            head += max_batch

    sigmas = sigmas.reshape((voxel_resolution, voxel_resolution, voxel_resolution)).cpu().numpy()

    return sigmas

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('path', type=str)
    parser.add_argument('--seeds', nargs='+', default=[3,4,5])
    parser.add_argument('--cube_size', type=float, default=0.3)
    parser.add_argument('--voxel_resolution', type=int, default=256)
    parser.add_argument('--output_dir', type=str, default='shapes')
    parser.add_argument('--latent_path', type=str, default=None)
    opt = parser.parse_args()

    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

    generator = torch.load(opt.path, map_location=torch.device(device))
    ema = torch.load(opt.path.split('generator')[0] + 'ema.pth')
    ema.copy_to(generator.parameters())
    generator.set_device(device)
    generator.eval()

    if opt.latent_path is None:
        for seed in opt.seeds:
            torch.manual_seed(seed)

            z = torch.randn(1, 256, device=device)

            voxel_grid = sample_generator(generator, z, cube_length=opt.cube_size, voxel_resolution=opt.voxel_resolution)
            os.makedirs(opt.output_dir, exist_ok=True)
            with mrcfile.new_mmap(os.path.join(opt.output_dir, f'{seed}.mrc'), overwrite=True, shape=voxel_grid.shape, mrc_mode=2) as mrc:
                mrc.data[:] = voxel_grid

    else:
        meta = torch.load(opt.latent_path)
        # ### debug: transform for inversed latent codes
        w_geo_frequency_offsets, w_geo_phase_shift_offsets, w_app_frequency_offsets, w_app_phase_shift_offsets = meta['w_geo_frequency_offsets'].to(device), meta['w_geo_phase_shift_offsets'].to(device), meta['w_app_frequency_offsets'].to(device), meta['w_app_phase_shift_offsets'].to(device)
        w_geo_frequencies, w_geo_phase_shifts, w_app_frequencies, w_app_phase_shifts = meta['w_geo_frequencies'].to(device), meta['w_geo_phase_shifts'].to(device), meta['w_app_frequencies'].to(device), meta['w_app_phase_shifts'].to(device)
        meta['truncated_frequencies_geo'] = w_geo_frequencies + w_geo_frequency_offsets
        meta['truncated_frequencies_app'] =  w_app_frequencies + w_app_frequency_offsets
        meta['truncated_phase_shifts_geo'] = w_geo_phase_shifts + w_geo_phase_shift_offsets
        meta['truncated_phase_shifts_app'] = w_app_phase_shifts + w_app_phase_shift_offsets

        voxel_grid = sample_generator_wth_frequencies_phase_shifts(generator, meta, cube_length=opt.cube_size, voxel_resolution=opt.voxel_resolution)
        os.makedirs(opt.output_dir, exist_ok=True)
        with mrcfile.new_mmap(os.path.join(opt.output_dir, f'{opt.seeds[0]}.mrc'), overwrite=True, shape=voxel_grid.shape, mrc_mode=2) as mrc:
            mrc.data[:] = voxel_grid


from hashlib import new
import random
def start_game():
    mat = []
    for i in range(4):
        mat.append([0]*4)

    return mat

def add_new_2(mat):
    r = random.randint(0, 3)
    c = random.randint(0, 3)

    while mat[r][c] != 0:
        r = random.randint(0, 3)
        c = random.randint(0, 3)

    mat[r][c] = 2

def get_current_state(mat):
    for i in range(4):
        for j in range(4):
            if mat[i][j] == 2048:
                return 'WON'

    for i in range(4):
        for j in range(4):
            if mat[i][j] == 0:
                return 'GAME NOT OVER'
            if i + 1 < 4 and mat[i][j] == mat[i+1][j]:
                return 'GAME NOT OVER'
            if j + 1 < 4 and mat[i][j] == mat[i][j+1]:
                return 'GAME NOT OVER'

    return 'LOST'

def compress(mat):
    new_mat = []
    for i in range(4):
        new_mat.append([0] * 4)

    change = False
    for i in range(4):
        pos = 0
        for j in range(4):
            if mat[i][j] != 0:
                new_mat[i][pos] = mat[i][j]
                if pos != j:
                    change = True
                pos += 1

    return new_mat, change

def merge(mat):
    change = False
    for i in range(4):
        for j in range(3):
            if mat[i][j] == mat[i][j+1] and mat[i][j] != 0:
                mat[i][j] *= 2
                mat[i][j+1] = 0
                change = True

    return change

def reverse(mat):
    new_mat = []
    for i in range(4):
        new_mat.append([])
        for j in range(4):
            new_mat[i].append(mat[i][3 - j])

    return new_mat

def transpose(mat):
    new_mat = []
    for i in range(4):
        new_mat.append([])
        for j in range(4):
            new_mat[i].append(mat[j][i])

    return new_mat

def move_up(mat):
    transpose_mat = transpose(mat)
    compress_mat, change1 = compress(transpose_mat)
    change2 = merge(compress_mat)
    changed = change1 or change2
    compress_mat, change1 = compress(compress_mat)
    transpose_mat = transpose(compress_mat)
    return transpose_mat, changed

def move_down(mat):
    transpose_mat = transpose(mat)
    reverse_mat = reverse(transpose_mat)
    compress_mat, change1 = compress(reverse_mat)
    change2 = merge(compress_mat)
    changed = change1 or change2
    compress_mat, change1 = compress(compress_mat)
    reverse_mat = reverse(compress_mat)
    transpose_mat = transpose(reverse_mat)
    return transpose_mat, changed

def move_right(mat):
    reverse_mat = reverse(mat)
    compress_mat, change1 = compress(reverse_mat)
    change2 = merge(compress_mat)
    changed = change1 or change2
    compress_mat, change1 = compress(compress_mat)
    reverse_mat = reverse(compress_mat)
    return reverse_mat, changed

def move_left(mat):
    compress_mat, change1 = compress(mat)
    change2 = merge(compress_mat)
    changed = change1 or change2
    compress_mat, change1 = compress(compress_mat)
    return compress_mat, changed


import tkinter as tk
from tkinter import ttk, messagebox
import datetime

class CalendarReminderApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Calendar Reminder App")

        # List to store reminders as tuples of (datetime, reminder_text)
        self.reminders = []

        # Label and entry for date input
        self.date_label = tk.Label(root, text="Date (YYYY-MM-DD):")
        self.date_label.grid(row=0, column=0, padx=5, pady=5)

        self.date_entry = tk.Entry(root)
        self.date_entry.grid(row=0, column=1, padx=5, pady=5)

        # Label and entry for time input
        self.time_label = tk.Label(root, text="Time (HH:MM):")
        self.time_label.grid(row=1, column=0, padx=5, pady=5)

        self.time_entry = tk.Entry(root)
        self.time_entry.grid(row=1, column=1, padx=5, pady=5)

        # Label and entry for reminder input
        self.reminder_label = tk.Label(root, text="Reminder:")
        self.reminder_label.grid(row=2, column=0, padx=5, pady=5)

        self.reminder_entry = tk.Entry(root)
        self.reminder_entry.grid(row=2, column=1, padx=5, pady=5)

        # Button to add a reminder
        self.add_reminder_button = tk.Button(
            root, text="Add Reminder", command=self.add_reminder
        )
        self.add_reminder_button.grid(row=3, column=0, columnspan=2, pady=10)

        # Treeview to display the list of reminders
        self.reminder_tree = ttk.Treeview(
            root,
            columns=("Date", "Time", "Reminder"),
            show="headings",
            selectmode="extended",
        )
        self.reminder_tree.heading("Date", text="Date")
        self.reminder_tree.heading("Time", text="Time")
        self.reminder_tree.heading("Reminder", text="Reminder")
        self.reminder_tree.grid(row=4, column=0, columnspan=2, padx=5, pady=5)

        # Button to remove selected reminders
        self.remove_reminder_button = tk.Button(
            root, text="Remove Reminder", command=self.remove_reminder
        )
        self.remove_reminder_button.grid(row=5, column=0, columnspan=2, pady=10)

    def add_reminder(self):
        # Add a reminder to the list
        date_str = self.date_entry.get()
        time_str = self.time_entry.get()
        reminder_text = self.reminder_entry.get()

        try:
            # Parse date and time strings
            date = datetime.datetime.strptime(date_str, "%Y-%m-%d")
            time = datetime.datetime.strptime(time_str, "%H:%M").time()

            # Combine date and time to create a datetime object
            reminder_datetime = datetime.datetime.combine(date.date(), time)

            # Add reminder to the list
            self.reminders.append((reminder_datetime, reminder_text))

            # Show a message box indicating successful addition
            messagebox.showinfo("Reminder Added", "Reminder has been added.")

            # Clear entry fields
            self.date_entry.delete(0, tk.END)
            self.time_entry.delete(0, tk.END)
            self.reminder_entry.delete(0, tk.END)

            # Update the Treeview with the new data
            self.update_reminder_tree()
        except ValueError:
            # Show a warning if there's an error in date or time input
            messagebox.showwarning("Warning", "Please enter valid date and time.")

    def remove_reminder(self):
        # Remove selected reminders from the list
        selected_items = self.reminder_tree.selection()
        if not selected_items:
            messagebox.showwarning("Warning", "Please select a reminder to remove.")
            return

        for item in selected_items:
            reminder_index = int(self.reminder_tree.item(item, "text")) - 1
            del self.reminders[reminder_index]

        # Show a message box indicating successful removal
        messagebox.showinfo("Reminder Removed", "Selected reminders have been removed.")

        # Update the Treeview after removal
        self.update_reminder_tree()

    def update_reminder_tree(self):
        # Update the Treeview with the current list of reminders
        self.reminder_tree.delete(*self.reminder_tree.get_children())
        for i, (reminder_datetime, reminder_text) in enumerate(self.reminders, start=1):
            date_str = reminder_datetime.strftime("%Y-%m-%d")
            time_str = reminder_datetime.strftime("%H:%M")
            self.reminder_tree.insert(
                "", "end", text=str(i), values=(date_str, time_str, reminder_text)
            )

if __name__ == "__main__":
    root = tk.Tk()
    app = CalendarReminderApp(root)
    root.mainloop()


import numpy as np
import pandas as pd
import scipy.io
from sklearn import preprocessing

##################建立feature_fft这个类####################

class Feature_fft(object):
    def __init__(self, sequence_data):
        self.data = sequence_data
        fft_trans = np.abs(np.fft.fft(sequence_data))
        self.dc = fft_trans[0]
        self.freq_spectrum = fft_trans[1:int(np.floor(len(sequence_data) * 1.0 / 2)) + 1]
        self._freq_sum_ = np.sum(self.freq_spectrum)

    def fft_mean(self):
        return np.mean(self.freq_spectrum)

    def fft_shape_mean(self):
        shape_sum = np.sum([x * self.freq_spectrum[x]
                            for x in range(len(self.freq_spectrum))])
        return 0 if self._freq_sum_ == 0 else shape_sum * 1.0 / self._freq_sum_

    def fft_all(self):
        '''
        Get all fft features in one function
        :return: All fft features in one list
        '''
        feature_all = list()
        feature_all.append(self.fft_shape_mean())
        feature_all.append(self.fft_mean())

        return feature_all

#####        (3)构造波动率指标        #####
def cal_wave_rate(data):
    # 先对数据进行标准归一化
    data = data.reshape(-1,1)
    min_max_scaler = preprocessing.MinMaxScaler()
    data_minmax = min_max_scaler.fit_transform(data)
    #print(data_minmax)
    wave_rate = np.percentile(data_minmax,90)-np.percentile(data_minmax,10)
    return wave_rate

#####        (5)构造平均剂量率指标  #####
def average(data):
    data_aver = np.mean(data)
    return data_aver

#####        (7)构造中位数剂量率指标  #####
def median(data):
    data_median = np.median(data)
    return data_median

#####        (8)构造样本熵指标     ####
# SampEn  计算时间序列U的样本熵
# 输入：U是数据一维数组array
#       m重构维数，一般选择1或2，优先选择2，一般不取m>2
#       r 阈值大小，一般选择r=0.1~0.25*Std(data)
# 输出：样本熵值大小
def SampEn(U, m, r):
     def _maxdist(x_i, x_j):
           return max([abs(ua - va) for ua, va in zip(x_i, x_j)])
     def _phi(m):
          x = [[U[j] for j in range(i, i + m - 1 + 1)] for i in range(N - m + 1)]
          B = [(len([1 for x_j in x if _maxdist(x_i, x_j) <= r]) - 1.0) / (N - m) for x_i in x]
          return (N - m + 1.0)**(-1) * sum(B)
     N = len(U)
     return -np.log(_phi(m+1) / _phi(m))

window_size = 5
#####      (9)对数据进行滑动窗口处理   #####
def rolling(data):
    data = data.rolling(window_size).sum()
    return data

window = window_size-1
wave_rate_all = []
data_aver = []
data_median = []
SampEn_all = []
#fft的一些频域指标
fft_shape_mean = []
fft_mean = []

########### Read data file ###########
source_data = './datafile.mat'
data_info = scipy.io.loadmat(source_data)
obs_data = data_info['obs_data']
Sta_num = obs_data.shape[1]
Scaling_factor = data_info['Scaling_factor']

df_all = pd.DataFrame(obs_data)
df = df_all #保存数据到df
df_all = rolling(df_all)
df = Scaling_factor*np.array(df[0:window]) #取出前3行数据用于补充后面的NAN值
data_all = df_all.values * Scaling_factor
data_all = (1/window_size)*data_all[window:]
data_all = np.vstack((df,data_all))

start_time = 11
end_time = 40

for index_col in range(Sta_num):

    data = data_all[:,index_col]
    data = np.array(data)
    data = data[start_time:end_time]

    #Hurst_exponent_all.append(hurst(data))
    wave_rate_all.append(cal_wave_rate(data))
    data_aver.append(average(data))
    data_median.append(median(data))
    SampEn_all.append(SampEn(data,2,np.std(data)))

    a = list(data)
    feature_fft = Feature_fft(a).fft_all()
    fft_shape_mean.append(feature_fft[0])
    fft_mean.append(feature_fft[1])

Feature_results = {
                   'release_num': 1,
                   'wave_rate1':wave_rate_all[0],'aver1':data_aver[0],'median1':data_median[0],'fft_shape_mean1':fft_shape_mean[0],'fft_mean1':fft_mean[0],'SamEn1':SampEn_all[0],
                   'wave_rate2':wave_rate_all[1],'aver2':data_aver[1],'median2':data_median[1],'fft_shape_mean2':fft_shape_mean[1],'fft_mean2':fft_mean[1],'SamEn2':SampEn_all[1],
                   'wave_rate3':wave_rate_all[2],'aver3':data_aver[2],'median3':data_median[2],'fft_shape_mean3':fft_shape_mean[2],'fft_mean3':fft_mean[2],'SamEn3':SampEn_all[2],
                   'wave_rate4':wave_rate_all[3],'aver4':data_aver[3],'median4':data_median[3],'fft_shape_mean4':fft_shape_mean[3],'fft_mean4':fft_mean[3],'SamEn4':SampEn_all[3],
                  }
Feature_results = pd.DataFrame(Feature_results,index=[0])
Feature_results.to_csv('./Testing_datasets/test_data.csv',index=None)


"""
You can cd to the directory of that file and use python3
 key_value.storage.py --key {key}
 to read all values from the key
 or python3 key_value storage.py --key {key} --val {val} to write value to the key
 in your command line
 """

import argparse
import os
from tempfile import gettempdir
STORAGE_PATH = os.path.join(gettempdir(), 'storage.data')

def storage_init(STORAGE_PATH):
	""" Function that creates key-val storage from the file """
	storage = dict()
	parsed_keys=set()
	if not os.path.exists(STORAGE_PATH):
		with open(STORAGE_PATH, 'w') as f:
			pass
	with open(STORAGE_PATH, 'r+') as f:
		for line in f:
			key, value = line.split()
			if key in parsed_keys:
				storage[str(key)] += ', ' + value
			else:
				storage[str(key)] = value
			parsed_keys.add(str(key))
	return storage

def print_values(key:str,storage:dict):
	""" Function that print value(s) from requested key """
	if key in storage.keys():
		return storage[str(key)]

def parse_arguments(storage:dict):
	""" Function that parse arguments from the command line """
	parser = 														argparse.ArgumentParser(description='key_value_storage')

	parser.add_argument('--key', action = "store", dest="keys")
	parser.add_argument('--val', action = "store", dest="values")
	args = parser.parse_args()
	args = vars(args)
	if args['values'] is None:
		print(print_values(args['keys'], storage))
	else:
		with open(STORAGE_PATH, 'a') as f:
			f.write(args['keys']+' '+args['values']+'\n')
	return
if __name__ == '__main__':
	storage = storage_init(STORAGE_PATH)
	parse_arguments(storage)


from math import sqrt, gcd

def coprime(x, y):
    if gcd(x, y) == 1:
        return True
    else:
        return False

def is_odd(x):
    odds = [1, 3, 5, 7, 9]
    a = str(x)
    if int(a[-1]) in odds:
        return True
    else:
        return False

def both_odd(x, y):
    if is_odd(x) and is_odd(y):
        return True
    else:
        return False

if __name__ == "__main__":

    len_lim = 1.5e6 + 1
    py_trips = {}

    for m in range(1, int(sqrt(len_lim))+10):
        print(m)

        for k in range(1, int(len_lim)):

            if k * m**2 > len_lim:
                break

            for n in range(1, m):

                if both_odd(m, n):
                    continue

                if not coprime(m, n):
                    continue

                a = k * (m**2 - n**2)
                b = k * 2*m*n
                c = k* (m**2 + n**2)
                total = a+b+c
                if total > len_lim:
                    continue
                else:
                    if total in py_trips.keys():
                        py_trips[total] = py_trips[total] + 1
                    else:
                        py_trips[total] = 1

    unique_triples = 0

    for i in py_trips:
        if py_trips[i] == 1:
            unique_triples = unique_triples + 1

    print(unique_triples)


import bbsengine5 as bbsengine
import ttyio5 as ttyio

for k, v in ttyio.emoji.items():
    label = k
    if type(v) == tuple:
        value = v[0]
        spaces = v[1]
    elif type(v) == str:
        value = v
        spaces = ""
    buf = "%s: %s %d" % (label, value, len(spaces))
#    ttyio.echo(buf)
    ttyio.echo(ttyio.ljust(buf, fillchar="*"))


import cv2
import pyautogui
from time import time
from math import hypot
import mediapipe as mp
import matplotlib.pyplot as plt

from PoseDetection import detectPose

def checkHandsJoined(image, results, draw=False, display=False):
    '''
    This function checks whether the hands of the person are joined or not in an image.
    Args:
        image:   The input image with a prominent person whose hands status (joined or not) needs to be classified.
        results: The output of the pose landmarks detection on the input image.
        draw:    A boolean value that is if set to true the function writes the hands status & distance on the output image.
        display: A boolean value that is if set to true the function displays the resultant image and returns nothing.
    Returns:
        output_image: The same input image but with the classified hands status written, if it was specified.
        hand_status:  The classified status of the hands whether they are joined or not.
    '''

    # Get the height and width of the input image.
    height, width, _ = image.shape

    # Create a copy of the input image to write the hands status label on.
    output_image = image.copy()

    # Get the left wrist landmark x and y coordinates.
    left_wrist_landmark = (results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST].x * width,
                          results.pose_landmarks.landmark[mp_pose.PoseLandmark.LEFT_WRIST].y * height)

    # Get the right wrist landmark x and y coordinates.
    right_wrist_landmark = (results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST].x * width,
                           results.pose_landmarks.landmark[mp_pose.PoseLandmark.RIGHT_WRIST].y * height)

    # Calculate the euclidean distance between the left and right wrist.
    euclidean_distance = int(hypot(left_wrist_landmark[0] - right_wrist_landmark[0],
                                   left_wrist_landmark[1] - right_wrist_landmark[1]))

    # Compare the distance between the wrists with a appropriate threshold to check if both hands are joined.
    if euclidean_distance < 130:

        # Set the hands status to joined.
        hand_status = 'Hands Joined'

        # Set the color value to green.
        color = (0, 255, 0)

    # Otherwise.
    else:

        # Set the hands status to not joined.
        hand_status = 'Hands Not Joined'

        # Set the color value to red.
        color = (0, 0, 255)

    # Check if the Hands Joined status and hands distance are specified to be written on the output image.
    if draw:

        # Write the classified hands status on the image.
        cv2.putText(output_image, hand_status, (10, 30), cv2.FONT_HERSHEY_PLAIN, 2, color, 3)

        # Write the the distance between the wrists on the image.
        cv2.putText(output_image, f'Distance: {euclidean_distance}', (10, 70),
                    cv2.FONT_HERSHEY_PLAIN, 2, color, 3)

    # Check if the output image is specified to be displayed.
    if display:

        # Display the output image.
        plt.figure(figsize=[10,10])
        plt.imshow(output_image[:,:,::-1]);plt.title("Output Image");plt.axis('off');

    # Otherwise
    else:

        # Return the output image and the classified hands status indicating whether the hands are joined or not.
        return output_image, hand_status

# Initialize the VideoCapture object to read from the webcam.
camera_video = cv2.VideoCapture(0)
camera_video.set(3,1280)
camera_video.set(4,960)

# Create named window for resizing purposes.
cv2.namedWindow('Hands Joined?', cv2.WINDOW_NORMAL)

# Iterate until the webcam is accessed successfully.
while camera_video.isOpened():

    # Read a frame.
    ok, frame = camera_video.read()

    # Check if frame is not read properly then continue to the next iteration to read the next frame.
    if not ok:
        continue

    # Flip the frame horizontally for natural (selfie-view) visualization.
    frame = cv2.flip(frame, 1)

    # Get the height and width of the frame of the webcam video.
    frame_height, frame_width, _ = frame.shape

    # Perform the pose detection on the frame.
    frame, results = detectPose(frame, pose_video, draw=True)

    # Check if the pose landmarks in the frame are detected.
    if results.pose_landmarks:

        # Check if the left and right hands are joined.
        frame, _ = checkHandsJoined(frame, results, draw=True)

    # Display the frame.
    cv2.imshow('Hands Joined?', frame)

    # Wait for 1ms. If a key is pressed, retreive the ASCII code of the key.
    k = cv2.waitKey(1) & 0xFF

    # Check if 'ESC' is pressed and break the loop.
    if(k == 27):
        break

# Release the VideoCapture Object and close the windows.
camera_video.release()
cv2.destroyAllWindows()


import math

def Menu ():
        print("Wpisz 1 aby obliczyć pole kwadratu")
        print("Wpisz 2 aby obliczyć pole prostokątu")
        print("Wpisz 3 aby obliczyć pole trójkąta")
        print("Wpisz 4 aby obliczyć pole trapezu")
        print("Wpisz 5 aby obliczyć pole koła")
        print("Wpisz 6 aby zakończyć")

def powrót ():
    Menu()
    print()
    wart()

def kwadrat (a):
    return a * a

def prostokąt (a, b):
    return a * b

def trójkąt (a, h):
    return (a * h) / 2

def trapez (a, b, h):
    return ((a+b) * h) / 2

def koło(r):
    return math.pi * r**2

def wart ():
    c = input("Wybierz opcję: ")
    if (c == '1'):
        a = input("Wpisz długosc boku: ")
        a = int(a)
        wynik = kwadrat(a)
        print(wynik)
        print()
        w = input("Wpisz 1 aby wrócić do menu ")
        if (w == '1'):
            print()
            return powrót()
        else:
            quit()

    elif (c == '2'):
        a = input("Wpisz długosc 1 boku: ")
        a = int(a)
        b = input("Wpisz długosc 2 boku: ")
        b = int(b)
        wynikP = prostokąt(a, b)
        print(wynikP)
        print()
        w = input("Wpisz 1 aby wrócić do menu ")
        if (w == '1'):
            print()
            return powrót()
        else:
            quit()

    elif(c == '3'):
        a = input("Wpisz długosc boku: ")
        a = int(a)
        h = input("Wpisz długosc wysokosci: ")
        h = int(h)
        wynikT = trójkąt(a, h)
        print(wynikT)
        print()
        w = input("Wpisz 1 aby wrócić do menu ")
        if (w == '1'):
            print()
            return powrót()
        else:
            quit()

    elif(c == '4'):
        a = input("Wpisz długosc 1 podstawy: ")
        a = int(a)
        b = input("Wpisz długosc 2 podstawy: ")
        b = int(b)
        h = input("Wpisz długosc wysokosci: ")
        h = int(h)
        wynikTr = trapez(a, b, h)
        print(wynikTr)
        print()
        w = input("Wpisz 1 aby wrócić do menu ")
        if (w == '1'):
            print()
            return powrót()
        else:
            quit()

    elif(c == '5'):
        r = input("Wpisz długosc promienia ")
        r = int(r)
        wynikK = koło(r)
        print(wynikK)
        print()
        w = input("Wpisz 1 aby wrócić do menu ")
        if (w == '1'):
            print()
            return powrót()
        else:
            quit()

    elif(c =='6'):
        quit()

    else:
        quit()

print(powrót())


#!/opt/anaconda3/bin/python3
# -*- coding: utf-8 -*-

import sys
sys.path.append('../scripts/')
from puddle_world import *
import itertools
import seaborn as sns
import collections

class PolicyEvaluator:
    def __init__(self, widths, goal, puddles, time_interval, sampling_num, puddle_coef=100.0,
                 lowerleft=np.array([-4,-4]).T, upperright=np.array([4,4]).T):
        self.pose_min = np.r_[lowerleft, 0]
        self.pose_max = np.r_[upperright, math.pi*2]
        self.widths   = widths
        self.goal     = goal

        self.index_nums = ((self.pose_max - self.pose_min)/self.widths).astype(int)
        nx, ny, nt = self.index_nums
        self.indexes = list(itertools.product(range(nx), range(ny), range(nt)))

        self.value_function, self.final_state_flags = self.init_value_function()
        self.policy = self.init_policy()
        self.actions = list(set([tuple(self.policy[i]) for i in self.indexes]))

        self.state_transition_probs = self.init_state_transition_probs(time_interval, sampling_num)

        self.depths = self.depth_means(puddles, sampling_num)

        self.time_interval = time_interval
        self.puddle_coef = puddle_coef

    def policy_evaluation_sweep(self):
        for index in self.indexes:
            if not self.final_state_flags[index]:
                self.value_function[index] = self.action_value(tuple(self.policy[index]), index)

    def action_value(self, action, index):
        value = 0.0
        for delta, prob in self.state_transition_probs[(action, index[2])]:
            after = tuple(self.out_correction(np.array(index).T + delta))
            reward = -self.time_interval * self.depths[(after[0], after[1])] * self.puddle_coef - self.time_interval
            value += (self.value_function[after] + reward) * prob

        return value

    def out_correction(self, index):
        index[2] = (index[2] + self.index_nums[2])%self.index_nums[2]

        return index

    def depth_means(self, puddles, sampling_num):
        dx = np.linspace(0, self.widths[0], sampling_num)
        dy = np.linspace(0, self.widths[1], sampling_num)
        samples = list(itertools.product(dx, dy))

        tmp = np.zeros(self.index_nums[0:2])
        for xy in itertools.product(range(self.index_nums[0]), range(self.index_nums[1])):
            for s in samples:
                pose = self.pose_min + self.widths*np.array([xy[0], xy[1], 0]).T + np.array([s[0], s[1], 0]).T
                for p in puddles:
                    tmp[xy] += p.depth*p.inside(pose)

            tmp[xy] /= sampling_num**2

        return tmp

    def init_state_transition_probs(self, time_interval, sampling_num):
        dx = np.linspace(0.001, self.widths[0]*0.999, sampling_num)
        dy = np.linspace(0.001, self.widths[1]*0.999, sampling_num)
        dt = np.linspace(0.001, self.widths[2]*0.999, sampling_num)
        samples = list(itertools.product(dx, dy, dt))

        tmp = {}
        for a in self.actions:
            for i_t in range(self.index_nums[2]):
                transitions = []
                for s in samples:
                    before = np.array([s[0], s[1], s[2]+i_t*self.widths[2]]).T + self.pose_min
                    before_index = np.array([0,0,i_t]).T

                    after = IdealRobot.state_transition(a[0], a[1], time_interval, before)
                    after_index = np.floor((after-self.pose_min)/self.widths).astype(int)

                    transitions.append(after_index - before_index)

                #unique, count = np.unique(transitions, axis=0, return_counts=True)
                unique, count = np.unique(transitions, return_counts=True)
                probs = [c/sampling_num**3 for c in count]
                tmp[a, i_t] = list(zip(unique, probs))

        return tmp

    def init_policy(self):
        tmp = np.zeros(np.r_[self.index_nums, 2])
        for index in self.indexes:
            center = self.pose_min + self.widths*(np.array(index).T + 0.5)
            tmp[index] = PuddleIgnoreAgent.policy(center, self.goal)

        return tmp

    def init_value_function(self):
        v = np.empty(self.index_nums)
        f = np.zeros(self.index_nums)

        for index in self.indexes:
            f[index] = self.final_state(np.array(index).T)
            v[index] = self.goal.value if f[index] else -100.0

        return v, f

    def final_state(self, index):
        x_min, y_min, _ = self.pose_min + self.widths*index     #xy平面上で左下の座標
        x_max, y_max, _ = self.pose_min + self.widths*(index+1) #右上の座標(斜め上の離散状態の左下の座標)

        corners = [[x_min, y_min, _], [x_min, y_max, _], [x_max, y_min, _], [x_max, y_max, _]]
        return all([self.goal.inside(np.array(c).T) for c in corners])

def main():
    # pe = PolicyEvaluator(np.array([0.2,0.2,math.pi/18]).T, Goal(-3,-3), 0.1, 10)
    # print(pe.state_transition_probs)

    # v = pe.value_function[:,:,0]
    # sns.heatmap(np.rot90(v), square=False)
    # plt.show()

    # f = pe.final_state_flags[:,:,0]
    # sns.heatmap(np.rot90(f), square=False)
    # plt.show()

    # p = np.zeros(pe.index_nums)
    # for i in pe.indexes:
    #     p[i] = sum(pe.policy[i]) #速度と角速度を足すと, 0.2:直進, 0.5:左回転, -0.5:右回転になる
    #                              #                      1.0:直進, 2.0:左回転, -2.0:右回転 じゃなく???
    # sns.heatmap(np.rot90(p[:,:,18]), square=False)
    # plt.show()

    puddles = [Puddle((-2,0),(0,2),0.1), Puddle((-0.5,-2),(2.5,1),0.1)]
    pe = PolicyEvaluator(np.array([0.2,0.2,math.pi/18]).T, Goal(-3,-3), puddles, 0.1, 10)

    counter =0

    for i in range(10):
        pe.policy_evaluation_sweep()
        counter += 1

    v = pe.value_function[:,:,18]
    sns.heatmap(np.rot90(v), square=False)
    print(counter)
    plt.show()

if __name__ == '__main__':
    main()


from django.urls import path
from . import views

urlpatterns = [
    path('', views.post_create, name='homepage'),
    path('new_post/', views.PostCreateView.as_view(), name='create_post'),
    path('edit_post/<int:pk>/', views.PostUpdateView.as_view(), name='edit_post'),
    path('view_post/<int:post_id>/', views.CommentCreateView.as_view(), name='view_post'),
    path('posts/mine/', views.my_posts, name='my_posts')
]


import os
import logging
import json
import shutil
from datetime import datetime
import pandas as pd
import xml.etree.ElementTree as eTree
import time

def initializeDataFrame():
    # Define the column names
    column_names = ["section_no", "subject", "text", "modal_verb", "deontic_operator", "antecedent", "consequent"]
    # Load the list of lines into a DataFrame
    iDF = pd.DataFrame(columns=column_names)
    # Change the display options to show more text
    pd.set_option('max_colwidth', 80)
    return iDF

def print_list_of_provisions(cfr_list):
    df = initializeDataFrame()
    my_provision_list = []
    for subpart in cfr_list:
        row_data = {}
        for key, value in subpart.items():
            row_data[key] = value
        my_provision_list.append(row_data)
        df = pd.DataFrame(my_provision_list)
    return df

def getCFRData(reg_xml_file_location):

    try:
        # use XSLT to get only two important elements
        # store the results and return
        tree = eTree.parse(reg_xml_file_location)
        root = tree.getroot()
        cfrXmlElements = []

        # loops through the CFR.xml file to get the
        # section number, subject, and text (key/value) pairs- dictionary
        # stores them in a list.  See the following example
        # 'SECTNO': '1.000', 'SUBJECT': 'Scope of part.', 'TEXT': 'This part sets forth basic policies...
        # this method returns a list of dictionaries

        for subpart_element in root.findall('.//SECTION'):
            subpart_element_data = {
                'SECTNO': '',
                'SUBJECT': '',
                'TEXT': ''
            }

            sectno_elements = subpart_element.findall('.//SECTNO')
            if len(sectno_elements) > 0:
                subpart_element_data['SECTNO'] = ", ".join(
                    [element.text for element in sectno_elements if element.text is not None])

            subject_elements = subpart_element.findall('.//SUBJECT')
            if len(subject_elements) > 0:
                subpart_element_data['SUBJECT'] = ", ".join(
                    [element.text for element in subject_elements if element.text is not None])

            text_elements = subpart_element.findall('.//P')
            if len(text_elements) > 0:
                text = ""
                for element in text_elements:
                    text_fragments = [text_fragment.strip() for text_fragment in element.itertext()]
                    text += " ".join(text_fragments) + " "
                text = " ".join(text.split())  # remove extra whitespace
                subpart_element_data['TEXT'] = text

            cfrXmlElements.append(subpart_element_data)
        return cfrXmlElements
    except() as e:
        logging.error("Error occurred while parsing XML: %s", e)
        return []

def save_dataframe_as_excel(dff, dataSetName, cfrHomeBase):

    now = datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
    fileExt = ".xlsx"
    output = "output/"
    prefix = "_dtg-"

    # Define the file name and path
    file_name = cfrHomeBase + output + dataSetName + prefix +  now + fileExt

    # Create the output directory if it doesn't exist
    output_dir = os.path.dirname(file_name)
    os.makedirs(output_dir, exist_ok=True)

    try:
        # Save using XlsxWriter
        writer = pd.ExcelWriter(file_name, engine='xlsxwriter')
        dff.to_excel(writer, index=False, sheet_name='SHAMROQ')
        workbook  = writer.book
        worksheet = writer.sheets['SHAMROQ']

        # Specify the format for text
        text_format = workbook.add_format({'num_format': '@'})

        # Apply the format
        worksheet.set_column('A:A', None, text_format)
        writer.save()

    except Exception  as e:
        logging.error("Cannot save file: %s", e)
        file_name = None

    return file_name

def save_dataframe_as_csv(dff, dataSetName, cfrHomeBase):
    now = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
    fileExt = ".csv"
    output = "output/"
    prefix = "_dtg-"

    # Define the file name and path
    file_name = cfrHomeBase + output + dataSetName + prefix + now + fileExt

    # Create the output directory if it doesn't exist
    output_dir = os.path.dirname(file_name)
    os.makedirs(output_dir, exist_ok=True)

    try:
        # Write the DataFrame to a CSV file
        dff.to_csv(file_name, index=False, encoding='utf-8-sig')
    except OSError as e:
        logging.error("Cannot save file: %s", e)
        file_name = None

    return file_name

def extract_cfr_data(regList):
    # Initialize an empty DataFrame
    df_all_regulations = pd.DataFrame()

    # Loop through the list of CFR.xml files
    for regXmlInstance in regList:
        regSectionElements = getCFRData(regXmlInstance)
        df_regulation = pd.DataFrame(regSectionElements)
        df_all_regulations = pd.concat([df_all_regulations, df_regulation], ignore_index=True)

    # Force columns to desired data types - strings - to prevent excel warnings
    for col in df_all_regulations.columns:
        df_all_regulations["SECTNO"] = df_all_regulations["SECTNO"].apply(lambda x: f"{x}\u00A0")

    return df_all_regulations

def init(cfr_with_year):
    # Configure logging
    logging.basicConfig(filename='./logs/app.shamroq.log', level=logging.INFO,
                        format='%(asctime)s - %(levelname)s - %(message)s')

    # Set config file location
    configFile = "./config/pre-process.config.json"
    logging.info("Location of Config File: %s", configFile)

    # Load configuration from JSON file
    config = None;
    try:
        # Load configuration from JSON file
        with open(configFile, 'r', encoding='utf-8') as config_file:
            config = json.load(config_file)
    except FileNotFoundError as e:
        logging.error("Config file not found: %s", e)
    except json.JSONDecodeError as e:
        logging.error("Error parsing JSON file: %s", e)
    except Exception as e:
        logging.error("An error occurred while loading configuration: %s", e)

    # extract REG_NAME, BASE URL, & CFR volumes from config file
    cfr_home_base = config[cfr_with_year]['HOME_BASE']
    cfr_volumes = config[cfr_with_year]['VOLUMES']
    cfr_reg_name = config[cfr_with_year]['REG_NAME']

    cfr_xml_data = [cfr_home_base + volume for volume in cfr_volumes]
    logging.info("Final dataset: %s", cfr_xml_data)
    return cfr_xml_data, cfr_reg_name, cfr_home_base

def stage_cfr_for_processing(cfrHomeBase, dataSetName, original_file_name):
    stage = "stage/"
    output = "output/"
    output_source = cfrHomeBase + output

    # Extract the base name of the original file
    base_name = os.path.basename(original_file_name)

    # Create the new file name
    new_file_name = f"{dataSetName}.xlsx"

    # Construct source and destination paths
    source_path = os.path.join(output_source, base_name)
    destination_path = os.path.join(cfrHomeBase, stage, new_file_name)

    # Create the output directory (staging area) if it doesn't exist
    output_dir = os.path.dirname(destination_path)
    os.makedirs(output_dir, exist_ok=True)

    try:
        # Copy and rename the file to the staging area
        shutil.copy(source_path, destination_path)
    except OSError as e:
        logging.error("Cannot copy and rename file: %s", e)
        destination_path = None

    return destination_path

def main():
    CFR_WITH_YEAR = "CFR_16_2021"
    # CFR_WITH_YEAR = "CFR_45_2021"
    # CFR_WITH_YEAR = "CFR_48_2021"
    dataSet, regName, homeBase = init(CFR_WITH_YEAR)
    df_regs = extract_cfr_data(dataSet)
    logging.info("List of regulations: %s", df_regs)
    cfr_extracted_file = save_dataframe_as_excel(df_regs, regName, homeBase)
    logging.info("Saved File Name: %s", cfr_extracted_file)
    staged_file = stage_cfr_for_processing(homeBase, regName, cfr_extracted_file)
    logging.info("Staged File Name: %s", staged_file)

# -------------------------------------
# @Author Patrick Cook
# @Date: circa 2023 ATLAS release
# PREPROCESSING:  getCFRfromXML2-JSON.py
# Uses the getCFRData function to extract the SECTNO, SUBJECT,
# and concatenated TEXT elements within each SECTION element from all seven
# volumes of Title 48 contained in XML files.
# -------------------------------------

if __name__ == '__main__':
    start_time = datetime.now()
    main()
    end_time = datetime.now()
    duration = end_time - start_time
    logging.info("Execution time: %s", duration)
    print(f"Execution time: {duration}")


import datetime
import cv2
from time_extract import detectTime as dT

class Intersection:
    def __init__(self, roi=None, box_info=None, stop_track=3):
        self.roi = roi
        self.box_info = box_info
        self.stop_track = stop_track
        self.time_database = []
        self.is_transaction_sent = False
        self.cashier_id = -1
        self.customer_id = -1
        self.cash_id = -1
        self.tracked_id = -1
        self.intersect = []

    def set_roi(self, roi):
        self.roi = roi

    def set_box_info(self, box_info):
        self.box_info = box_info

    def get_time_database(self):
        return self.time_database

# """Check cash transaction"""
# time_database = []                      # Store all cash transaction
# is_transaction_sent = False             # Check if there is any transaction by cash

# # Store the existing frame that tracking cashier, customer and cash id
# cas_id = -1
# cus_id = -1
# cash_id = -1

# # Deal with the scenario when id disappear unexpectedly
# tracked_id = -1
# # Counter to drop the customer id after defined frames
# stop_track = 3

    def check_intersect(self):
        print("transaction happening: ", self.is_transaction_sent)

        inters = []
        counter = 0
        for c, x1, y1, x2, y2 in self.roi:
                # x1, y1, x2, y2, category, identity
            for xa, ya, xb, yb, cate, iden  in self.box_info:
                counter+=1
                # Calculate the coordinate of the intersection quad
                inter_x1 = max(x1, xa)
                inter_y1 = max(y1, ya)
                inter_x2 = min(x2, xb)
                inter_y2 = min(y2, yb)
                w = max(0., (inter_x2 - inter_x1))
                h = max(0., (inter_y2 - inter_y1))

                inter_area = (w * h)
                roi_area = ((x2 - x1) * (y2 - y1))

                intersection = inter_area / roi_area
                inters.append([c, cate, iden, intersection])

        """"
        inters list now have all the box information visible in every frame

        c - category of ROI (0 = cashier, 1 = customer)
        cate - category of detected object (0 = person, 1 = cash)
        iden - unique ID of detected object
        intersection - the intersection ratio of the ROI on detected object (c/cate)
        """

        # print("Iteration: ", counter)
        # print(f"Intersection is: {inters}")

        # Sorted so that the arrangement is in descending order
        inters.sort(key=lambda x: x[3], reverse=True)

        return inters

    def cash_transaction(self, img):
        self.intersect = self.check_intersect()

        haveCashier = False
        haveCustomer = False
        haveCash = False

        # Store the value of intersection of 0 so that: it can easily detected the dropped unique id and remove it.
        all_iden = [row[2] for row in self.intersect if float(row[3]) == 0 ]

        for c, cate, iden, intersection in self.intersect:
            # print(f"{c}, {cate}, {iden}, {intersection}")
            # Deal with the box where detected object have no intersection with ROIs
            if intersection == float(0):
                """
                Case 1: Customer leaving the ROI and the cas_id need to be cleared (-1)
                Case 2: Customer leaving the ROI but its unique_id changed due to poor object detection
                Case 3: Person in the background (can be customer or cashier) which will be ignored
                """
                # print(all_iden)

                # Case 1 (Drop the track when it is not visible after stop_track frame)
                if int(self.tracked_id) != -1 and int(self.tracked_id) not in all_iden:
                    print("deduce1 left: ", self.stop_track)
                    self.stop_track -= 1

                # Customer leaving
                    """
                    isPersonCustomerTemp to get the last frame of customer leaving the customer box. This make the detection of
                        customer leaving the box to be one frame later.
                    int(c) == 1 to ensure the taken value is the customer box
                    int(iden) == int(customer_id) to get the specific customer that leaves the customer box
                    """
                # Case 1 (When it reaches stop_track frames)
                if self.stop_track == 0:
                    print("Tracked id dropped")
                    # Reset tracked_id, this prevent this tracked_id on tracking disappeared id which cause the prevention of turning
                    #   is_transaction_sent to False, and to start tracking the new customer id
                    # Reset the stop_trck
                    self.tracked_id = -1
                    self.stop_track = 3

                # Case 2 (When the tracked_id as customer is move out of ROI, that is happen exactly when their intersection is 0)
                if int(c) == 1 and int(iden) == int(self.tracked_id):
                    print("Customer leaving")
                    cv2.waitKey(2000)

                    # Customer leaving indicating end of transaction, therefore
                    # Stop track the id --> tracked_id = -1
                    # Turn is_transaction_sent to False
                    # Reset the cash_id to start get new id
                    self.tracked_id = -1
                    self.is_transaction_sent = False
                    self.cash_id = -1
                    self.stop_track = 3
            else:
                # print("there is intersection")
                # The first encounter that meet these 3 requirements is the one with the highest intersection value
                # This is because the list is sorted in descending in respect to the intersection.
                if int(c) == 0 and int(cate) == 0:
                    # Start tracking cashier id
                    if not haveCashier:
                        # print(iden)
                        self.cashier_id = iden
                        haveCashier = True

                # The first encounter that meet these 3 requirements is the one with the highest intersection value
                elif int(c) == 1 and int(cate) == 0:
                    # Start tracking customer id
                    if not haveCustomer:
                        # print(iden)
                        self.customer_id = iden
                        haveCustomer = True
                        # Assign new id if havent
                        if int(self.tracked_id) == -1:
                            self.tracked_id = self.customer_id

                # The first encounter that meet these 3 requirements is the one with the highest intersection value
                # int(cash_id) == -1 is to make sure it track only the frame where cash is visible in the customer ROI
                elif int(c) == 1 and int(cate) == 1 and int(self.cash_id) == -1:
                    if not haveCash:
                        # print(iden)
                        self.cash_id = iden
                        haveCash = True

        # print("tracked_id: ", tracked_id)
        # print("cashier id: ", cas_id)
        # print("customer id: ", cus_id)
        # print("cashier_id: ", cash_id)

        # When all the haveCashier, haveCustomer and haveCash is True, indicating cashier in cashier ROI, customer in customer ROI ,
            # and cash in customer ROI (customer paying by cash)
        if(self.cashier_id != -1 and self.customer_id != -1 and self.cash_id != -1):
            # If the transaction not happening yet
            if not self.is_transaction_sent:
                print("Payment happening, sending data")

                # Send the time
                # current = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                current = dT(img)
                self.time_database.append(current)

                cv2.waitKey(1000)
                # Set the is_transaction_sent to True to prevent this if statement from running and causing duplicate result
                self.is_transaction_sent = True


__author__ = 'Dmitriy Korsakov'

import json
import yaml
import six
import prettytable
import re
from scalrctl import settings

def calc_vertical_table(response_json, columns):
    rows = []
    for block in response_json.get('data', ''):
        row = []
        for name in columns:
            for item in block:
                if name.lower() == item.lower():
                    row.append(block[item])
                    break
                elif name.lower() == '%s.id' % item.lower():
                    if 'id' in block[item]:
                        row.append(block[item]['id'])
                    else:
                        row.append('')
                    break
            else:
                row.append('')
        if row:
            rows.append(row)

    pagination = response_json.get("pagination", None)
    pagenum_last, current_pagenum = 1, 1
    if pagination:
        url_last = pagination.get('last', None)
        if url_last:
            number = re.search("pageNum=(\d*)", url_last)
            pagenum_last = number.group(1) if number else 1

        url_next = pagination.get('next', None)
        if url_next:
            num = re.search("pageNum=(\d*)", url_next)
            pagenum_next = num.group(1) if num else 1
            current_pagenum = int(pagenum_next) - 1
    return rows, current_pagenum, pagenum_last

def prepare_table():
    table = prettytable.PrettyTable()
    table.align = "l"
    table.right_padding_width = 4
    table.left_padding_width = 1
    table.set_style(prettytable.PLAIN_COLUMNS)
    return table

def build_vertical_table(field_names, rows, pre=None, post=None):
    table = prepare_table()

    template = '\x1b[1m%s\x1b[0m' if settings.colored_output else "%s"
    table.field_names = [template % field.upper().replace("_", " ") for field in field_names]

    for row in rows:
        table.add_row(row)

    body = table.get_string()

    if body and pre:
        body = "%s\n\n%s" % (pre, body)
    if body and post:
        body = "%s\n\n%s" % (body, post)

    return "\n%s\n" % body

def calc_horizontal_table(response_json, columns):
    rows = []
    data = response_json.get("data", {})
    for column_name in columns:
        if column_name.lower() in [d.lower() for d in data.keys()]:
            rows.append([column_name, data[column_name]])
        elif column_name.lower() in ['%s.id' % d.lower() for d in data.keys()]:
            if 'id' in data[column_name[:-3]]:
                rows.append([column_name, data[column_name[:-3]]['id']])
            else:
                rows.append([column_name, ''])
    return rows

def build_horizontal_table(rows):
    table = prepare_table()
    template = '\x1b[1m%s\x1b[0m' if settings.colored_output else "%s"
    table.field_names = [template % "PROPERTY", template % "VALUE"]
    for row in sorted(rows):
        table.add_row(row)
    return table.get_string()

def build_tree(data):
    if isinstance(data, str):
        data = json.loads(data)

    yaml_text = yaml.safe_dump(data, allow_unicode=True, default_flow_style=False)
    if six.PY2:
        yaml_text = yaml_text.decode("utf-8")

    if not settings.colored_output:
        return yaml_text

    pairs = []
    in_key = False

    for token in yaml.scan(yaml_text):

        if token.__class__ == yaml.tokens.KeyToken:
            in_key = True
            continue
        if in_key and yaml.tokens.ScalarToken == token.__class__:
            pairs.append((token.start_mark.index, token.end_mark.index))
            in_key = False

    if not pairs:
        return yaml_text

    last_pos = pairs[0][0]
    result = yaml_text[:last_pos]

    for start, end in pairs:

        result += yaml_text[last_pos:start] + "\x1b[31m" + yaml_text[start:end] + "\x1b[39m"
        last_pos = end

    result += yaml_text[last_pos:]

    return result


from __future__ import unicode_literals

from django.utils.translation import ugettext_lazy as _

from shuup.admin.modules.contact_group_price_display.views.forms import PriceDisplayChoices, get_price_display_mode
from shuup.admin.shop_provider import get_shop
from shuup.admin.toolbar import NewActionButton, SettingsActionButton, Toolbar
from shuup.admin.utils.picotable import Column
from shuup.admin.utils.views import PicotableListView
from shuup.core.models import ContactGroupPriceDisplay, get_groups_for_price_display_create, get_price_displays_for_shop
from shuup.utils.django_compat import force_text

class ContactGroupPriceDisplayListView(PicotableListView):
    model = ContactGroupPriceDisplay
    default_columns = [
        Column("group", _("Group"), display="group"),
        Column("display_mode", _("Display Mode"), display="show_display_mode"),
    ]
    toolbar_buttons_provider_key = "contact_group_price_list_toolbar_provider"
    mass_actions_provider_key = "contact_group_price_list_mass_actions_provider"

    def get_queryset(self):
        if getattr(self.request.user, "is_superuser", False):
            ContactGroupPriceDisplay.objects.all()
        shop = get_shop(self.request)
        return get_price_displays_for_shop(shop)

    def show_display_mode(self, instance):
        display_mode = get_price_display_mode(self.request, instance)
        for k, v in PriceDisplayChoices.choices():
            if k == display_mode:
                return force_text(v).title()
        return _("Unspecified")

    def get_context_data(self, **kwargs):
        context = super(ContactGroupPriceDisplayListView, self).get_context_data(**kwargs)
        if self.request.user.is_superuser:
            settings_button = SettingsActionButton.for_model(
                ContactGroupPriceDisplay, return_url="contact_group_price_display"
            )
        else:
            settings_button = None

        shop = get_shop(self.request)
        can_create = len(get_groups_for_price_display_create(shop))
        context["toolbar"] = Toolbar(
            [NewActionButton("shuup_admin:contact_group_price_display.new") if can_create else None, settings_button],
            view=self,
        )
        return context


"""Standalone command-line application that calculates the AUC
(Area Under Curve) statistic for various curves."""

import sys

from yard.data import BinaryClassifierData
from yard.curve import CurveFactory
from yard.scripts import CommandLineAppForClassifierData

__author__ = "Tamas Nepusz"
__email__ = "tamas@cs.rhul.ac.uk"
__copyright__ = "Copyright (c) 2010, Tamas Nepusz"
__license__ = "MIT"

class AUCCalculatorApplication(CommandLineAppForClassifierData):
    """\
    %prog input_file

    Standalone command-line application that calculates the AUC
    (Area Under Curve) statistic for various curves.

    The input file must contain one observation per line, the first column
    being the expected class (1 for positive examples, -1 for negatives),
    the second being the prediction itself. You can also use the -c switch
    to use different column indices and multiple datasets. Columns are
    separated by whitespace per default.\
    """

    short_name = "yard-auc"

    def __init__(self):
        super(AUCCalculatorApplication, self).__init__()

    def add_parser_options(self):
        """Creates the command line parser object for the application"""
        super(AUCCalculatorApplication, self).add_parser_options()

        parser = self.parser

        parser.add_option(
            "-t",
            "--curve-type",
            dest="curve_types",
            metavar="TYPE",
            choices=CurveFactory.get_curve_names(),
            action="append",
            default=[],
            help="sets the TYPE of the curve to be plotted "
            "(roc, pr, ac, sespe or croc). May be specified "
            "multiple times.",
        )

    def run_real(self):
        """Runs the main application"""

        # If no curve type was given, assume a ROC curve
        if not self.options.curve_types:
            self.options.curve_types = ["roc"]

        # Get the types of the curves to be plotted
        curve_classes = []
        for name in self.options.curve_types:
            try:
                curve_classes.append(CurveFactory.find_class_by_name(name))
            except ValueError:
                self.parser.error("Unknown curve type: %s" % name)

        self.process_input_files()
        for curve_class in curve_classes:
            self.print_scores_for_curve(curve_class)

    def print_scores_for_curve(self, curve_class):
        """Calculates AUC scores for curves given by `curve_class` for all
        the data in `self.data`.

        `curve_class` is a subclass of `BinaryClassifierPerformanceCurve`.
        `self.data` must be a dict of lists, and the ``__class__`` key of
        `self.data` must map to the expected classes of elements.
        """
        data = self.data
        expected = data["__class__"]

        keys = sorted(data.keys())
        keys.remove("__class__")

        print("Calculating AUCs for %s..." % curve_class.get_friendly_name())
        for key in keys:
            observed = data[key]

            bc_data = BinaryClassifierData(zip(observed, expected), title=key)
            auc = curve_class(bc_data).auc()
            print("  AUC[%s] = %.4f" % (key, auc))
        print("")

def main():
    """Entry point for the plotter script"""
    sys.exit(AUCCalculatorApplication().run())

if __name__ == "__main__":
    main()


n = int(input())
soon = list(map(int, input().split()))
i = n - 2

while 0 <= i:
    if soon[i] > soon[i + 1]:  # 바꿀 수 있는 가장 낮은 자릿수부터 탐색
        break
    else:
        i -= 1  # 자릿수 앞으로 이동하도록 인덱스 감소

if i == -1:  # n = 1인 경우 or 사전순 가장 처음일 때
    print(-1)

else:
    for j in range(i+1, len(soon)):
        if soon[i] > soon[j]:  # i보다 작되, 가장 낮은 자릿수 탐색
            jj = j

    soon[i], soon[jj] = soon[jj], soon[i]  # 두 수 위치 변경

    align = soon[i + 1:]  # i보다 낮은 자릿수들 정렬
    align.sort(reverse = True)

    print(' '.join(map(str, (soon[:i + 1] + align))))

백준/코드와트_스터디/10973_이전순열.py


import io, re, subprocess, sys, unittest
from mock import patch
from click.testing import CliRunner

from .context import hlcloud
from hlcloud import cli_buckets_make

class CliBucketsMakeTest(unittest.TestCase):

    @patch('subprocess.check_call')
    @patch('getpass.getuser')
    @patch('google.auth.default')
    def test_buckets_make(self, auth_patch, getuser_patch, checkcall_patch):
        credentials = "streetcred"
        project = "mgi-cloud"
        auth_patch.return_value = (credentials, project)
        getuser_patch.return_value = "mgi-user"
        checkcall_patch.return_value = 1

        runner = CliRunner()
        result = runner.invoke(cli_buckets_make.buckets_make_cmd, ["gs://test", "--service-accounts", "SA", "--groups", "G1", "--collaborators", "C1@abc.edu,C2@abc.edu", "-p", "mgi-project", "-l", "mgi-pipeline"])
        if result.exception:
            print("{}".format(result.exception))
        self.assertEqual(result.exit_code, 0)

        expected_out = "\n".join([
            "Make bucket: gs://test",
            "Running: gsutil mb gs://test",
            "Running: gsutil iam set /tmp/[\w\d]+ gs://test",
            "Running: gsutil defacl set bucket-owner-full-control gs://test",
            "Running: gsutil label ch -l user:mgi-user -l project:mgi-project -l pipeline:mgi-pipeline gs://test",
            "Make bucket\.\.\.SUCCESS"])
        self.assertRegex(result.output, expected_out)

# -- CliBucketsMakeTest

if __name__ == '__main__':
    unittest.main(verbosity=2)

#-- __main__


from parse_conditions_for_restrictions import ClassParser

import numpy as np
import re
from datetime import datetime
from dateutil import relativedelta

def is_blank(value):
    if value is None or value == 'NULL' or (isinstance(value, np.float) and np.isnan(value)):
        return True
    else:
        return False

def parse_conditions(condition_string):
    race_info = {
        'cond_race_class': 'NULL',
        'purse_string': 'NULL',
        'purse': 'NULL',
        'race_conditions': 'NULL',
        'weight_info': 'NULL',
        'standard_weight': 'NULL',
        'three_yo_weight': 'NULL',
        'cond_rail_distance': 'NULL',
        'weight_allowance_0_amt': 'NULL',
        'weight_allowance_0_condition': 'NULL',
        'weight_allowance_1_amt': 'NULL',
        'weight_allowance_1_condition': 'NULL',
        'weight_allowance_2_amt': 'NULL',
        'weight_allowance_2_condition': 'NULL',
        'weight_allowance_3_amt': 'NULL',
        'weight_allowance_3_condition': 'NULL',
        'cond_left_on_string': 'NULL',
    }

    # Race class
    try:
        race_class = re.match(r'[\w. ]+(?=\. )', condition_string)
        race_info['cond_race_class'] = race_class.group(0).strip()
        condition_string = condition_string[:race_class.regs[0][0]] + \
                           condition_string[race_class.regs[0][1]:]
        condition_string = condition_string[2:]
    except AttributeError:
        pass

    # Race purse info
    try:
        purse_data = re.match('Purse \$([\d;]+) (\(.+?\) )?', condition_string)
        all_purse_data = re.sub(';', '', purse_data.group(0))
        race_info['purse'] = re.sub(';', '', purse_data.group(1))
        race_info['purse_string'] = all_purse_data
        condition_string = condition_string[purse_data.end(0):]
    except AttributeError:
        pass

    # Race conditions
    try:
        race_conditions = re.match(r'[A-Z0-9 ;\$-]+. ', condition_string)
        condition_string = condition_string[race_conditions.end(0):]
    except AttributeError:
        pass

    # Weight amounts
    try:
        weight_info = re.search(r'(Weight|Three).+?\.( |$)', condition_string)
        # print(weight_info.group(0))
        race_info['weight_info'] = weight_info.group(0)

    except AttributeError:
        pass

        # Single-weight amount
    try:
        one_weight = re.match(r'[Ww]eight.+?(\d+)', weight_info.group(0))
        race_info['standard_weight'] = one_weight.group(1)
    except AttributeError:
        pass

        # Special 3-year-old weight amount
    try:
        three_yo_weights = re.search(r'[Tt]hree.+?(\d+).+?(\d+)', condition_string)
        race_info['three_yo_weight'] = three_yo_weights.group(1)
        race_info['standard_weight'] = three_yo_weights.group(2)
    except AttributeError:
        pass

    try:
        condition_string = condition_string[:weight_info.regs[0][0]] + condition_string[weight_info.regs[0][1]:]
    except AttributeError:
        pass

    # Rail distance
    try:
        rail_info = re.search(r'\(?[Rr]ail.+?(\d+).*\.', condition_string)
        # print(rail_info.group(0), rail_info.group(1))
        race_info['cond_rail_distance'] = rail_info.group(1)
        condition_string = condition_string[:rail_info.regs[0][0]] + condition_string[rail_info.regs[0][1]:]
    except AttributeError:
        pass

    # Weight allowances
    i = 0
    while re.search(r'[^.]* [Aa]llowed \d+ [^.]*\.', condition_string):
        weight_allowance = re.search(r'[^.]* [Aa]llowed (\d+)[^.]*\.', condition_string)
        # print(weight_allowance.group(0))
        condition_string = condition_string[:weight_allowance.regs[0][0]] + \
                           condition_string[weight_allowance.regs[0][1]:]
        race_info[f'weight_allowance_{i}_amt'] = weight_allowance.group(1)
        race_info[f'weight_allowance_{i}_condition'] = weight_allowance.group(0)[:255]
        i += 1
    del i

    race_info['cond_left_on_string'] = condition_string

    return race_info

def parse_age_sex_restrictions(restriction_column):

    new_columns = ['allowed_age_two',
                   'allowed_age_three',
                   'allowed_age_four',
                   'allowed_age_five',
                   'allowed_age_older',
                   'allowed_fillies',
                   'allowed_mares',
                   'allowed_colts_geldings',
                   ]

    age_mappings = {
        'AO': ['two'],
        'AU': ['two', 'three', 'four', 'five', 'older'],
        'BO': ['three'],
        'BU': ['three', 'four', 'five', 'older'],
        'CO': ['four'],
        'CU': ['four', 'five', 'older'],
        'DO': ['five'],
        'DU': ['five', 'older'],
        'EO': ['three', 'four'],
        'FO': ['four', 'five'],
        'GO': ['three', 'four', 'five'],
        'HO': ['two', 'three', 'four', 'five', 'older'],
    }

    sex_mappings = {
        'N': ['fillies', 'mares', 'colts_geldings'],
        'M': ['fillies', 'mares'],
        'F': ['fillies'],
        'C': ['colts_geldings'],
    }

    new_column_dict = dict.fromkeys(new_columns)
    for key in new_column_dict:
        new_column_dict[key] = [0 for _ in range(len(restriction_column))]

    for i in range(len(restriction_column)):
        age_sex_string = restriction_column[i]
        if (isinstance(age_sex_string, np.float) and np.isnan(age_sex_string)):
            age_sex_string = 'NULL'
        age_code = age_sex_string[:2]
        sex_code = age_sex_string[2:]
        try:
            for item in age_mappings[age_code]:
                new_column_dict[f'allowed_age_{item}'][i] = 1
        except KeyError:
            for item in age_mappings['HO']:
                new_column_dict[f'allowed_age_{item}'][i] = 'NULL'

        try:
            for item in sex_mappings[sex_code]:
                new_column_dict[f'allowed_{item}'][i] = 1
        except KeyError:
            for item in sex_mappings['N']:
                new_column_dict[f'allowed_{item}'][i] = 'NULL'

    return new_column_dict

def add_features (table_data, extension, verbose=True):
    extension = str(extension)
    if extension == '1':
        if verbose: print('Adding features to .1 file ...')
        # Parse and flatten age/sex restriction codes
        for key, value in parse_age_sex_restrictions(table_data['age_sex_restrictions']).items():
            table_data[key] = value

        #********************
        # Parse race condition string for race restrictions and add new columns to dataframe

        # Initialize instance of parsing class
        parser = ClassParser()
        condition_columns = ['race_conditions_1', 'race_conditions_2', 'race_conditions_3',
                             'race_conditions_4', 'race_conditions_5']

        # Create list of full race conditions text for processing
        condition_list = []
        for i in range(len(table_data)):
            condition_text = ''
            for column in condition_columns:
                if not is_blank(table_data[column][i]):
                    condition_text += str(table_data[column][i])
            condition_list.append(condition_text)

        # Create a list of race dates for use by the conditions_parser in computing time limits
        date_list = []
        for date in table_data['date']:
            date_list.append(datetime.strptime(str(date), '%Y%m%d'))

        # Process condition strings and add resulting columns to table
        condition_data = parser.process_condition_list(condition_list, date_list)
        for key, value in condition_data.items():
            table_data[key] = value

            ##############NEED TO ADD TO DBs AND TABLE STRUCTURE DICTS. ALSO ADD TO OTHER TABLES WITH CONDITION DATA

    if extension == '2':
        if verbose: print('Adding features to .2 file ...')

        # ************************************************
        # Flatten medication codes into individual columns
        #
        medication_col = table_data.columns.get_loc('medication_codes')
        bleeder_meds = [0 for _ in range(len(table_data))]
        bute = [0 for _ in range(len(table_data))]
        lasix = [0 for _ in range(len(table_data))]
        for i in range(len(table_data)):
            try:
                code = table_data.iloc[i, medication_col].upper()
            except AttributeError:
                code = ''
            if 'A' in code:
                bleeder_meds[i] = 1
            if 'B' in code or 'C' in code:
                bute[i] = 1
            if 'L' in code or 'M' in code:
                lasix[i] = 1
        table_data['meds_adjunct_bleeder'] = bleeder_meds
        table_data['meds_bute'] = bute
        table_data['meds_lasix'] = lasix

        # ***********************************************
        # Flatten equipment codes into individual columns
        #
        equipment_col = table_data.columns.get_loc('equipment_code')
        equipment_list = {
            '1': 'running_ws',
            '2': 'screens',
            '3': 'shields',
            'A': 'aluminum_pads',
            'B': 'blinkers',
            'C': 'mud_calks',
            'D': 'glued_shoes',
            'E': 'inner_rims',
            'F': 'front_bandages',
            'G': 'goggles',
            'H': 'outer_rims',
            'I': 'inserts',
            'J': 'aluminum_pad',
            'K': 'flipping_halter',
            'L': 'bar_shoes',
            'M': 'blocks',
            'N': 'no_whip',
            'O': 'blinkers_off',
            'P': 'pads',
            'Q': 'nasal_strip_off',
            'R': 'bar_shoe',
            'S': 'nasal_strip',
            'T': 'turndowns',
            'U': 'spurs',
            'V': 'cheek_piece',
            'W': 'queens_plates',
            'X': 'cheek_piece_off',
            'Y': 'no_shoes',
            'Z': 'tongue_tie',
        }
        equipment_dict = dict.fromkeys(list(equipment_list.values()))
        for key in equipment_dict.keys():
            equipment_dict[key] = [0 for _ in range(len(table_data))]

        for i in range(len(table_data)):
            code = table_data.iloc[i, equipment_col]
            if is_blank(code):
                continue
            for letter in code:
                equipment_dict[equipment_list[letter]][i] = 1
        for key, value in equipment_dict.items():
            table_data[key] = value

        # ***********************************************
        # Combine lead/beaten lengths columns into single column,
        # with a positive value for the leader and a negative
        # value for all trailing horses
        calls = ['start', '1st_call', '2d_call', '3d_call', 'stretch_call', 'finish']
        for call in calls:
            column_data = list()
            lead_column = table_data.columns.get_loc(f'{call}_lead')
            beaten_column = table_data.columns.get_loc(f'{call}_beaten')
            for i in range(len(table_data)):
                if not np.isnan(table_data.iloc[i, lead_column]):
                    column_data.append(table_data.iloc[i, lead_column])
                elif np.isnan(table_data.iloc[i, beaten_column]):
                    column_data.append('NULL')
                elif table_data.iloc[i, beaten_column] == 0:
                    column_data.append('NULL')
                elif table_data.iloc[i, beaten_column] != 0:
                    column_data.append(table_data.iloc[i, beaten_column] * -1)
                else:
                    print(f'logic leak\nRow: {i}')
            table_data[f'lead_or_beaten_lengths_{call}'] = column_data

    if extension == '3':
        if verbose: print('Adding features to .3 file ...')
    if extension == '4':
        if verbose: print('Adding features to .4 file ...')
    if extension == '5':
        if verbose: print('Adding features to .5 file ...')
        where_bred = list()
        foreign_bred = list(table_data['foreignbred_code'])
        state_bred = list(table_data['statebred_code'])
        foreign_bred_null = list(table_data['foreignbred_code'].isnull())

        for i in range(len(foreign_bred)):
            if foreign_bred_null[i]:
                where_bred.append(state_bred[i])
            else:
                where_bred.append(foreign_bred[i])
        table_data['where_bred'] = where_bred

    if extension == '6':
        if verbose: print('Adding features to .6 file ...')
    if extension == 'DRF':
        if verbose: print('Adding features to .DRF file ...')

        for i in range(1, 11):
            past_bullet_flag = list()
            for j in range(len(table_data)):
                if table_data[f'workout_time_{i}'][j] < 0:
                    past_bullet_flag.append(1)
                else:
                    past_bullet_flag.append(0)
            table_data[f'workout_time_{i}_bullet'] = past_bullet_flag

        for i in range(1, 11):
            table_data[f'workout_time_{i}'] = table_data[f'workout_time_{i}'].abs()

        for i in range(1, 11):
            past_about_distance = list()
            for j in range(len(table_data)):
                if table_data[f'past_distance_{i}'][j] < 0:
                    past_about_distance.append(1)
                else:
                    past_about_distance.append(0)
            table_data[f'past_distance_{i}_about_flag'] = past_about_distance
        for i in range(1, 11):
            table_data[f'past_distance_{i}'] = table_data[f'past_distance_{i}'].abs()
        for i in range(1, 11):
            table_data[f'workout_distance_{i}'] = table_data[f'workout_distance_{i}'].abs()
        table_data['distance'] = table_data['distance'].abs()

        # Extract whether there was a off turf distance change for the PP race, and add a column with a flag for that
        for i in range(1, 11):
            past_off_turf_dist_change = list()
            for j in range(len(table_data)):
                if table_data[f'past_start_code_{i}'][j] == 'x':
                    past_off_turf_dist_change.append(1)
                else:
                    past_off_turf_dist_change.append(0)
            table_data[f'past_{i}_off_turf_dist_change'] = past_off_turf_dist_change

        # Extract whether the horse used a nasal string for the PP race; add a column with a flag for that info
        # Extract whether there was a off turf distance change for the PP race, and add a column with a flag for that
        for i in range(1, 11):
            past_nasal_strip = list()
            for j in range(len(table_data)):
                if table_data[f'past_start_code_{i}'][j] == 's':
                    past_nasal_strip.append(1)
                else:
                    past_nasal_strip.append(0)
            table_data[f'past_{i}_nasal_strip'] = past_nasal_strip

        if verbose: print('Flattening medication columns')
        # Flatten medication column (this is a data_column_{} entry)
        for i in range(1, 11):
            medication_col = table_data.columns.get_loc(f'past_medication_{i}')
            bute = [0 for _ in range(len(table_data))]
            lasix = [0 for _ in range(len(table_data))]

            for j in range(len(table_data)):
                if table_data.iloc[j, medication_col] == 1:
                    lasix[j] = 1
                if table_data.iloc[j, medication_col] == 2:
                    bute[j] = 1
                if table_data.iloc[j, medication_col] == 3:
                    lasix[j] = 1
                    bute[j] = 1
            table_data[f'past_medication_{i}_lasix'] = lasix
            table_data[f'past_medication_{i}_bute'] = bute

        # ***********************************************
        # Combine lead/beaten lengths columns into single column,
        # with a positive value for the leader and a negative
        # value for all trailing horses
        if verbose: print('Combining lead/beaten lengths columns into a single column')
        calls = ['start', 'first_call', 'second_call', 'stretch_call', 'finish']
        for call in calls:
            for j in range(1, 11):
                column_data = list()
                lead_beaten_col = table_data.columns.get_loc(f'past_lead_margin_{call}_{j}')
                beaten_only_col = table_data.columns.get_loc(f'past_beaten_lengths_{call}_{j}')

                for i in range(len(table_data)):
                    if not np.isnan(table_data.iloc[i, beaten_only_col]):
                        column_data.append(table_data.iloc[i, beaten_only_col] * -1)
                    else:
                        column_data.append(table_data.iloc[i, lead_beaten_col])
                table_data[f'past_lead_or_beaten_lengths_{call}_{j}'] = column_data

        # ***********************************************
        # Parse the race conditions to add:
        #   (1) weight allowance conditions:
        #       - weight_allowance_0_amt
        #       - weight_allowance_0_condition
        #       - weight_allowance_0_amt
        #       - weight_allowance_0_condition
        #       - weight_allowance_0_amt
        #       - weight_allowance_0_condition
        #       - weight_allowance_0_amt
        #       - weight_allowance_0_condition
        # (2) weight conditions:
        #       - standard_weight
        #       - three_yo_weight
        # (3) race_class (probably duplicative of other previously provided columns)
        #       - cond_race_class
        # (4) rail distance (to confirm with previously provided column)
        #       - cond_rail_distance
        # (5) remaining unparsed portion of conditions string (for diagnostic purposes)
        #       - cond_left_on_string
        condition_fields = {
            'cond_race_class': list(),
            'standard_weight': list(),
            'three_yo_weight': list(),
            'cond_rail_distance': list(),
            'weight_allowance_0_amt': list(),
            'weight_allowance_0_condition': list(),
            'weight_allowance_1_amt': list(),
            'weight_allowance_1_condition': list(),
            'weight_allowance_2_amt': list(),
            'weight_allowance_2_condition': list(),
            'weight_allowance_3_amt': list(),
            'weight_allowance_3_condition': list(),
            'cond_left_on_string': list(),
        }
        if verbose: print('running parse_conditions')
        for i in range(len(table_data)):
            race_conditions = ['race_conditions_1', 'race_conditions_2', 'race_conditions_3',
                               'race_conditions_4', 'race_conditions_5', 'race_conditions_6', ]
            condition_string = ''
            for condition in race_conditions:
                race_condition_data = table_data[condition][i]
                if not is_blank(race_condition_data):
                    condition_string += str(race_condition_data)
                # print(condition_string)
            parsed_data = parse_conditions(condition_string)
            for key in condition_fields.keys():
                condition_fields[key].append(parsed_data[key])
        for key, value in condition_fields.items():
            table_data[key] = value

        # Parse and flatten age_sex_restriction codes, both for current race
        # and for past performance races

        for key, value in parse_age_sex_restrictions(table_data['age_sex_restricts']).items():
            table_data[key] = value

        for i in range(1, 11):
            for key, value in parse_age_sex_restrictions(table_data[f'past_age_sex_restrictions_{i}']).items():
                table_data[f'past_{key}_{i}'] = value

        #********************
        # Parse race condition string for race restrictions and add new columns to dataframe
        if verbose: print('Parsing race conditions')
        # Initialize instance of parsing class
        parser = ClassParser()
        condition_columns = ['race_conditions_1', 'race_conditions_2', 'race_conditions_3',
                             'race_conditions_4', 'race_conditions_5', 'race_conditions_6']

        # Create list of full race conditions text for processing
        condition_list = list()
        for i in range(len(table_data)):
            condition_text = ''
            for column in condition_columns:
                if not is_blank(table_data[column][i]):
                    condition_text += str(table_data[column][i])
            condition_list.append(condition_text)

        # Create a list of race dates for use by the conditions parser in computing time limits
        date_list = list()
        for date in table_data['date']:
            date_list.append(datetime.strptime(str(date), '%Y%m%d'))

        # Process condition strings and add resulting columns to table
        condition_data = parser.process_condition_list(condition_list, date_list)
        for key, value in condition_data.items():
            table_data[key] = value

    # Cover internal error values with None so that they can be put into the SQL table without throwing an error
    table_data.replace('ERROR!', np.nan, inplace=True)
    table_data.replace('ERROR!--NEGATIVE NUM', np.nan, inplace=True)
    table_data.replace('ISSUE!', np.nan, inplace=True)

    return table_data