# -*- coding: utf-8 -*-
"""
Created on Thu May 16 11:39:34 2019

@author: Ethan
"""
import matplotlib.pyplot as plt
import matplotlib.cm as cmx
import numpy as np
import pandas as pd
import pickle
import sys

plotFigs = False

returnPeriods = np.array([50, 30, 10, 5, 1, .5, .1])
returnPeriodsPrc = 1 / returnPeriods
returnPeriodLabels = ['50', '30', '10', '5', '1', '1/2', '1/10']

genData = {}
with open('genData.dat', 'rb') as f:
    genData = pickle.load(f)

tx = genData['txScatter']
gen = genData['genTxScatter']

subplotTxSummerMean = []
for s in range(tx.shape[0]):
    ind = np.where((genData['monthScatter'][s] == 7) | (genData['monthScatter'][s] == 8))[0]
    subplotTxSummerMean.append(np.nanmean(tx[s][ind]))
subplotTxSummerMean = np.array(subplotTxSummerMean)

txAll = []
genAll = []

for s in range(tx.shape[0]):
    txAll.extend(tx[s])
    genAll.extend(gen[s])

txAll = np.array(txAll)
genAll = np.array(genAll)

pBootstrap = []
zBootstrap = []

for i in range(1000):
    resampleInd = np.random.choice(len(txAll), int(len(genAll)))

    data = {'Temp':txAll[resampleInd], 'Gen':genAll[resampleInd]}
    df = pd.DataFrame(data, columns=['Temp', 'Gen'])

    df = df.dropna()

    z = np.polyfit(df['Temp'], df['Gen'], 3)
    p = np.poly1d(z)
    zBootstrap.append(z)
    pBootstrap.append(p)

# unpack polyfit coefs into lists
(p1,p2,p3,p4) = zip(*[(p[0], p[1], p[2], p[3]) for p in pBootstrap])
p1 = np.array(p1)
p2 = np.array(p2)
p3 = np.array(p3)
p4 = np.array(p4)
pSel = p4

# find percentiles for quadratic coef
pPoly10 = np.percentile(pSel, 10)
pPoly50 = np.percentile(pSel, 50)
pPoly90 = np.percentile(pSel, 90)

indPoly10 = np.where(abs(pSel-pPoly10) == np.nanmin(abs(pSel-pPoly10)))[0]
indPoly50 = np.where(abs(pSel-pPoly50) == np.nanmin(abs(pSel-pPoly50)))[0]
indPoly90 = np.where(abs(pSel-pPoly90) == np.nanmin(abs(pSel-pPoly90)))[0]

xd = np.linspace(0, 50, 200)
yPolyAll = np.array([pBootstrap[i](xd) for i in range(len(pBootstrap))])
yPolyd10 = np.array(pBootstrap[indPoly10[0]](xd))
yPolyd50 = np.array(pBootstrap[indPoly50[0]](xd))
yPolyd90 = np.array(pBootstrap[indPoly90[0]](xd))

demandPercentiles = []
for w in [0,1,2,3,4]:
    demandPercentiles.append(np.nanpercentile(pBootstrap[indPoly90[0]](txAll+w), 100-returnPeriodsPrc))
demandPercentiles = np.array(demandPercentiles)

plt.figure(figsize=(4,4))
plt.ylim([0.02, 0.07])
plt.grid(True)

plt.plot(xd, yPolyAll.T, '-', linewidth = 1, color = [.6, .6, .6], alpha = .2)
p1 = plt.plot(xd, yPolyd10, '-', linewidth = 2.5, color = cmx.tab20(0), label='10th Percentile')
p2 = plt.plot(xd, yPolyd50, '-', linewidth = 2.5, color = [0, 0, 0], label='50th Percentile')
p3 = plt.plot(xd, yPolyd90, '-', linewidth = 2.5, color = cmx.tab20(6), label='90th Percentile')

for s in range(len(subplotTxSummerMean)):
    plt.plot([subplotTxSummerMean[s], subplotTxSummerMean[s]], [0.02, 0.023], lw=3, color=cmx.tab20(0))
    plt.plot([subplotTxSummerMean[s]+4, subplotTxSummerMean[s]+4], [0.02, 0.023], lw=3, color=cmx.tab20(6))

plt.gca().set_xticks(range(0, 51, 10))

for tick in plt.gca().xaxis.get_major_ticks():
    tick.label.set_fontname('Helvetica')
    tick.label.set_fontsize(14)
for tick in plt.gca().yaxis.get_major_ticks():
    tick.label.set_fontname('Helvetica')
    tick.label.set_fontsize(14)

plt.xlabel('Daily Tx ($\degree$C)', fontname = 'Helvetica', fontsize=16)
plt.ylabel('Normalized subgrid generation', fontname = 'Helvetica', fontsize=16)

leg = plt.legend(prop = {'size':12, 'family':'Helvetica'}, loc = 'upper left')
leg.get_frame().set_linewidth(0.0)

x0,x1 = plt.gca().get_xlim()
y0,y1 = plt.gca().get_ylim()
plt.gca().set_aspect(abs(x1-x0)/abs(y1-y0))

if plotFigs:
    plt.savefig('hist-demand-temp-regression-perc.png', format='png', dpi=500, bbox_inches = 'tight', pad_inches = 0)

warming = [0, 1, 2, 3, 4]

txx = np.zeros([len(warming), genData['allTx'].shape[0], len(range(1981, 2018+1))])
for year in range(1981, 2018+1):
    ind = np.where(genData['allYears'] == year)[0]

    for s in range(genData['allTx'].shape[0]):
        for w in range(len(warming)):
            txx[w, s, year-1981] = np.nanmax(genData['allTx'][s][ind]+warming[w])

histGen10 = np.array(pBootstrap[indPoly10[0]](txx))
histGen50 = np.array(pBootstrap[indPoly50[0]](txx))
histGen90 = np.array(pBootstrap[indPoly90[0]](txx))

xd = np.array(list(range(1981, 2018+1)))-1981+1

pc = np.linspace(96.1, 95.7, len(xd))/100
pcFut10 = np.linspace(96.2, 95.5, 5)/100
pcFut50 = np.linspace(95.9, 94.8, 5)/100
pcFut90 = np.linspace(95.7, 94, 5)/100

pcWorst = np.linspace(95.7, 85, 5)/100

z = np.polyfit(xd, np.nanmean(histGen10[0,:,:], axis=0), 1)
histPolyTxx10 = np.poly1d(z)
z = np.polyfit(xd, np.nanmean(histGen50[0,:,:], axis=0), 1)
histPolyTxx50 = np.poly1d(z)
z = np.polyfit(xd, np.nanmean(histGen90[0,:,:], axis=0), 1)
histPolyTxx90 = np.poly1d(z)

plt.figure(figsize=(4,4))
plt.xlim([-1, 105])
plt.ylim([0.034, 0.042])
plt.grid(True)

plt.plot(xd, histPolyTxx10(xd), '-', linewidth = 3, color = cmx.tab20(0), alpha = .8)
#plt.plot(xd, histPolyTxx10(xd)*(pc[0]-pc+1), '--', linewidth = 3, color = cmx.tab20(0), alpha = .8)

plt.plot(xd, histPolyTxx50(xd), '-', linewidth = 3, color = [0, 0, 0], alpha = .8)
#p2 = plt.plot(xd, histPolyTxx50(xd)*(pc[0]-pc+1), '--', linewidth = 3, color = [0, 0, 0], alpha = .8, label='TXx')

plt.plot(xd, histPolyTxx90(xd), '-', linewidth = 3, color = cmx.tab20(6), alpha = .8)
#plt.plot(xd, histPolyTxx90(xd)*(pc[0]-pc+1), '--', linewidth = 3, color = cmx.tab20(6), alpha = .8)

warmGen10 = [np.nanmean(np.nanmean(histGen10[1,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen10[2,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen10[3,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen10[4,:,:], axis=1), axis=0)]
plt.plot([55, 70, 85, 100], \
         warmGen10, \
          'o', markersize=7, color=cmx.tab20(0))

warmGen50 = [np.nanmean(np.nanmean(histGen50[1,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen50[2,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen50[3,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen50[4,:,:], axis=1), axis=0)]
p1 = plt.plot([55, 70, 85, 100], \
         warmGen50, \
          'o', markersize=7, color='black', label='Without curtailment')

warmGen90 = [np.nanmean(np.nanmean(histGen90[1,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen90[2,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen90[3,:,:], axis=1), axis=0), \
          np.nanmean(np.nanmean(histGen90[4,:,:], axis=1), axis=0)]
plt.plot([55, 70, 85, 100], \
         warmGen90, \
          'o', markersize=7, color=cmx.tab20(6))

warmGen10Amp = warmGen10 * (pcFut10[0]-pcFut10[1:]+1)
plt.plot([55, 70, 85, 100], \
         warmGen10Amp, \
          'x', markersize=7, color=cmx.tab20(0))

warmGen50Amp = warmGen50 * (pcFut50[0]-pcFut50[1:]+1)
p2 = plt.plot([55, 70, 85, 100], \
         warmGen50Amp, \
          'x', markersize=7, color='black', label='With curtailment')

warmGen90Amp = warmGen90 * (pcFut90[0]-pcFut90[1:]+1)
plt.plot([55, 70, 85, 100], \
         warmGen90Amp, \
          'x', markersize=7, color=cmx.tab20(6))

#warmGen90Worst = warmGen90 * (pcWorst[0]-pcWorst+1)
#plt.plot([55, 70, 85, 100], \
#         warmGen90Worst, \
#          '+', markersize=7, color=cmx.tab20(6))

plt.plot([38,38], [0,1], '--', linewidth=2, color='black')

plt.gca().set_xticks([1, 38, 55, 70, 85, 100])
plt.gca().set_xticklabels([1981, 2018, '1$\degree$C', '2$\degree$C', '3$\degree$C', '4$\degree$C'])

for tick in plt.gca().xaxis.get_major_ticks():
    tick.label.set_fontname('Helvetica')
    tick.label.set_fontsize(14)
for tick in plt.gca().yaxis.get_major_ticks():
    tick.label.set_fontname('Helvetica')
    tick.label.set_fontsize(14)

plt.ylabel('Normalized subgrid generation', fontname = 'Helvetica', fontsize=16)

leg = plt.legend(prop = {'size':12, 'family':'Helvetica'}, loc='upper left')
leg.get_frame().set_linewidth(0.0)

x0,x1 = plt.gca().get_xlim()
y0,y1 = plt.gca().get_ylim()
plt.gca().set_aspect(abs(x1-x0)/abs(y1-y0))

if plotFigs:
    plt.savefig('hist-fut-gen-chg.eps', format='eps', dpi=500, bbox_inches = 'tight', pad_inches = 0)

chg10 = (warmGen10-np.nanmean(histPolyTxx10(xd))) / np.nanmean(histPolyTxx10(xd))
chg10Amp = (warmGen10Amp-np.nanmean(histPolyTxx10(xd))) / np.nanmean(histPolyTxx10(xd))
chg50 = (warmGen50-np.nanmean(histPolyTxx50(xd))) / np.nanmean(histPolyTxx50(xd))
chg50Amp = (warmGen50Amp-np.nanmean(histPolyTxx50(xd))) / np.nanmean(histPolyTxx50(xd))
chg90 = (warmGen90-np.nanmean(histPolyTxx90(xd))) / np.nanmean(histPolyTxx90(xd))
chg90Amp = (warmGen90Amp-np.nanmean(histPolyTxx90(xd))) / np.nanmean(histPolyTxx90(xd))

diff10 = (chg10Amp-chg10)*100
diff50 = (chg50Amp-chg50)*100
diff90 = (chg90Amp-chg90)*100

plt.figure(figsize=(4,4))
plt.ylim([0, 3.2])
plt.grid(True)

plt.plot([1,2,3,4], diff10, 'o', markersize=7, color = cmx.tab20(0))
p2 = plt.plot([1,2,3,4], diff50, 'o', markersize=7, color = [0, 0, 0], label='TXx')
plt.plot([1,2,3,4], diff90, 'o', markersize=7, color = cmx.tab20(6))

plt.gca().set_xticks([1, 2, 3, 4])
plt.gca().set_xticklabels(['1$\degree$C', '2$\degree$C', '3$\degree$C', '4$\degree$C'])

for tick in plt.gca().xaxis.get_major_ticks():
    tick.label.set_fontname('Helvetica')
    tick.label.set_fontsize(14)
for tick in plt.gca().yaxis.get_major_ticks():
    tick.label.set_fontname('Helvetica')
    tick.label.set_fontsize(14)

plt.xlabel('Mean warming', fontname = 'Helvetica', fontsize=16)
plt.ylabel('Additional generation (%)', fontname = 'Helvetica', fontsize=16)

x0,x1 = plt.gca().get_xlim()
y0,y1 = plt.gca().get_ylim()
plt.gca().set_aspect(abs(x1-x0)/abs(y1-y0))

if plotFigs:
    plt.savefig('subgrid-additional-gen.eps', format='eps', dpi=500, bbox_inches = 'tight', pad_inches = 0)


import time
import unittest
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

# Selenium is a "property based" tool, a.k.a "second generation".
# Might wanna look up what that means, since you slept through that
# part of the lecture.

driver = webdriver.Chrome()

# launch the app
driver.get("http://www.wikipedia.org")
time.sleep(2)

# find elements
driver.find_element_by_id("js-link-box-en").click()
time.sleep(2)

# interact
driver.find_element_by_id("searchInput").send_keys("tiger")
time.sleep(2)
driver.find_element_by_id("searchInput").send_keys(Keys.ENTER)
time.sleep(2)

# check
assert "Tiger - Wikipedia" == driver.title

assert "Tiger" == driver.find_element_by_id("firstHeading").text

print("all good")

driver.close()

# Pretty cool tool. Might be able to use this for a bunch of
# fun online automation things. HLTV stats perhaps? Quickly
# calculating


import argparse

import numpy as np
from vispy import app, scene
from vispy.io import imread, load_data_file, read_mesh
from vispy.scene.visuals import Mesh
from vispy.scene import transforms
from vispy.visuals.filters import TextureFilter

parser = argparse.ArgumentParser()
parser.add_argument('--shading', default='smooth',
                    choices=['none', 'flat', 'smooth'],
                    help="shading mode")
args, _ = parser.parse_known_args()

dir = '/Users/liuchu/code_every_day/games102/hw8'
mesh_path = load_data_file('spot/spot.obj.gz')
texture_path = load_data_file('spot/spot.png')
vertices, faces, normals, texcoords = read_mesh(mesh_path)
print(texcoords)
texture = np.flipud(imread(texture_path))

canvas = scene.SceneCanvas(keys='interactive', bgcolor='white',
                           size=(800, 600))
view = canvas.central_widget.add_view()

view.camera = 'arcball'
# Adapt the depth to the scale of the mesh to avoid rendering artefacts.
view.camera.depth_value = 10 * (vertices.max() - vertices.min())

shading = None if args.shading == 'none' else args.shading
mesh = Mesh(vertices, faces, shading=shading, color='white')
mesh.transform = transforms.MatrixTransform()
mesh.transform.rotate(90, (1, 0, 0))
mesh.transform.rotate(135, (0, 0, 1))
mesh.shading_filter.shininess = 1e+1
view.add(mesh)
texture = np.flipud(imread(texture_path))
texture_filter = TextureFilter(texture, texcoords)
mesh.attach(texture_filter)

@canvas.events.key_press.connect
def on_key_press(event):
    if event.key == "t":
        texture_filter.enabled = not texture_filter.enabled
        mesh.update()

def attach_headlight(mesh, view, canvas):
    light_dir = (0, 1, 0, 0)
    mesh.shading_filter.light_dir = light_dir[:3]
    initial_light_dir = view.camera.transform.imap(light_dir)

    @view.scene.transform.changed.connect
    def on_transform_change(event):
        transform = view.camera.transform
        mesh.shading_filter.light_dir = transform.map(initial_light_dir)[:3]

attach_headlight(mesh, view, canvas)

canvas.show()

if __name__ == "__main__":
    app.run()


# example 1

i = 1
while i<= 50:
    print(i)
    i = i+1
print("Done")

# example 2

i = 0
while i<2:
    print("Harry")
    i = i+1  # this loop becomes finite by adding this addition


import sys

def rotate(l, n): #Args: l = list, n=number
    return l[n:] + l[:n]

def toyTetragraphHash(msg):
	msg = msg.replace(" ","") #Remove spaces and punctuation
	msg = msg.replace(".", "")
	msg = msg.replace("?", "")
	msg = msg.replace("!","")
	msg = msg.replace("\n","")
	msg = msg.lower() #convert to lowercase
	while len(msg)%16!=0:
		msg+="a" #pad message with null char (a)

	blocks = [[[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]] for x in range(len(msg)//16)] #Initialize each block to 4x4 matrix of zeros
	charMap = {chr(x+97):x for x in range(26)} #Dictionary lookup builder
	for charIdx in range(len(msg)):
		blockIdx = charIdx//16 #Block number is floor of charIdx / 16
		rowIdx = charIdx%16//4 #Character in block is idx%16, 4 rows and row idx is floor of charIdx / 4
		colIdx = charIdx%4     #4 columns, colIdx is charIdx mod 4
		blocks[blockIdx][rowIdx][colIdx] = charMap[msg[charIdx]]

	RunningTotal = [0,0,0,0]
	for block in blocks:
		#Phase 1
		for i in range(4):
			for j in range(4):
				RunningTotal[i]+=block[j][i] #Add each row in column j
			RunningTotal[i]%=26 #Mod 26
		#Phase 2
		ShiftedBlock = [rotate(block[0],1),rotate(block[1],2),rotate(block[2],3),list(reversed(block[3]))]
		for i in range(4):
			for j in range(4):
				RunningTotal[i]+=ShiftedBlock[j][i]
			RunningTotal[i]%=26
	charMapReverse = {x:chr(x+97) for x in range(26)} #Dictionary lookup builder
	return ((''.join([charMapReverse[RunningTotal[i]] for i in range(4)])).upper())

for i in sys.stdin.readlines():
	print(toyTetragraphHash(i))


import time

import pyautogui

# move: 현재 좌표에서 10,100만큼 이동
# pyautogui.move(10,100,duration =1)

# moveTo: 절대 좌표에서 10,100만큼 이동
# pyautogui.moveTo(10,100,duration =1)

# 현재 좌표 가져오기
pos = pyautogui.position()
print(pos)

pyautogui.click(20,1050,duration =1)
time.sleep(1)
pyautogui.click(389,599,duration =1)


#!/usr/bin/python

# sim_index.py
import numpy as np
import wx
import wx.lib.scrolledpanel as scrolled

class Sim_Index(scrolled.ScrolledPanel):

    def __init__(self, parent, simulation, color):
        scrolled.ScrolledPanel.__init__(self, parent, id = -1,  style = wx.TAB_TRAVERSAL|wx.SUNKEN_BORDER)

        sim_color = simulation.sim_color if simulation.sim_color else color

        self.sdrdf = simulation.sdrdf#[2.5,1.5,1,.8,2.5,1.5,1,.8,2.5,1.5,1,.8,2.5,1.5,1,.8]
        self.sdrdflen = len(self.sdrdf)

        self.srdf = simulation.srdf

        #fcc_sim = [111,122,220,400,111,122,220,400,111,122,220,400,111,122,220,400]
        self.peak_index_labels = simulation.peak_index_labels

        wx.StaticText(self, -1, 'Legend Label: ', (20, 5))

        self.sim_label_tc = wx.TextCtrl(self, -1, '',  (130, 0), (130, -1))
        sim_label_text = simulation.sim_label
        self.sim_label_tc.SetValue(sim_label_text)

        wx.StaticText(self, -1, 'Simulation Intensity: ', (20, 35))

        self.sim_intens_tc = wx.TextCtrl(self, -1, '',  (200, 30), (60, -1))
        sim_intens_text = str(simulation.sim_intens)
        self.sim_intens_tc.SetValue(sim_intens_text)

        wx.StaticText(self, -1, 'Simulation Color: ', (20, 65))

        self.colorpicker = wx.ColourPickerCtrl(self, -1, colour=sim_color, pos=(200, 60),
                 size=(60, 30), name='Simulation Color')
        #self.sim_color_tc = wx.TextCtrl(self, -1, '',  (150, 60), (90, -1))
        #self.colorDlgBtn = wx.Button(self,  -1, "...",  (240, 60), (20, -1))
        #self.colorDlgBtn.Bind(wx.EVT_BUTTON, self.onColorDlg)
        #self.sim_color_tc.SetValue('#ffffff')

        vbox = wx.BoxSizer(wx.VERTICAL)

        offset = 4
        sp = 30
        i = offset
        for peak, intens in zip(self.sdrdf,self.srdf):
            static = wx.StaticText(self, -1, str(i-offset+1) + '-', (20, sp*i+5))
            static1 = wx.StaticText(self, -1, 'd:', (60, sp*i+5))
            dspace = 1/peak
            wx.StaticText(self, -1, str('%.2f' % dspace) + u' \u00c5', (75, sp*i+5))

            static2 = wx.StaticText(self, -1,'i:', (140, sp*i+5))
            wx.StaticText(self, -1, str('%.2f' % intens), (153, sp*i+5))
            i += 1

        vbox.Add((250,sp*i+5), wx.EXPAND, 0)

        if len(self.peak_index_labels)==0:
            i = offset
            self.peak_index_tc=[]
            for peak_index_label in self.sdrdf:
                self.peak_index_tc += [wx.TextCtrl(self, -1, '',  (200, sp*i), (60, -1))]
                #self.peak_index_tc[i-1].SetValue(str(au_radius))
                i += 1
        else:
            i = offset
            self.peak_index_tc=[]
            for peak_index_label in self.peak_index_labels[:self.sdrdflen]:
                self.peak_index_tc += [wx.TextCtrl(self, -1, '',  (200, sp*i), (60, -1))]
                self.peak_index_tc[i-offset].SetValue(str(peak_index_label))
                i += 1

        self.SetSizer(vbox)
        self.SetupScrolling()

#    def onColorDlg(self, event):
#        """
#        This is mostly from the wxPython Demo!
#        """
#        dlg = wx.ColourDialog(self)
#
#        # Ensure the full colour dialog is displayed,
#        # not the abbreviated version.
#        dlg.GetColourData().SetChooseFull(True)
#
#        if dlg.ShowModal() == wx.ID_OK:
#            data = dlg.GetColourData()
#            self.sim_color_tc.SetValue('#%02x%02x%02x' % data.GetColour().Get())
#            print ('#%02x%02x%02x' % data.GetColour().Get())
#
#        dlg.Destroy()

class Index(wx.Dialog):
    def __init__(self, parent, id, title):

        window_height = 500
        wx.Dialog.__init__(self, parent, id, title, wx.DefaultPosition, wx.Size(350, window_height))

        wx.StaticText(self, -1, 'Enter or edit the peak indices and title\nfor the imported simulations', (20,20))

        nb = wx.Notebook(self, -1, pos = (25, 70), size = (300, 350), style=wx.NB_TOP)

        self.parent = parent
        self.simulations = parent.simulations

        if len(self.simulations) >= 3:
            sim_len_i = 3
        else:
            sim_len_i = len(self.simulations)
        print(sim_len_i)#,self.srdfb[sim_len_i[0]],self.sdrdfb[sim_len_i[0]])

        color = ['#42D151','#2AA298','#E7E73C']

        for i, simulation in enumerate(self.simulations[-sim_len_i:]):
            sim = Sim_Index(nb,simulation,color[i])
            simulation.sim_tcs = sim
            nb.AddPage(sim, simulation.sim_name)

        set_btn = wx.Button(self, 1, 'Edit Labels', (70, window_height-55))
        set_btn.SetFocus()
        clear_btn = wx.Button(self, 2, 'Cancel', (185, window_height-55))

        self.Bind(wx.EVT_BUTTON, self.OnIndex, id=1)
        self.Bind(wx.EVT_BUTTON, self.OnClose, id=2)
        self.Bind(wx.EVT_CLOSE, self.OnClose)

    def OnIndex(self, event):
        if len(self.simulations) >= 3:
            sim_len_i = 3
        else:
            sim_len_i = len(self.simulations)
        print(sim_len_i)#,self.srdfb[sim_len_i[0]],self.sdrdfb[sim_len_i[0]])
        for simulation in self.simulations[-sim_len_i:]:
            peak_index_labels = []

            for peak_index_tc in simulation.sim_tcs.peak_index_tc:
                peak_index_labels += [peak_index_tc.GetValue()]
            print(simulation.sim_tcs.colorpicker.GetColour(), simulation.sim_tcs.colorpicker.GetColour()[0:3])
            simulation.edit_index_labels(peak_index_labels, simulation.sim_tcs.sim_label_tc.GetValue(), simulation.sim_tcs.sim_intens_tc.GetValue(), simulation.sim_tcs.colorpicker.GetColour())
        self.Destroy()

        self.parent.axes.cla()
        self.parent.plot(2,'b')

        self.parent.axes.figure.canvas.draw()

    def OnClose(self, event):
        self.Destroy()

class Simulation:
    """
    Simulation label and index
    """
    def __init__(self, sim_name, sim_open, peak_index_labels=[]):
        if len(sim_open.shape) == 1: # it's a records array
            sdrdf = sim_open['inv_d']
            srdf = sim_open['intensity']
            self.sim_intens = 1
        else:
            theta_2 = sim_open[:,0]
            inv_d = (2*np.sin(((theta_2/180)*np.pi)/2.))/.5

            intensity = sim_open[:,1]
            intensity /= intensity.max()

            print(sim_open.shape, len(theta_2), len(intensity))

            srdf = intensity
            sdrdf = inv_d
            self.sim_intens = 1

            sim_index = np.nonzero(srdf!=0)

            sdrdf = sdrdf[sim_index]
            srdf = srdf[sim_index]

        self.sdrdf = sdrdf
        self.srdf = srdf

        self.sim_name = sim_name
        self.sim_label = sim_name

        self.peak_index_labels = list(peak_index_labels)
        self.sim_tcs = []
        self.sim_color = 0

        #print(1/array(sim_scatter))

        #print(imgcal)

        #filen=(simname + '.txt')
        #data = loadtxt(filen,skiprows=0)
        ##print(data)

        #srdf = data[:,1]
        #sdrdf = data[:,0]

        #start =20
        #dsdrdf = linspace(0,sdrdf[-1],boxs)

        print(self.sdrdf, self.srdf)

    def edit_index_labels(self, index_labels, sim_label, sim_intens, sim_color):
        self.peak_index_labels = index_labels
        self.sim_label = sim_label
        self.sim_intens = float(sim_intens)
        self.sim_color = '#%02x%02x%02x' % sim_color[0:3]

#app = wx.App()
#dlg = Index(None, -1, 'Index Peaks')
#dlg.Show(True)
#app.MainLoop()


print()
print('- - - - - - - - - - - - - - - - - - ')
print('--- Дополнить телефонный справочник возможностью изменения и удаления данных. ---')
print('--- Пользователь также может ввести имя или фамилию, ---')
print('--- и Вы должны реализовать функционал для изменения и удаления данных. ---')
print('- - - - - - - - - - - - - - - - - - ')
print()

# -I- -----------------------------------------------------
import pickle
# -F- ------------------------------------------------------

# функция для отображения всего справочника
def show_all():
    for name, phone in address_book.items():
        print(f'{name} - {phone}')

# функция для поиска абонента по фамилии
def find_by_last_name(last_name):
    for name, phone in address_book.items():
        if last_name in name:
            print(f'{name} - {phone}')

# функция для поиска абонента по номеру телефона
def find_by_phone(phone):
    for name, number in address_book.items():
        if phone == number:
            print(f'{name} - {number}')

# функция для добавления нового абонента
def add_entry(name, phone):
    address_book[name] = phone
    print(f'{name} - {phone} has been added')

# функция для удаления абонента из справочника
def delete_entry(name):
    deleted = address_book.pop(name, None)
    if deleted:
        print(f'{name} - {deleted} has been deleted')
    else:
        print(f'{name} was not found in the address book')

# функция для сохранения справочника в бинарном формате
def save_address_book():
    with open('address_book.bin', 'wb') as f:
        pickle.dump(address_book, f)

# функция для загрузки справочника из бинарного формата
def load_address_book():
    global address_book
    with open('address_book.bin', 'rb') as f:
        address_book = pickle.load(f)

# -F- ------------------------------------------------------
# [ ] -------------------------------------------------->->->

# исходные данные
address_book = {
    'Иванов Иван': '111-11-11',
    'Петров Петр': '222-22-22',
    'Сидоров Сидор': '333-33-33'
}

# основной цикл программы
while True:
    print('\nЧто вы хотите сделать?')
    print('1. Отобразить весь справочник')
    print('2. Найти абонента по фамилии')
    print('3. Найти абонента по номеру телефона')
    print('4. Добавить абонента в справочник')
    print('5. Удалить абонента из справочника')
    print('6. Сохранить справочник в бинарном формате')
    print('7. Загрузить справочник из бинарного формата')
    print('8. Закончить работу')

    choice = input('Введите число: ')

    if choice == '1':
        show_all()
    elif choice == '2':
        last_name = input('Введите фамилию: ')
        find_by_last_name(last_name)
    elif choice == '3':
        phone = input('Введите номер телефона: ')
        find_by_phone(phone)
    elif choice == '4':
        name = input('Введите имя и фамилию через пробел: ')
        phone = input('Введите номер телефона: ')
        add_entry(name, phone)
    elif choice == '5':
        name = input('Введите имя и фамилию через пробел: ')
        delete_entry(name)
    elif choice == '6':
        save_address_book()
    elif choice == '7':
        load_address_book()
    elif choice == '8':
        break
    else:
        print('Ошибка ввода')

print('Работа программы завершена.')

# [ ] -------------------------------------------------<-<-<-
print()
print('- - - - - - - - - - - - - - - - - - ')


import h5py
import numpy as np
#
#
file = h5py.File('FakeDim_remove.h5','w')
#
# Create  dataset under the Root group.
#
comp_type = np.dtype([('Orbit', 'i'), ('Temperature', 'f8')])
dataset = file.create_dataset("DSC",(2,), maxshape=(None,),chunks=(2,),dtype=comp_type)
data = np.array([(1153, 53.23), (1184, 55.12)], dtype = comp_type)
dataset[...] = data
comp_type1 = np.dtype([('Pressure', 'f8'), ('index', 'i')])
dataset = file.create_dataset("dummy",(3,), maxshape=(None,),chunks=(3,),dtype=comp_type1)
data = np.array([(999.0, 1), (997.0, 2),(996.0,3)], dtype = comp_type1)
dataset[...] = data
atomic_array = np.arange(4)
dataset = file.create_dataset("atomic",(4,),maxshape=(None,),chunks=(4,),data=atomic_array,dtype='i2')
dataset_dim = file.create_dataset("dima",(4,),maxshape=(None,),chunks=(4,),data=atomic_array,dtype='i2')
file["dima"].dims.create_scale(file["dima"])
file["atomic"].dims[0].attach_scale(file["dima"])

#
# Close the file before exiting
#
file.close()


def solution(s):
    stack = []
    PAIRS = {"(": ")", "[": "]", "{": "}"}

    for chr in s:
        if len(stack) == 0 and chr not in PAIRS:
            return False
            break
        elif chr in PAIRS:
            stack.append(chr)
        elif chr == PAIRS[stack[-1]]:
            stack.pop()
        else:
            return False
            break

    return len(stack) == 0

programmers/코딩테스트 대비반/2주차/대중소 괄호 짝 맞추기.py

대중소 괄호 짝 맞추기.py


# pylint:disable=g-multiple-import
"""Creates an environment for the lowest level of a hierarchical framework"""
import sys
import inspect
import os

from hct.envs.goal import Goal
from hct.envs.tools import *
from hct.envs.ant_test import AntTest
from hct.training.configs import NetworkArchitecture, SMALL_TRANSFORMER_CONFIGS, DEFAULT_MLP_CONFIGS
from hct.io import model
from hct.envs.maze.maze_attributes import *

from brax import base, generalized
from brax.envs.base import Env, PipelineEnv, State
from brax.io import mjcf
from brax.kinematics import forward

from etils import epath

import jax
from jax import numpy as jp

from typing import Optional, Literal, Tuple

from absl import logging

class FlatMazeEnv(PipelineEnv):

  def __init__(
    self,
    task_information: bool = False,
    reward_per_milestone = 1,
    reward_sparsity = 1,
    architecture_name='MLP',
    architecture_configs=DEFAULT_MLP_CONFIGS, # trial larger network
    reward_type: Literal['sparse', 'sparse_with_information', 'dense'] = 'sparse',
    reward_movement: Literal['position', 'velocity'] = 'velocity',
    **kwargs
  ):

    frame = inspect.currentframe()
    args, _, _, values = inspect.getargvalues(frame)
    self.parameters = {arg: values[arg] for arg in args}
    self.parameters.pop('self')

    logging.info('Initialising environment...')

    path = epath.resource_path('hct') / f'envs/assets/ant_maze.xml'
    sys = mjcf.load(path)

    n_frames = 5

    backend = 'positional'

    if backend in ['spring', 'positional']:
      sys = sys.replace(dt=0.005)
      n_frames = 10

    if backend == 'positional':
      sys = sys.replace(
        actuator=sys.actuator.replace(
          gear=200 * jp.ones_like(sys.actuator.gear)
        )
      )

    kwargs['n_frames'] = kwargs.get('n_frames', n_frames)

    super().__init__(sys=sys, backend=backend, **kwargs)

    # Agent attributes
    self.dof = jp.array(self.sys.dof.limit).T.shape[0]
    self.num_links = sys.num_links()
    self.link_parents = sys.link_parents
    self.task_information = task_information

    # Reward attributes
    self.reward_milestone = reward_sparsity * reward_per_milestone
    self.reward_sparsity = reward_sparsity
    self.reward_type = reward_type
    self.reward_movement = reward_movement

    self.non_actuator_nodes = 0
    self.action_mask = None
    self.num_nodes = 9
    self.obs_mask = None

    # Network architecture
    self.network_architecture = NetworkArchitecture.create(name=architecture_name, **architecture_configs)
    num_attn_heads = self.network_architecture.configs['policy_num_heads'] if self.network_architecture.name=='Transformer' else 2
    self.max_actions_per_node = 1 if self.network_architecture.name=='Transformer' else 8

    # Observation attributes
    self.root_mask = base.Transform(jp.array([0.0, 0.0, 1.0]), jp.array([1.0, 1.0, 1.0, 1.0]))
    self.state_obs_width = 13
    concat_obs_width = self.state_obs_width
    if concat_obs_width % num_attn_heads != 0:
        self.concat_obs_width = ((concat_obs_width // num_attn_heads) + 1) * num_attn_heads
    else:
        self.concat_obs_width = concat_obs_width

    self.action_repeat = 1
    self.episode_length = 1000
    self.action_shape = (8, 1)

    logging.info('Environment initialised.')

  def reset(self, rng: jp.ndarray) -> State:
    """Resets the environment to an initial state."""
    return reset(self, rng)

  def step(self, state: State, action: jp.ndarray) -> State:
    """Run one timestep of the environment's dynamics."""
    return step(self, state, action)

  def take_action(self, state: State, action: jp.array, rng):
    return self.pipeline_step(state, action), rng

  def get_obs(self, state: base.State) -> jp.ndarray:
    """
    Processes a state and goal into observation format

    Args:
        state: dynamic State object, changing every step
        goal: Goal object, containing egocentric Transform goals
          and/or world frame velocity goals

    Returns:
        obs: (num_links, 13 + goal_size) array containing goal observations:
    """

    def _get_state_obs(state: Union[base.State, Goal]):
      """Returns world root position (masking XY position) and limb position relative to parent"""
      return self._world_to_relative(state)

    sx, sxd =  _get_state_obs(state)
    sx, sxd = concatenate_attrs(sx), concatenate_attrs(sxd)

    obs = jp.concatenate([sx, sxd], axis = -1)

    if self.network_architecture.name == 'MLP':
      obs = obs.reshape(*obs.shape[:-2], -1)

    return obs

  def _world_to_relative(self, state: base.State):
    return world_to_relative(state, self)

'''
def _sample_goal(self, rng: jp.ndarray, state: base.State):
    """
    Samples normalised goal and outputs a goal state

    Goal is restricted to ensure a valid state, and acheive a range of positions
    that are expected to be achieved by the optimal policy. Restictions on
      Z position of all links
      Root rotation
      Number of feet in contact with ground:
        Randomly sample an ordered subset of end effector IDs
        Ensure that these end effectors are in contact with ground

    Args:
      rng: jp.ndarray

    Returns:
      goal: Goal
    """

    rng, rng1, rng2 = jax.random.split(rng, 3)
    randint = jax.random.randint(rng1,shape=(1,), minval = 0, maxval = 4)
    randchoice = jax.random.choice(rng2, jp.array([self.goal_contact_cond, self.goal_z_cond[1]]), shape=(1,), p = jp.array([0.9, 0.1]))
    goal_contact_cond = jp.full((4,), self.goal_z_cond[1]).at[randint].set(randchoice)

    def _create_goal(g: jp.ndarray, state: base.State) -> Goal:
      """
      Creates a goal state

      Args:
        g: jp.ndarray normalised goal
        state: environment state

      Returns:
        Goal: goal state
      """
      q = q_spherical_to_quaternion(g[:self.dof], state, self.sys)
      qd = g[-self.dof:]
      x_world, xd_world = forward(self.sys, q, qd)
      x_world, xd_world = x_world * self.goal_x_mask, xd_world * self.goal_xd_mask
      x_rel, xd_rel = world_to_relative(x_world, self.sys), world_to_relative(xd_world, self.sys)
      x_rel, xd_rel = x_rel * self.goal_x_mask, xd_rel * self.goal_xd_mask
      return Goal(g, q, qd, x_world, x_rel, xd_world, xd_rel)

    def _sample(carry):
      rng, _ = carry
      rng, rng1 = jax.random.split(rng)
      g = jax.random.uniform(
        rng1,
        shape=self.goal_size,
        minval=self.goalsampler_limit[:, 0],
        maxval=self.goalsampler_limit[:, 1]
      )
      goal = _create_goal(g, state)
      return rng, goal

    def _reject(carry):
      rng, goal = carry
      #cpos_foot_z = contact(self.sys, goal.x).pos[foot_contact_idx, 2]
      foot_z = goal.x_world.pos[self.end_effector_idx, 2]
      z = goal.x_world.pos[:,2]
      polar = goal.g[4]
      cond = \
        jp.any(z < self.goal_z_cond[0]) | jp.any(z > self.goal_z_cond[1]) | \
        (polar > self.goal_polar_cond) | \
        jp.any(foot_z > goal_contact_cond)
      return cond

    init_g = jax.random.uniform(
      rng,
      shape=self.goal_size,
      minval=self.goalsampler_limit[:, 0],
      maxval=self.goalsampler_limit[:, 1]
    )

    init_val = rng, _create_goal(init_g, state)
    goal = jax.lax.while_loop(_reject, _sample, init_val)[1]

    return goal

  def _sample_goal(self, rng: jp.ndarray, state: base.State):
    """
    Samples normalised goal and outputs a goal state

    Goal is restricted to ensure a valid state, and acheive a range of positions
    that are expected to be achieved by the optimal policy. Restictions on
      Z position of all links
      Root rotation
      Number of feet in contact with ground:
        Randomly sample an ordered subset of end effector IDs
        Ensure that these end effectors are in contact with ground

    Args:
      rng: jp.ndarray

    Returns:
      goal: Goal
    """

    def _create_goal(g: jp.ndarray, state: base.State) -> Goal:
      """
      Creates a goal state

      Args:
        g: jp.ndarray normalised goal
        state: environment state

      Returns:
        Goal: goal state
      """

      q = q_spherical_to_quaternion(g[:self.dof], state, self.sys)
      qd = g[-self.dof:]
      x_world, xd_world = forward(self.sys, q, qd)
      x_world, xd_world = x_world * self.goal_x_mask, xd_world * self.goal_xd_mask
      x_rel, xd_rel = world_to_relative(x_world, self.sys), world_to_relative(xd_world, self.sys)
      x_rel, xd_rel = x_rel * self.goal_x_mask, xd_rel * self.goal_xd_mask
      return Goal(g, q, qd, x_world, x_rel, xd_world, xd_rel)

    rng, rng1, rng2 = jax.random.split(rng, 3)
    g = jax.random.uniform(
      rng,
      shape=self.goal_size,
      minval=self.goalsampler_limit[:, 0],
      maxval=self.goalsampler_limit[:, 1]
    )
    goal = _create_goal(g, state)
    z = goal.x_world.pos[:,2]
    z_root = z[0] - jp.min(z) + self.goal_z_cond[0]
    z_root = z_root + jax.random.choice(rng1, jp.array([0, 1]), p=jp.array([0.9, 0.1])) * jax.random.uniform(rng2, minval=z_root, maxval=self.goal_z_cond[1]-z_root)

    q = goal.q.at[2].set(z_root)
    qd = goal.qd
    x_world, xd_world = forward(self.sys, q, qd)
    x_world, xd_world = x_world * self.goal_x_mask, xd_world * self.goal_xd_mask
    x_rel, xd_rel = world_to_relative(x_world, self.sys), world_to_relative(xd_world, self.sys)
    x_rel, xd_rel = x_rel * self.goal_x_mask, xd_rel * self.goal_xd_mask

    return Goal(g, q, qd, x_world, x_rel, xd_world, xd_rel)

'''


from django.contrib.auth.models import AbstractUser
from django.utils.text import slugify
from django.conf import settings
from django.db import models

import uuid
import re
import os

PAGE_STATUS_DRAFT = 'a'
PAGE_STATUS_PUBLIC = 'z'
PAGE_STATUS = [
    (PAGE_STATUS_DRAFT, 'esborrany'),
    (PAGE_STATUS_PUBLIC, 'publicada'),
]

class User(AbstractUser):
  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
  email = models.EmailField(max_length=256, unique=True)

  name = models.CharField(max_length=256, blank=True, null=True, default='')

  def __str__(self):
    if self.name:
      return self.name
    else:
      return self.email

  class Meta:
    ordering = ['email']
    indexes = [
        models.Index(fields=['email']),
    ]

class Page(models.Model):
  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
  slug = models.SlugField(max_length=256, default=None, blank=True, null=True, unique=True)

  title = models.CharField(max_length=256)
  html_message = models.TextField(max_length=50000, default=None, blank=True, null=True)

  status = models.CharField(
    max_length=1,
    choices=PAGE_STATUS,
    default=PAGE_STATUS_DRAFT,
  )

  parent = models.ForeignKey('self', on_delete=models.CASCADE, default=None, blank=True, null=True, related_name='children_pages')

  show_blog = models.BooleanField(default=False)
  show_gallery = models.BooleanField(default=False)
  is_post = models.BooleanField(default=False)

  post_date = models.DateTimeField(default=None, blank=True, null=True, editable=True)
  updated_at = models.DateTimeField(auto_now=True)

  def getURL(self):
    if self.parent:
      return self.parent.getURL()+"/"+self.slug
    else:
      return "/"+self.slug

  def save(self, *args, **kwargs):
    self.full_clean()
    self.slug = slugify(self.title, allow_unicode=False)
    super().save(*args, **kwargs)

  class Meta:
    ordering = ['slug']
    indexes = [
        models.Index(fields=['parent', 'slug']),
        models.Index(fields=['is_post', 'parent', '-post_date']),
    ]

class FileAttachment(models.Model):
  id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

  name = models.CharField(max_length=256, blank=True, null=True, default='')

  filename = models.CharField(max_length=256)
  upload_path = models.CharField(max_length=256)
  filepath = models.CharField(max_length=256)

  page = models.ForeignKey(Page, on_delete=models.CASCADE, default=None, blank=True, null=True, related_name='attachments')

  is_image = models.BooleanField(default=False)
  static_url = models.CharField(max_length=256, blank=True, null=True, default='')

  def save(self, *args, **kwargs):
    if re.search('\.jpg$', self.filename.lower()) or re.search('\.jpeg$', self.filename.lower()) or re.search('\.png$', self.filename.lower()):
      self.is_image = True
    self.static_url = settings.STATIC_DOMAIN+'uploads/'+self.upload_path+'/'+self.filename
    self.full_clean()
    super().save(*args, **kwargs)

  def __str__(self):
    return self.filename

  def delete(self, *args, **kwargs):
    try:
      os.remove(self.filepath)
    except:
      pass
    super(FileAttachment, self).delete(*args, **kwargs)

  class Meta:
    ordering = ['name', '-filename']
    indexes = [
      models.Index(fields=['name', '-filename']),
      models.Index(fields=['name']),
      models.Index(fields=['page', 'name']),
    ]


"""
Generic tracking and analytics interface
Supports Google Analytics through ga.py, others may follow
"""
import six

from tardis.analytics import ga

service = ga
"""This can become a setting to other service in the future"""

track_login = service.track_login
track_logout = service.track_logout
track_download = service.track_download
# sig: label, session_id, ip, user,
# total_size=None, num_files=None,
# ua=None

class IteratorTracker(object):
    """wraps file iterator to track successful and incomplete downloads"""

    def __init__(self, iterator, tracker_data=None):
        self._iterator = iterator
        self.tracker_data = tracker_data
        self.complete = False

    def __iter__(self):
        return self

    def close(self):
        if hasattr(self._iterator, 'close'):
            self._iterator.close()

    def __next__(self):
        try:
            if six.PY3:
                return self._iterator.__next__()
            return self._iterator.next()
        except StopIteration:
            self.complete = True
            raise StopIteration()

    def next(self):
        return self.__next__()

    def __del__(self):
        if not self.complete:
            self.tracker_data['label'] = self.tracker_data.get(
                'label', '') + '-aborted'
        track_download(**self.tracker_data)


import os
import shutil
import sys

main_dir = 'D:/git/BlackHole-simulation'
v_arr = ['32']

for k in range(len(v_arr)):
    v = v_arr[k]

    dir_here = main_dir
    os.chdir(dir_here)

    try:
        shutil.rmtree('Black Hole x' + v)
    except:
        pass

    if v == '32':
        python_name = 'python'
        python_v = '32'
    else:
        python_name = 'python'
        python_v = '-amd64'

    if v == '64':
        os.system(python_name + ' setup.py build')
    else:
        os.system(python_name + ' setup.py build')

    os.chdir(dir_here + '/build')

    os.rename(main_dir + "/build/exe.win" + python_v + "-3.8",
              main_dir + "/Black Hole x" + v)

    os.chdir(dir_here)
    shutil.rmtree('build')

    dir_build = main_dir + "/Black Hole x" + v
    os.chdir(dir_build)

    arr = os.listdir()

    try:
        os.makedirs('img')
        os.makedirs('music')
        os.makedirs('text')
        os.makedirs('font')
    except:
        pass

    for k in arr:
        if "." in k:
            if k[-3:] == "png" or k[-3:] == "jpg" or k[-3:] == "gif":
                print("renaming {} to {}".format(k, 'img/' + k))
                os.rename(k, 'img/' + k)
            elif k[-3:] == "txt":
                print("renaming {} to {}".format(k, 'img/' + k))
                os.rename(k, 'text/' + k)
            elif k[-3:] == "mp3":
                print("renaming {} to {}".format(k, 'img/' + k))
                os.rename(k, 'music/' + k)
            elif k[-3:] == "ttf":
                print("renaming {} to {}".format(k, 'img/' + k))
                os.rename(k, 'font/' + k)

sys.exit()


import ctypes
import os
from ctypes.util import find_library
from signal import SIGSTOP

class Ptrace:

    def __init__(self):
        libc = ctypes.CDLL(find_library('c'), use_errno=True)
        func = ("ptrace", libc)
        prototype = ctypes.CFUNCTYPE(ctypes.c_long, ctypes.c_int, ctypes.c_int,
                                     ctypes.c_void_p, ctypes.c_void_p,
                                     use_errno=True)
        flags = (1, "request"), (1, "pid"), (1, "addr", None), (1, "data", 0)
        self._ptrace = prototype(func, flags)
        self._ptrace.errcheck = self._check_err

    def _check_err(self, result, func, args):
        if result != 0:
            errno = ctypes.get_errno()
            raise OSError(errno, os.strerror(errno))

    def attach(self, pid):
        self._ptrace(pid=pid, request=16)

    def detach(self, pid):
        self._ptrace(pid=pid, request=17)

    def cont(self, pid, signum=0):
        self._ptrace(pid=pid, request=7, data=signum)

    def wait(self, pid):
        while True:
            proc_pid, status = os.waitpid(pid, 0)
            if proc_pid == pid:
                if os.WIFSTOPPED(status):
                    signum = os.WSTOPSIG(status)
                    if signum == SIGSTOP:
                        break
                    else:
                        cont(pid, signum)


#Credits:
#M. Attene. A lightweight approach to repairing digitized polygon meshes.
#The Visual Computer, 2010. (c) Springer. DOI: 10.1007/s00371-010-0416-3
#http://pymeshfix.pyvista.org
#TetGen, a Delaunay-Based Quality Tetrahedral Mesh Generator
#https://github.com/pyvista/tetgen
#
# pip install pymeshfix
# pip install tetgen
#
import pymeshfix
import tetgen
import vedo

vedo.settings.use_depth_peeling = True

amesh = vedo.Mesh(vedo.dataurl+'290.vtk')

# repairing also closes the mesh in a nice way
meshfix = pymeshfix.MeshFix(amesh.points(), amesh.faces())
meshfix.repair()
repaired = vedo.Mesh(meshfix.mesh).linewidth(1).alpha(0.5)

# tetralize the closed surface
tet = tetgen.TetGen(repaired.points(), repaired.faces())
tet.tetrahedralize(order=1, mindihedral=20, minratio=1.5)
tmesh = vedo.TetMesh(tet.grid)

# save it to disk
#tmesh.write("my_tetmesh.vtk")

plt = vedo.Plotter(N=3, axes=1)
plt.at(0).show("Original mesh", amesh)
plt.at(1).show("Repaired mesh", repaired)
plt.at(2).show("Tetrahedral mesh\n(click & press shift-X)", tmesh.tomesh().shrink())
plt.interactive().close()


import os
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from skimage.io import imread

def is_button_clicked():
    file_type = [('Image File','.jpg .png')]
    Dir = os.path.abspath(os.path.dirname(__file__))
    filepath = filedialog.askopenfilename(filetypes=file_type, initialdir=Dir)
    image_path.set(filepath)

    img = imread(filepath)
    image_info.set('image_path (size {}x{}): '.format(img.shape[1], img.shape[0]))

def start_button_clicked():
    path = image_path.get()
    rwidth = rimage_width.get()
    rheight = rimage_height.get()
    if path == '':
        messagebox.showerror('Error', 'Please select an image file')
        return
    if rwidth == '' or rheight == '':
        messagebox.showerror('Error', 'Please enter resize value')
        return
    if not str.isdecimal(rwidth) or not str.isdecimal(rheight):
        messagebox.showerror('Error', 'Please enter numerical value in resizing parameter')
        return

    img = imread(path)
    height, width, _ = img.shape
    rwidth = int(rwidth)
    rheight = int(rheight)
    if rwidth > width: rwidth = width
    if rheight > height: rheight = height
    os.system('python seam_carving.py {} {} {}'.format(path, rwidth, rheight))

    messagebox.showinfo('Completed', 'the selected image is resized!')
    exit(0)

if __name__ == "__main__":
    root = tk.Tk()
    root.title('seam_carving')

    is_frame = tk.Frame(root)
    is_frame.grid()
    image_info = tk.StringVar()
    image_info.set('image_path: ')
    is_label = tk.Label(is_frame, textvariable=image_info)
    is_label.grid(row=0, column=0)
    image_path = tk.StringVar()
    file_entry = tk.Entry(is_frame, textvariable=image_path, width=50)
    file_entry.grid(row=0, column=1)
    is_button = tk.Button(is_frame, text='Browse', command=is_button_clicked)
    is_button.grid(row=0, column=2)

    resize_frame = tk.Frame(root)
    resize_frame.grid()
    rimage_label = tk.Label(resize_frame, text='resize: ')
    rimage_label.grid(row=1, column=0)
    rimage_width = tk.StringVar()
    rimage_width_entry = tk.Entry(resize_frame, textvariable=rimage_width, width=10)
    rimage_width_entry.grid(row=1, column=1)
    tk.Label(resize_frame, text='x').grid(row=1, column=2)
    rimage_height = tk.StringVar()
    rimage_height_entry = tk.Entry(resize_frame, textvariable=rimage_height, width=10)
    rimage_height_entry.grid(row=1, column=3)

    ok_frame = tk.Frame(root)
    ok_frame.grid()
    start_button = tk.Button(ok_frame, text='Start', command=start_button_clicked)
    start_button.grid(row=2, column=0)
    cancel_button = tk.Button(ok_frame, text='Cancel', command=quit)
    cancel_button.grid(row=2, column=1)

    root.mainloop()


import math
ints = lambda: list(map(int, input().split()))
alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
mx = 10**5
inp = lambda: int(input())

n = inp()
for _ in range(n):
    points = 0
    grid = [list(input()) for _ in range(10)]
    for i in range(10):
        for j in range(10):
            if grid[i][j] == "X":
                if 4<=j<=5 and 4<=i<=5:
                    points += 5
                elif 3<=j<=6 and 3<=i<=6:
                    points += 4
                elif 2<=j<=7 and 2<=i<=7:
                    points += 3
                elif 1<=j<=8 and 1<=i<=8:
                    points += 2
                else:
                    points += 1
    print(points)


import numpy as np
import tensorflow as tf
from tensorflow.python.keras.backend import dtype, print_tensor
from utils.thread import custom_Thread
from utils.randomTool import RandomHandler
from utils.npTcp import npTcpSender, npTcpReceiver
from utils.randomTool import get_random_mask, RandomHandler
from utils.coding import *
from utils.bnnLayers import sum_pool
from utils.np_ops import choose, extract_from_stream

def calculate_2_input_gate(a_masked: np.ndarray, b_masked: np.ndarray,
                           triple: np.ndarray, constant_computation: bool):

    ret = triple[2] ^ (a_masked & triple[1]) ^ (b_masked & triple[0])

    if constant_computation:
        ret ^= a_masked & b_masked

    return ret

def beaver_mult_bool(x_share: np.ndarray, y_share: np.ndarray, triple,
                     sender: npTcpSender, listener: npTcpReceiver,
                     constant_computation: bool):
    '''
    return z_share = x_share * y_share
    '''
    x_share_masked = x_share ^ triple[0]
    y_share_masked = y_share ^ triple[1]
    msg = np.array([x_share_masked, y_share_masked], dtype='bool')

    send_msg_thread = sender.send_ndarray_by_bytes_thread(msg, packbits=True)
    send_msg_thread.start()

    [x_other, y_other] = listener.receive_ndarray_by_bytes(size=msg.shape,
                                                           packbits=True)

    x_masked = x_share_masked ^ x_other
    y_masked = y_share_masked ^ y_other

    z_share = calculate_2_input_gate(x_masked, y_masked, triple,
                                     constant_computation)

    send_msg_thread.join()

    return z_share

def beaver_mult_bool_two_round_with_optimization(x_share: np.ndarray,
                                                 y_share: np.ndarray, triple,
                                                 sender: npTcpSender,
                                                 listener: npTcpReceiver,
                                                 constant_computation: bool):
    '''
    return z_share = x_share * y_share
    '''
    # modify d = x ^ u
    d_share = x_share ^ triple[0]
    e_share = y_share ^ triple[1]

    # print('d_share.shape:', d_share.shape)
    # print('e_share.shape:', e_share.shape)
    # print('x_share.shape:', x_share.shape)
    # print('y_share.shape:', y_share.shape)
    # print('triple[0].shape', triple[0].shape)
    # print('triple[1].shape:', triple[1].shape)
    # print(d.shape)
    # assert(np.sum(d_share[0]!=d_share[1])==0)
    # only send one element of d

    msg = np.array([d_share[0], e_share[0], e_share[1]], dtype='bool')

    send_msg_thread = sender.send_ndarray_by_bytes_thread(msg, packbits=True)
    send_msg_thread.start()
    rcv_thread = listener.receive_ndarray_by_bytes_thread(size=msg.shape,
                                                          packbits=True)
    rcv_thread.start()
    rcv_thread.join()

    [d_other_0, e_other_0, e_other_1] = rcv_thread.get_result()

    # recover the array
    d_other = np.array([d_other_0, d_other_0], dtype='bool')
    e_other = np.array([e_other_0, e_other_1], dtype='bool')

    d = d_share ^ d_other
    e = e_share ^ e_other
    z_share = triple[2] ^ (e & triple[0]) ^ (d & triple[1])

    if constant_computation:
        z_share ^= d & e

    send_msg_thread.join()

    return z_share

def calculate_3_input_gate(a_masked: np.ndarray, b_masked: np.ndarray,
                           c_masked: np.ndarray, help_tuple,
                           constant_computation: bool):
    # help_tuple: (u, v, w, uv, uw, vw, uvw)

    ret = (help_tuple[3] & c_masked) ^ (help_tuple[4] & b_masked) ^ (
        help_tuple[5] & a_masked) ^ (a_masked & b_masked & help_tuple[2]) ^ (
            a_masked & help_tuple[1] & c_masked) ^ (help_tuple[0] & b_masked
                                                    & c_masked) ^ help_tuple[6]

    if constant_computation:
        ret ^= a_masked & b_masked & c_masked

    return ret

def beaver_mult_bool_3_input(a_share: np.ndarray, b_share: np.ndarray,
                             c_share: np.ndarray, help_tuple,
                             sender: npTcpSender, listener: npTcpReceiver,
                             constant_computation: bool):
    '''
    return z_share = a_share * b_share * c_share
    help_tuple: (u, v, w, uv, uw, vw, uvw)
    '''
    a_share_masked = a_share ^ help_tuple[0]
    b_share_masked = b_share ^ help_tuple[1]
    c_share_masked = c_share ^ help_tuple[2]

    msg = np.array([a_share_masked, b_share_masked, c_share_masked],
                   dtype='bool')

    send_msg_thread = sender.send_ndarray_by_bytes_thread(msg, packbits=True)
    send_msg_thread.start()
    rcv_thread = listener.receive_ndarray_by_bytes_thread(size=msg.shape,
                                                          packbits=True)
    rcv_thread.start()

    rcv_thread.join()
    [a_other, b_other, c_other] = rcv_thread.get_result()

    a_masked = a_share_masked ^ a_other
    b_masked = b_share_masked ^ b_other
    c_masked = c_share_masked ^ c_other

    z_share = calculate_3_input_gate(a_masked, b_masked, c_masked, help_tuple,
                                     constant_computation)

    send_msg_thread.join()

    return z_share

def ot_3party(role,
              sender: list,
              listener: list,
              random_handler: RandomHandler,
              msg_0=None,
              msg_1=None,
              msg_dtype=None,
              msg_bit=None,
              msg_shape=None,
              choose_bit=None):
    '''
    role=0 means receiver
    role=1 means sender
    role=2 means role_ttp
    '''

    role_receiver = 0
    role_sender = 1
    role_ttp = 2

    ret = None

    if role == role_receiver:

        ori_shape = choose_bit.shape

        # get same random numbers with sender
        swap_bit = random_handler.get_same_random_with(role_sender,
                                                       bits=1,
                                                       size=ori_shape)
        random_handler.cnter += 1

        # Send choose_bit
        sender[role_ttp].send_ndarray_by_bytes(choose_bit ^ swap_bit,
                                               packbits=True)

        # receive the message
        ret = listener[role_ttp].receive_ndarray_by_bytes(size=ori_shape,
                                                          dtype=msg_dtype)

        # unmask the message
        mask = random_handler.get_same_random_with(role_sender,
                                                   bits=msg_bit,
                                                   size=(2, *ori_shape))
        random_handler.cnter += 1
        mask = ((True ^ choose_bit ^ swap_bit) * mask[0] +
                (choose_bit ^ swap_bit) * mask[1]).astype(ret.dtype)

        ret = ret ^ mask

    elif role == role_sender:

        # get same random numbers with receiver and swap the message
        swap_bit = random_handler.get_same_random_with(role_receiver,
                                                       bits=1,
                                                       size=msg_0.shape)
        random_handler.cnter += 1
        msg = np.zeros(shape=(2, *msg_0.shape), dtype=msg_0.dtype)
        msg[0] = choose(swap_bit, msg_0, msg_1)
        msg[1] = choose(True ^ swap_bit, msg_0, msg_1)

        # mask the message
        mask = random_handler.get_same_random_with(role_receiver,
                                                   bits=msg_bit,
                                                   size=(2, *msg_0.shape))
        random_handler.cnter += 1
        msg = msg ^ mask
        # send
        sender[role_ttp].send_ndarray_by_bytes(msg)

    elif role == role_ttp:

        # receive the choose bit from receiver
        choice_thread = listener[
            role_receiver].receive_ndarray_by_bytes_thread(msg_shape,
                                                           packbits=True)
        choice_thread.start()

        # receive the masked message from sender
        data_thread = listener[role_sender].receive_ndarray_by_bytes_thread(
            (2, *msg_shape), dtype=msg_dtype)
        data_thread.start()

        # keep the counter in sync
        random_handler.cnter += 1

        choice_thread.join()
        choose_bit = choice_thread.get_result()
        data_thread.join()
        data = data_thread.get_result()

        # select the message
        msg = ((True ^ choose_bit) * data[0] + choose_bit * data[1]).astype(
            data.dtype)

        # send the selected message to receiver
        sender[role_receiver].send_ndarray_by_bytes(msg)

    return ret

def extract_msb(role: int, listener: list, sender: list,
                random_handler: RandomHandler, a_share: np.ndarray,
                b_share: np.ndarray, total_bit: int, pos: int,
                triple: np.ndarray):
    data_owner = 0
    model_owner = 1
    ret = None
    if role == model_owner or role == data_owner:
        const_compute = True if role == model_owner else False
        p_triple = 0
        a_1 = extractbit(a_share, pos=0, n_bits=total_bit)
        b_1 = extractbit(b_share, pos=0, n_bits=total_bit)

        # 2)
        c_last = beaver_mult_bool(a_1, b_1, triple[:,
                                                   p_triple], sender[1 - role],
                                  listener[1 - role], const_compute)
        p_triple += 1

        for i in range(1, pos + 1):
            a_i = extractbit(a_share, i, total_bit)
            b_i = extractbit(b_share, i, total_bit)
            y_i = a_i ^ b_i
            # d)
            if i == pos:
                ret = y_i ^ c_last
            else:
                # a)
                d_i = beaver_mult_bool(a_i, b_i, triple[:, p_triple],
                                       sender[1 - role], listener[1 - role],
                                       const_compute)
                if const_compute:
                    d_i ^= True
                p_triple += 1

                # b)
                e_i = beaver_mult_bool(y_i, c_last, triple[:, p_triple],
                                       sender[1 - role], listener[1 - role],
                                       const_compute)
                p_triple += 1
                if const_compute:
                    e_i ^= True

                # c)
                c_i = beaver_mult_bool(e_i, d_i, triple[:, p_triple],
                                       sender[1 - role], listener[1 - role],
                                       const_compute)
                p_triple += 1
                if const_compute:
                    c_i ^= True
                c_last = c_i

        ret ^= random_handler.get_same_random_with(1 - role,
                                                   bits=1,
                                                   size=ret.shape)

    # all three party add the cnter
    random_handler.cnter += 1

    return ret

def count_ppa_n_triple(msb_pos: int):
    # msb_pos counts from zero
    ret = msb_pos
    l_bound = msb_pos - 1
    while l_bound > 0:
        is_even = False

        if l_bound % 2 == 0:
            is_even = True
            l_bound = l_bound - 1

        n_node = (l_bound + 1) // 2
        ret += n_node + n_node

        if is_even == True:
            # count the unpaired node
            l_bound = n_node + 1 - 1
        else:
            l_bound = n_node - 1
    return ret

def modify_triple_with_optimization(msb_pos, triple_do=None, triple_mo=None):
    # msb_pos is counted from zero
    # there are msb_pos + 1 bits

    p_triple = 0

    # calculate carry_bit
    p_triple += msb_pos

    # divide and conquer
    l_bound = msb_pos - 1

    while l_bound > 0:
        exist_unpaired_bits = False

        if l_bound % 2 == 0:
            l_bound = l_bound - 1
            exist_unpaired_bits = True

        # l_bound is odd
        l_idx = list(range(1, l_bound + 1, 2))
        len_l = len(l_idx)
        # len_l = l_bound // 2 + 1

        # data_1 = np.array([l_all_1, l_all_1], dtype='bool')
        # data_2 = np.array([r_all_1, carry_bit[r_idx]], dtype='bool')

        # [U, U'] -> [U, U]
        mid_p = p_triple + len_l
        nxt_p = mid_p + len_l

        # print(triple_do.shape)
        # print(triple_mo.shape)

        if triple_do is not None:
            triple_do[0, mid_p:nxt_p] = triple_do[0, p_triple:mid_p]
        if triple_mo is not None:
            triple_mo[0, mid_p:nxt_p] = triple_mo[0, p_triple:mid_p]
        p_triple = nxt_p

        if exist_unpaired_bits is True:
            len_l += 1

        l_bound = len_l - 1
        # print(l_bound, len_l)

    if (triple_do is not None) and (triple_mo is not None):
        delta = (triple_do[0] ^ triple_mo[0]) & (triple_do[1]
                                                 ^ triple_mo[1]) ^ triple_do[2]
        return delta
    elif triple_mo is not None:
        return triple_mo
    elif triple_do is not None:
        return triple_do

    return None

def extract_msb_ppa(role: int, listener: list, sender: list,
                    a_share: np.ndarray, b_share: np.ndarray, total_bit: int,
                    msb_pos: int, triple: np.ndarray):

    # msb_pos and l_bound counts from zero
    if role == 2:
        return None

    const_compute = True if role == 0 else False

    a_share_bit = list()
    b_share_bit = list()

    ret = extractbit(a_share, msb_pos, n_bits=total_bit) ^ extractbit(
        b_share, msb_pos, n_bits=total_bit)

    for i in range(0, msb_pos):
        a_share_bit.append(extractbit(a_share, i, n_bits=total_bit))
        b_share_bit.append(extractbit(b_share, i, n_bits=total_bit))

    a_share_bit = np.array(a_share_bit, dtype='bool')
    b_share_bit = np.array(b_share_bit, dtype='bool')

    p_triple = 0

    all_1 = a_share_bit ^ b_share_bit

    nxt_p = p_triple + len(a_share_bit)
    carry_bit = beaver_mult_bool(a_share_bit,
                                 b_share_bit,
                                 triple[:, p_triple:nxt_p],
                                 sender[1 - role],
                                 listener[1 - role],
                                 constant_computation=const_compute)
    p_triple = nxt_p

    l_bound = msb_pos - 1

    while l_bound > 0:
        # All the nodes are paired

        left_most_all_1 = None
        left_most_carry_bit = None

        if l_bound % 2 == 0:
            left_most_all_1 = all_1[l_bound]
            left_most_carry_bit = carry_bit[l_bound]
            l_bound = l_bound - 1

        l_idx = list(range(1, l_bound + 1, 2))
        r_idx = list(range(0, l_bound + 1, 2))
        l_all_1 = all_1[l_idx]
        r_all_1 = all_1[r_idx]

        data_1 = np.array([l_all_1, l_all_1], dtype='bool')
        data_2 = np.array([r_all_1, carry_bit[r_idx]], dtype='bool')

        nxt_p = p_triple + len(l_all_1) + len(l_all_1)
        data_ret = beaver_mult_bool(data_1,
                                    data_2,
                                    triple[:, p_triple:nxt_p].reshape(
                                        3, *data_1.shape),
                                    sender[1 - role],
                                    listener[1 - role],
                                    constant_computation=const_compute)
        p_triple = nxt_p

        all_1 = data_ret[0]
        carry_bit = data_ret[1] ^ carry_bit[l_idx]

        if left_most_all_1 is not None:
            all_1 = np.append(all_1, [left_most_all_1], axis=0)
            carry_bit = np.append(carry_bit, [left_most_carry_bit], axis=0)

        l_bound = len(all_1) - 1

    # print(p_triple, triple.shape[1],
    #         msb_pos, count_ppa_n_triple(msb_pos))
    return ret ^ carry_bit[0]

def extract_msb_ppa_with_optimize(role: int, listener: list, sender: list,
                                  a_share: np.ndarray, b_share: np.ndarray,
                                  total_bit: int, msb_pos: int,
                                  triple: np.ndarray):

    # msb_pos and l_bound counts from zero
    if role == 2:
        return None

    const_compute = True if role == 0 else False

    a_share_bit = list()
    b_share_bit = list()

    ret = extractbit(a_share, msb_pos, n_bits=total_bit) ^ extractbit(
        b_share, msb_pos, n_bits=total_bit)

    for i in range(0, msb_pos):
        a_share_bit.append(extractbit(a_share, i, n_bits=total_bit))
        b_share_bit.append(extractbit(b_share, i, n_bits=total_bit))

    a_share_bit = np.array(a_share_bit, dtype='bool')
    b_share_bit = np.array(b_share_bit, dtype='bool')

    p_triple = 0

    all_1 = a_share_bit ^ b_share_bit

    nxt_p = p_triple + len(a_share_bit)
    carry_bit = beaver_mult_bool(a_share_bit,
                                 b_share_bit,
                                 triple[:, p_triple:nxt_p],
                                 sender[1 - role],
                                 listener[1 - role],
                                 constant_computation=const_compute)
    p_triple = nxt_p

    l_bound = msb_pos - 1

    while l_bound > 0:

        # make nodes be paired
        left_most_all_1 = None
        left_most_carry_bit = None

        if l_bound % 2 == 0:
            left_most_all_1 = all_1[l_bound]
            left_most_carry_bit = carry_bit[l_bound]
            l_bound = l_bound - 1

        l_idx = list(range(1, l_bound + 1, 2))
        r_idx = list(range(0, l_bound + 1, 2))
        l_all_1 = all_1[l_idx]
        r_all_1 = all_1[r_idx]

        data_1 = np.array([l_all_1, l_all_1], dtype='bool')
        data_2 = np.array([r_all_1, carry_bit[r_idx]], dtype='bool')

        mid_p = p_triple + len(l_all_1)
        nxt_p = mid_p + len(l_all_1)
        cur_triple = triple[:, p_triple:nxt_p]
        cur_triple[0, mid_p:nxt_p] = cur_triple[0, p_triple:mid_p]
        data_ret = beaver_mult_bool_two_round_with_optimization(
            data_1,
            data_2,
            cur_triple.reshape(3, *data_1.shape),
            sender[1 - role],
            listener[1 - role],
            constant_computation=const_compute)
        p_triple = nxt_p

        all_1 = data_ret[0]
        carry_bit = data_ret[1] ^ carry_bit[l_idx]

        if left_most_all_1 is not None:
            all_1 = np.append(all_1, [left_most_all_1], axis=0)
            carry_bit = np.append(carry_bit, [left_most_carry_bit], axis=0)

        l_bound = len(all_1) - 1

    return ret ^ carry_bit[0]

def extract_msb_with_3_input_gate(role: int, listener: list, sender: list,
                                  a_share: np.ndarray, b_share: np.ndarray,
                                  total_bit: int, msb_pos: int,
                                  triple: np.ndarray, help_tuple: np.ndarray):
    '''
    help_tuple: (u, v, w, uv, uw, vw, uvw)
    '''
    # msb_pos and l_bound counts from zero
    if role == 2:
        return None

    const_compute = True if role == 0 else False

    # extract MSB
    ret = extractbit(a_share, msb_pos, n_bits=total_bit) ^ extractbit(
        b_share, msb_pos, n_bits=total_bit)

    a_share_bit = list()
    b_share_bit = list()

    # extract other bits
    for i in range(0, msb_pos):
        a_share_bit.append(extractbit(a_share, i, n_bits=total_bit))
        b_share_bit.append(extractbit(b_share, i, n_bits=total_bit))
    a_share_bit = np.array(a_share_bit, dtype='bool')
    b_share_bit = np.array(b_share_bit, dtype='bool')

    p_triple = 0
    p_help_tuple = 0

    # Start to solve the problem of the leaves

    all_1 = a_share_bit ^ b_share_bit
    p_triple_nxt = p_triple + len(a_share_bit)
    carry_bit = beaver_mult_bool(a_share_bit,
                                 b_share_bit,
                                 triple[:, p_triple:p_triple_nxt],
                                 sender[1 - role],
                                 listener[1 - role],
                                 constant_computation=const_compute)
    p_triple = p_triple_nxt

    # divide and conquer
    l_bound = msb_pos - 1

    while l_bound > 0:

        flag = (l_bound + 1) % 3
        n_paired = (l_bound + 1) // 3
        paired_l_bound = max(n_paired * 3 - 1, 0)

        l_idx = list(range(2, paired_l_bound + 1, 3))
        m_idx = list(range(1, paired_l_bound + 1, 3))
        r_idx = list(range(0, paired_l_bound + 1, 3))

        # the input of 3-input-and gate
        # print(l_bound, all_1.shape, carry_bit.shape, n_paired)
        l_all_1 = all_1[l_idx]
        m_all_1 = all_1[m_idx]
        r_all_1 = all_1[r_idx]

        l_carry_bit = carry_bit[l_idx]
        m_carry_bit = carry_bit[m_idx]
        r_carry_bit = carry_bit[r_idx]

        # the input of 2-input-and gate (the left most two bits)
        left_most_l_all_1 = None
        left_most_l_carry_bit = None
        left_most_r_all_1 = None
        left_most_r_carry_bit = None

        left_most_all_1 = None
        left_most_carry_bit = None

        if flag == 1:
            left_most_all_1 = all_1[l_bound:l_bound + 1]
            left_most_carry_bit = carry_bit[l_bound:l_bound + 1]

        elif flag == 2:
            left_most_l_all_1 = all_1[l_bound:l_bound + 1]
            left_most_l_carry_bit = carry_bit[l_bound:l_bound + 1]

            left_most_r_all_1 = all_1[l_bound - 1:l_bound]
            left_most_r_carry_bit = carry_bit[l_bound - 1:l_bound]

        cur_node_len = n_paired  # the number of 3-input gates
        p_help_tuple_nxt = p_help_tuple + cur_node_len

        # mask the input
        if n_paired > 0:
            masked_tuple_elements_sent = np.array([
                l_all_1 ^ help_tuple[0, p_help_tuple:p_help_tuple_nxt],
                m_all_1 ^ help_tuple[1, p_help_tuple:p_help_tuple_nxt],
                r_all_1 ^ help_tuple[2, p_help_tuple:p_help_tuple_nxt],
                r_carry_bit ^ help_tuple[7, p_help_tuple:p_help_tuple_nxt],
                m_carry_bit ^ help_tuple[11, p_help_tuple:p_help_tuple_nxt]
            ])
            data_sent = masked_tuple_elements_sent.reshape(-1)

        if flag == 2:
            masked_triple_elements_sent = np.array([
                left_most_l_all_1 ^ triple[0, p_triple:p_triple + 1],
                left_most_r_all_1 ^ triple[1, p_triple:p_triple + 1],
                left_most_l_all_1 ^ triple[0, p_triple + 1:p_triple + 2],
                left_most_r_carry_bit ^ triple[1, p_triple + 1:p_triple + 2]
            ],
                dtype='bool')
            if n_paired == 0:
                data_sent = masked_triple_elements_sent.reshape(-1)
            else:
                # print('l_bound:', l_bound)
                # print('data_sent.shape:', data_sent.shape)
                # print('masked_triple_elements_sent.shape:', masked_triple_elements_sent.shape)
                data_sent = np.append(masked_tuple_elements_sent.reshape(-1),
                                      masked_triple_elements_sent.reshape(-1),
                                      axis=0)

        # exchange the message
        send_msg_thread = sender[1 - role].send_ndarray_by_bytes_thread(
            data_sent, packbits=True)
        send_msg_thread.start()
        data_received = listener[1 - role].receive_ndarray_by_bytes(
            size=data_sent.shape, packbits=True)

        # recover the masked data

        data_recovered = data_sent ^ data_received

        p_stream = 0
        if n_paired > 0:
            p_stream_nxt = p_stream + np.prod(masked_tuple_elements_sent.shape)
            masked_tuple_elements = data_recovered[
                p_stream:p_stream_nxt].reshape(
                    masked_tuple_elements_sent.shape)
            p_stream = p_stream_nxt
            l_all_1_masked = masked_tuple_elements[0]
            m_all_1_masked = masked_tuple_elements[1]
            r_all_1_masked = masked_tuple_elements[2]
            r_carry_bit_masked = masked_tuple_elements[3]
            m_carry_bit_masked = masked_tuple_elements[4]

        if flag == 2:
            p_stream_nxt = p_stream + np.prod(
                masked_triple_elements_sent.shape)
            masked_triple_elements = data_recovered[
                p_stream:p_stream_nxt].reshape(
                    masked_triple_elements_sent.shape)
            p_stream = p_stream_nxt
            left_most_l_all_1_masked_1 = masked_triple_elements[0]
            left_most_r_all_1_masked = masked_triple_elements[1]
            left_most_l_all_1_masked_2 = masked_triple_elements[2]
            left_most_r_carry_bit_masked = masked_triple_elements[3]

        if n_paired > 0:
            # all_1 = l_all_1 & m_all_1 & r_all_1
            all_1 = calculate_3_input_gate(
                l_all_1_masked, m_all_1_masked, r_all_1_masked,
                help_tuple[[0, 1, 2, 3, 4, 5, 6],
                           p_help_tuple:p_help_tuple_nxt], const_compute)

            # carry_bit = (l_all_1 & m_all_1 & r_carry_bit) ^ (l_all_1 & m_carry_bit) ^ l_carry_bit
            carry_bit = calculate_3_input_gate(
                l_all_1_masked, m_all_1_masked, r_carry_bit_masked,
                help_tuple[[0, 1, 7, 3, 8, 9, 10],
                           p_help_tuple:p_help_tuple_nxt],
                const_compute) ^ calculate_2_input_gate(
                    l_all_1_masked, m_carry_bit_masked,
                    help_tuple[[0, 11, 12], p_help_tuple:p_help_tuple_nxt],
                    const_compute) ^ l_carry_bit

            p_help_tuple = p_help_tuple_nxt

        if flag == 2:
            # left_most_all_1 = left_most_l_all_1 & left_most_r_all_1
            left_most_all_1 = calculate_2_input_gate(
                left_most_l_all_1_masked_1, left_most_r_all_1_masked,
                triple[:, p_triple:p_triple + 1], const_compute)

            # left_most_carry_bit = left_most_l_all_1 & left_most_r_carry_bit ^ left_most_l_carry_bt
            left_most_carry_bit = calculate_2_input_gate(
                left_most_l_all_1_masked_2, left_most_r_carry_bit_masked,
                triple[:, p_triple + 1:p_triple + 2],
                const_compute) ^ left_most_l_carry_bit

            p_triple = p_triple + 2

        if left_most_all_1 is not None:
            # all_1 = np.append(all_1, left_most_all_1, axis=0)
            if n_paired == 0:
                carry_bit = left_most_carry_bit
                all_1 = left_most_all_1
            else:
                carry_bit = np.append(carry_bit, left_most_carry_bit, axis=0)
                all_1 = np.append(all_1, left_most_all_1, axis=0)

        l_bound = len(all_1) - 1
        send_msg_thread.join()

    return ret ^ carry_bit[0]

def verify_triple(triple: np.ndarray, sender, listener):
    send_msg_thread = sender.send_ndarray_by_bytes_thread(triple,
                                                          packbits=True)
    send_msg_thread.start()
    rcv_thread = listener.receive_ndarray_by_bytes_thread(size=triple.shape,
                                                          packbits=True)
    rcv_thread.start()

    send_msg_thread.join()
    rcv_thread.join()

    triple_recieved = rcv_thread.get_result()

    tmp = triple ^ triple_recieved
    assert (np.sum((tmp[0] & tmp[1]) != tmp[2]) == 0)

def count_tuple_and_triple(msb_pos: int):
    '''
    return (n_tuple, n_triple)
    '''
    n_tuple, n_triple = 0, msb_pos

    l_bound = msb_pos - 1

    while l_bound > 0:
        flag = (l_bound + 1) % 3

        if flag == 2:
            n_triple += 2

        n_pair = (l_bound + 1) // 3
        n_tuple += n_pair
        l_bound = n_pair - 1

        if flag != 0:
            l_bound += 1

    return n_tuple, n_triple

def get_triple_delta(triple_mo: np.ndarray, triple_do: np.ndarray):
    '''
    get the delta sent to model owner
    '''
    return (triple_mo[0] ^ triple_do[0]) & (triple_mo[1]
                                            ^ triple_do[1]) ^ triple_do[2]

def get_tuple_delta(tuple_mo: np.ndarray, tuple_do: np.ndarray):
    '''
    get the delta sent to model owner
    tuple:
    u,  v,  w,  uv, uw, vw, uvw
    0,  1,  2,   3,  4,  5, 6

    u,  v,  w1, uv, uw1,    vw1,    uvw1
    0,  1,  7,  3,  8,      9,      10

    u,  v2, uv2
    0,  11, 12
    '''
    u = tuple_mo[0] ^ tuple_do[0]
    v = tuple_mo[1] ^ tuple_do[1]
    w = tuple_mo[2] ^ tuple_do[2]
    w1 = tuple_mo[7] ^ tuple_do[7]
    v2 = tuple_mo[11] ^ tuple_do[11]

    ret = np.array([
        u & v ^ tuple_do[3], u & w ^ tuple_do[4], v & w ^ tuple_do[5],
        u & v & w ^ tuple_do[6], u & w1 ^ tuple_do[8], v & w1 ^ tuple_do[9],
        u & v & w1 ^ tuple_do[10], u & v2 ^ tuple_do[12]
    ],
        dtype='bool')
    return ret

def SecureBiNN(role, random_handler, listener, sender, data_share,
               model_share):
    # role 0: data owner (share_0, share_1)
    # role 1: model owner (share_1, share_2)
    # role 2: trusted third party (share_2, share_0)
    data_owner = 0
    model_owner = 1
    ttp = 2

    role_last = (role - 1) % 3
    role_next = (role + 1) % 3

    ret = data_share

    for i in range(len(model_share)):

        random_handler.step_synchronous()

        cur_layer = model_share[i]
        name = cur_layer['name']
        # print(name)
        # print('Len ret:', len(ret))

        if name.startswith('dense'):
            ret = tf.matmul(ret[0], cur_layer['W'][0]) + \
                tf.matmul(ret[0], cur_layer['W'][1]) + \
                tf.matmul(ret[1], cur_layer['W'][0]) + \
                cur_layer['b']
            ret += random_handler.get_3_out_of_3_shares(bits=int(
                cur_layer['dtype'][3:]),
                size=ret.shape)
            random_handler.cnter += 1

        elif name.startswith('conv2d'):
            ret = tf.nn.conv2d(
                ret[0], cur_layer['W'][0], strides=cur_layer['strides'], padding=cur_layer['padding']) + \
                tf.nn.conv2d(
                    ret[0], cur_layer['W'][1], strides=cur_layer['strides'], padding=cur_layer['padding']) + \
                tf.nn.conv2d(
                    ret[1], cur_layer['W'][0], strides=cur_layer['strides'], padding=cur_layer['padding'])
            ret = tf.nn.bias_add(ret, cur_layer['b'])
            ret += random_handler.get_3_out_of_3_shares(bits=int(
                cur_layer['dtype'][3:]),
                size=ret.shape)
            random_handler.cnter += 1

        elif name.startswith('batch_normalization'):
            ret += cur_layer['val']

        elif name.startswith('activation') or name.startswith('max_pooling'):
            if name.startswith('max_pooling'):
                ret = ret[0]
                ret = sum_pool(ret, kernel_size=cur_layer['pool_size'])
                if role == data_owner:
                    ret = ret - 1

            input_dtype = cur_layer['dtype']
            output_dtype = cur_layer['nxt_dtype']

            total_bit = 32
            input_bit = int(input_dtype[3:])
            pos = cur_layer['msb']

            output_bit = int(output_dtype[3:])
            ori_shape = ret.shape
            ret = ret.numpy()

            # n_triple = 3 * (pos - 1) + 1
            # n_triple = count_ppa_n_triple(msb_pos=pos)
            n_tuple, n_triple = count_tuple_and_triple(msb_pos=pos)

            # Prepare beaver's triple
            '''
            tuple:
            u,  v,  w,  uv, uw, vw, uvw
            0,  1,  2,   3,  4,  5, 6

            u,  v,  w1, uv, uw1,    vw1,    uvw1
            0,  1,  7,  3,  8,      9,      10

            u,  v2, uv2
            0,  11, 12

            generate tuple, then generate triple
            '''

            if role == ttp:
                if name.startswith('activation'):
                    send_datashare_thread = sender[
                        data_owner].send_ndarray_by_bytes_thread(ret)
                    send_datashare_thread.start()

                tuple_do = random_handler.get_same_random_with(
                    data_owner, bits=1, size=(13, n_tuple, *ret.shape))
                tuple_mo = random_handler.get_same_random_with(
                    model_owner, bits=1, size=(13, n_tuple, *ret.shape))
                random_handler.cnter += 1

                triple_do = random_handler.get_same_random_with(
                    data_owner, bits=1, size=(3, n_triple, *ret.shape))
                triple_mo = random_handler.get_same_random_with(
                    model_owner, bits=1, size=(3, n_triple, *ret.shape))
                random_handler.cnter += 1

                # delta = modify_triple_with_optimization(
                #     pos, triple_do, triple_mo)
                # delta = (triple_do[0] ^ triple_mo[0]) & (
                #     triple_do[1] ^ triple_mo[1]) ^ triple_do[2]

                delta_tuple = get_tuple_delta(tuple_mo, tuple_do)
                delta_triple = get_triple_delta(triple_mo, triple_do)
                delta = np.append(delta_tuple.reshape(-1),
                                  delta_triple.reshape(-1))

                send_delta_thread = sender[
                    model_owner].send_ndarray_by_bytes_thread(delta,
                                                              packbits=True)
                send_delta_thread.start()
                a_share = None
                b_share = None
                triple = None
                tuple = None
                send_delta_thread.join()

                if name.startswith('activation'):
                    send_datashare_thread.join()

            elif role == data_owner:
                if name.startswith('activation'):
                    ttp_share = listener[ttp].receive_ndarray_by_bytes(
                        size=ret.shape, dtype=ret.dtype)
                    ret += ttp_share

                # triple = random_handler.get_same_random_with(
                #     ttp, bits=1, size=(3, n_triple, *ret.shape))
                # triple = modify_triple_with_optimization(
                #     pos, triple_do=triple)
                # random_handler.cnter += 1

                tuple = random_handler.get_same_random_with(ttp,
                                                            bits=1,
                                                            size=(13, n_tuple,
                                                                  *ret.shape))
                random_handler.cnter += 1

                triple = random_handler.get_same_random_with(ttp,
                                                             bits=1,
                                                             size=(3, n_triple,
                                                                   *ret.shape))
                random_handler.cnter += 1

                a_share = ret
                b_share = np.zeros_like(ret)

            elif role == model_owner:

                # delta = listener[ttp].receive_ndarray_by_bytes(
                #     size=(n_triple, *ret.shape), packbits=True)
                # triple = random_handler.get_same_random_with(
                #     ttp, bits=1, size=(3, n_triple, *ret.shape))
                # triple = modify_triple_with_optimization(
                #     pos, triple_mo=triple)
                # random_handler.cnter += 1
                # triple[2] = delta

                tuple = random_handler.get_same_random_with(ttp,
                                                            bits=1,
                                                            size=(13, n_tuple,
                                                                  *ret.shape))
                random_handler.cnter += 1

                triple = random_handler.get_same_random_with(ttp,
                                                             bits=1,
                                                             size=(3, n_triple,
                                                                   *ret.shape))
                random_handler.cnter += 1

                delta = listener[ttp].receive_ndarray_by_bytes(
                    size=((8 * n_tuple + n_triple) * np.prod(ret.shape)),
                    packbits=True)

                len_delta_triple = np.prod(triple[2].shape)
                len_delta_tuple = len(delta) - len_delta_triple

                delta_tuple = np.reshape(delta[:len_delta_tuple],
                                         (-1, n_tuple, *ret.shape))
                delta_triple = np.reshape(delta[len_delta_tuple:],
                                          triple[2].shape)

                tuple[3] = delta_tuple[0]
                tuple[4] = delta_tuple[1]
                tuple[5] = delta_tuple[2]
                tuple[6] = delta_tuple[3]
                tuple[8] = delta_tuple[4]
                tuple[9] = delta_tuple[5]
                tuple[10] = delta_tuple[6]
                tuple[12] = delta_tuple[7]

                triple[2] = delta_triple

                a_share = np.zeros_like(ret)
                b_share = ret

            # if role != ttp:
            #     verify_triple(triple, sender[1-role], listener[1-role])
            # Extract MSB
            # ret = extract_msb_ppa(
            #     role=role,
            #     listener=listener,
            #     sender=sender,
            #     a_share=a_share,
            #     b_share=b_share,
            #     total_bit=total_bit,
            #     msb_pos=pos,
            #     triple=triple
            # )
            # ret = extract_msb_ppa_with_optimize(
            #     role=role,
            #     listener=listener,
            #     sender=sender,
            #     a_share=a_share,
            #     b_share=b_share,
            #     total_bit=total_bit,
            #     msb_pos=pos,
            #     triple=triple
            # )
            ret = extract_msb_with_3_input_gate(role=role,
                                                listener=listener,
                                                sender=sender,
                                                a_share=a_share,
                                                b_share=b_share,
                                                total_bit=total_bit,
                                                msb_pos=pos,
                                                triple=triple,
                                                help_tuple=tuple)

            # Here ret_mo ^ ret_do = MSB

            # 3P - Oblivious Transfer

            if role == data_owner:
                ret = ot_3party(role=role,
                                sender=sender,
                                listener=listener,
                                random_handler=random_handler,
                                msg_dtype='u' + output_dtype,
                                msg_bit=output_bit,
                                choose_bit=ret)

            elif role == model_owner:
                msg_0 = ret
                msg_1 = True ^ ret
                msg_0 = ((True ^ msg_0) +
                         msg_0 * cur_layer['deact_val']).astype(output_dtype)
                msg_1 = ((True ^ msg_1) +
                         msg_1 * cur_layer['deact_val']).astype(output_dtype)
                msg_0 = int2uint(msg_0)
                msg_1 = int2uint(msg_1)

                # add r to two messages
                r = get_random_mask(msg_0.shape, bits=output_bit)
                msg_0 -= r
                msg_1 -= r

                # send the message
                ot_3party(role=role,
                          sender=sender,
                          listener=listener,
                          random_handler=random_handler,
                          msg_0=msg_0,
                          msg_1=msg_1,
                          msg_bit=output_bit)
                ret = r

            elif role == ttp:
                ot_3party(role=role,
                          sender=sender,
                          listener=listener,
                          random_handler=random_handler,
                          msg_dtype='u' + output_dtype,
                          msg_shape=ori_shape)
                ret = np.zeros(shape=ori_shape, dtype='u' + output_dtype)

            # Reshare
            if cur_layer['deact_val'] == -1:
                random_handler.step_synchronous()
                mask = random_handler.get_3_out_of_3_shares(output_bit,
                                                            size=ret.shape)
                ret += mask
                send_thread = sender[role_last].send_ndarray_by_bytes_thread(
                    ret)
                send_thread.start()
                share_rcv = listener[role_next].receive_ndarray_by_bytes(
                    size=ret.shape, dtype=ret.dtype)
                ret = tf.constant([ret, share_rcv], dtype=tf.int32)
                send_thread.join()
            else:
                ret = tf.constant([
                    ret,
                ], dtype=tf.int32)

        elif name.startswith('bnn__dense'):
            ret = tf.matmul(ret[0], cur_layer['W'][0]) + \
                tf.matmul(ret[0], cur_layer['W'][1]) + \
                tf.matmul(ret[1], cur_layer['W'][0])
            ret += random_handler.get_3_out_of_3_shares(bits=int(
                cur_layer['dtype'][3:]),
                size=ret.shape)
            random_handler.cnter += 1

        elif name.startswith('bnn__conv2d'):
            ret = tf.nn.conv2d(
                ret[0], cur_layer['W'][0], strides=cur_layer['strides'], padding=cur_layer['padding']) + \
                tf.nn.conv2d(
                    ret[0], cur_layer['W'][1], strides=cur_layer['strides'], padding=cur_layer['padding']) + \
                tf.nn.conv2d(
                    ret[1], cur_layer['W'][0], strides=cur_layer['strides'], padding=cur_layer['padding'])
            ret += random_handler.get_3_out_of_3_shares(bits=int(
                cur_layer['dtype'][3:]),
                size=ret.shape)
            random_handler.cnter += 1

        elif name.startswith('flatten'):
            share_0 = tf.reshape(ret[0], (ret[0].shape[0], -1))
            share_1 = tf.reshape(ret[1], (ret[1].shape[0], -1))
            ret = [share_0, share_1]

    return ret

def test_secure_activation(n_bit: int, n_batch: int, role: int, listener: list, sender: list, config):
    data_owner = 0
    model_owner = 1
    ttp = 2

    role_last = (role - 1) % 3
    role_next = (role + 1) % 3

    ret = np.zeros(n_batch, dtype='int32')
    cur_layer = {
        'dtype': 'int32',
        'output_dtype': 'int32',
        'msb': n_bit-1,
        'nxt_dtype': 'int32',
        'deact_val': -1
    }

    input_dtype = cur_layer['dtype']
    output_dtype = cur_layer['nxt_dtype']

    total_bit = 32
    input_bit = int(input_dtype[3:])
    pos = cur_layer['msb']

    output_bit = int(output_dtype[3:])
    ori_shape = ret.shape

    # n_triple = 3 * (pos - 1) + 1
    # n_triple = count_ppa_n_triple(msb_pos=pos)
    n_tuple, n_triple = count_tuple_and_triple(msb_pos=pos)

    random_handler = RandomHandler(role, config['r'][role],
                                   config['r'][role_next])
    # Prepare beaver's triple
    '''
    tuple:
    u,  v,  w,  uv, uw, vw, uvw
    0,  1,  2,   3,  4,  5, 6

    u,  v,  w1, uv, uw1,    vw1,    uvw1
    0,  1,  7,  3,  8,      9,      10

    u,  v2, uv2
    0,  11, 12

    generate tuple, then generate triple
    '''

    if role == ttp:
        send_datashare_thread = sender[
            data_owner].send_ndarray_by_bytes_thread(ret)
        send_datashare_thread.start()

        tuple_do = random_handler.get_same_random_with(
            data_owner, bits=1, size=(13, n_tuple, *ret.shape))
        tuple_mo = random_handler.get_same_random_with(
            model_owner, bits=1, size=(13, n_tuple, *ret.shape))
        random_handler.cnter += 1

        triple_do = random_handler.get_same_random_with(
            data_owner, bits=1, size=(3, n_triple, *ret.shape))
        triple_mo = random_handler.get_same_random_with(
            model_owner, bits=1, size=(3, n_triple, *ret.shape))
        random_handler.cnter += 1

        # delta = modify_triple_with_optimization(
        #     pos, triple_do, triple_mo)
        # delta = (triple_do[0] ^ triple_mo[0]) & (
        #     triple_do[1] ^ triple_mo[1]) ^ triple_do[2]

        delta_tuple = get_tuple_delta(tuple_mo, tuple_do)
        delta_triple = get_triple_delta(triple_mo, triple_do)
        delta = np.append(delta_tuple.reshape(-1),
                          delta_triple.reshape(-1))

        send_delta_thread = sender[
            model_owner].send_ndarray_by_bytes_thread(delta,
                                                      packbits=True)
        send_delta_thread.start()
        a_share = None
        b_share = None
        triple = None
        tuple = None
        send_delta_thread.join()

        send_datashare_thread.join()

    elif role == data_owner:
        ttp_share = listener[ttp].receive_ndarray_by_bytes(
            size=ret.shape, dtype=ret.dtype)
        ret += ttp_share

        tuple = random_handler.get_same_random_with(ttp,
                                                    bits=1,
                                                    size=(13, n_tuple,
                                                          *ret.shape))
        random_handler.cnter += 1

        triple = random_handler.get_same_random_with(ttp,
                                                     bits=1,
                                                     size=(3, n_triple,
                                                           *ret.shape))
        random_handler.cnter += 1

        a_share = ret
        b_share = np.zeros_like(ret)

    elif role == model_owner:

        tuple = random_handler.get_same_random_with(ttp,
                                                    bits=1,
                                                    size=(13, n_tuple,
                                                          *ret.shape))
        random_handler.cnter += 1

        triple = random_handler.get_same_random_with(ttp,
                                                     bits=1,
                                                     size=(3, n_triple,
                                                           *ret.shape))
        random_handler.cnter += 1

        delta = listener[ttp].receive_ndarray_by_bytes(
            size=((8 * n_tuple + n_triple) * np.prod(ret.shape)),
            packbits=True)

        len_delta_triple = np.prod(triple[2].shape)
        len_delta_tuple = len(delta) - len_delta_triple

        delta_tuple = None
        delta_triple = None

        if len_delta_tuple > 0:
            delta_tuple = np.reshape(delta[:len_delta_tuple],
                                     (-1, n_tuple, *ret.shape))
            tuple[3] = delta_tuple[0]
            tuple[4] = delta_tuple[1]
            tuple[5] = delta_tuple[2]
            tuple[6] = delta_tuple[3]
            tuple[8] = delta_tuple[4]
            tuple[9] = delta_tuple[5]
            tuple[10] = delta_tuple[6]
            tuple[12] = delta_tuple[7]

        if len_delta_triple > 0:
            delta_triple = np.reshape(delta[len_delta_tuple:],
                                      triple[2].shape)
            triple[2] = delta_triple

        a_share = np.zeros_like(ret)
        b_share = ret

    ret = extract_msb_with_3_input_gate(role=role,
                                        listener=listener,
                                        sender=sender,
                                        a_share=a_share,
                                        b_share=b_share,
                                        total_bit=total_bit,
                                        msb_pos=pos,
                                        triple=triple,
                                        help_tuple=tuple)

    # Here ret_mo ^ ret_do = MSB

    # 3P - Oblivious Transfer

    if role == data_owner:
        ret = ot_3party(role=role,
                        sender=sender,
                        listener=listener,
                        random_handler=random_handler,
                        msg_dtype='u' + output_dtype,
                        msg_bit=output_bit,
                        choose_bit=ret)

    elif role == model_owner:
        msg_0 = ret
        msg_1 = True ^ ret
        msg_0 = ((True ^ msg_0) +
                 msg_0 * cur_layer['deact_val']).astype(output_dtype)
        msg_1 = ((True ^ msg_1) +
                 msg_1 * cur_layer['deact_val']).astype(output_dtype)
        msg_0 = int2uint(msg_0)
        msg_1 = int2uint(msg_1)

        # add r to two messages
        r = get_random_mask(msg_0.shape, bits=output_bit)
        msg_0 -= r
        msg_1 -= r

        # send the message
        ot_3party(role=role,
                  sender=sender,
                  listener=listener,
                  random_handler=random_handler,
                  msg_0=msg_0,
                  msg_1=msg_1,
                  msg_bit=output_bit)
        ret = r

    elif role == ttp:
        ot_3party(role=role,
                  sender=sender,
                  listener=listener,
                  random_handler=random_handler,
                  msg_dtype='u' + output_dtype,
                  msg_shape=ori_shape)
        ret = np.zeros(shape=ori_shape, dtype='u' + output_dtype)

    # Reshare
    random_handler.step_synchronous()
    mask = random_handler.get_3_out_of_3_shares(output_bit,
                                                size=ret.shape)
    ret += mask
    send_thread = sender[role_last].send_ndarray_by_bytes_thread(
        ret)
    send_thread.start()
    share_rcv = listener[role_next].receive_ndarray_by_bytes(
        size=ret.shape, dtype=ret.dtype)
    ret = tf.constant([ret, share_rcv], dtype=tf.int32)
    send_thread.join()

    return None