commit 805637d104bc9a18e6d4d376521687b289b5d856 Author: n1gp Date: Sat Apr 4 16:53:58 2015 -0400 first commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..e712f2e --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +This is a copy of VK5ABN, Berndt's cuSDR source +derived from his post: http://www.ping.net.au/20140126_cuSDR64src.tar.gz + +I added local sound and up'd the number of recievers to 8 +for librtlhpsdr. + +I have only compiled and used this on linux. diff --git a/Source/bin/settings.ini b/Source/bin/settings.ini new file mode 100644 index 0000000..f849c40 --- /dev/null +++ b/Source/bin/settings.ini @@ -0,0 +1,1080 @@ +[General] +cudaSDR%20BETA%20=v0.3.2.13 +saved=Friday 03 April 2015 20:53:23 + +[ChirpWSPR] +chirpAmplitude=75 +chirpBufferDurationUs=10000000 +chirpBufferLength=4096 +chirpChannels=1 +chirpFilterLowerFrequency=500 +chirpFilterUpperFrequency=2500 +chirpSamplingFrequency=48000 +lowerChirpFrequency=500 +upperChirpFrequency=2500 + +[alex] +amp6m=off +amp6mHi=54000000 +amp6mLo=50000000 +bypassAll=off +hpf13MHz=off +hpf13MHzHi=18168000 +hpf13MHzLo=14000000 +hpf1_5MHz=off +hpf1_5MHzHi=5500000 +hpf1_5MHzLo=1500000 +hpf20MHz=off +hpf20MHzHi=29700000 +hpf20MHzLo=21000000 +hpf6_5MHz=off +hpf6_5MHzHi=7300000 +hpf6_5MHzLo=7000000 +hpf9_5MHz=off +hpf9_5MHzHi=10150000 +hpf9_5MHzLo=10100000 +lpf12_10m=off +lpf12_10mHi=29700000 +lpf12_10mLo=24890000 +lpf160m=off +lpf160mHi=2000000 +lpf160mLo=1800000 +lpf17_15m=off +lpf17_15mHi=21450000 +lpf17_15mLo=18068000 +lpf30_20m=off +lpf30_20mHi=14350000 +lpf30_20mLo=10100000 +lpf60_40m=off +lpf60_40mHi=7300000 +lpf60_40mLo=5330000 +lpf6m=off +lpf6mHi=54000000 +lpf6mLo=50000000 +lpf80m=off +lpf80mHi=4000000 +lpf80mLo=3500000 +manual=off +state10m=33 +state12m=33 +state15m=33 +state160m=33 +state17m=33 +state20m=33 +state2200m=33 +state30m=33 +state40m=33 +state60m=33 +state630m=33 +state6m=33 +state80m=33 +stateGen=33 + +[colors] +distanceLine=#f61b2d +distanceLineFilled=#e81d56 +gridLine=#076060 +panBackground=#664508 +panCenterLine=#f60713 +panLine=#f6a44c +panLineFilled=#f69f07 +panSolidBottom=#666008 +panSolidTop=#e6f6cc +panWideBandFilled=#89ac3e +panWideBandLine=#496f07 +panWideBandSolidBottom=#e8861d +panWideBandSolidTop=#ec2610 +waterfall=#f69206 + +[graphics] +dBmDistScaleMax=100 +dBmDistScaleMin=-20 +sMeterHoldTime=10000 + +[hpsdr] +alex=false +checkfw=false +excalibur=false +hardware=1 +interface=hermes +mercury=true +penelope=false +pennylane=false + +[network] +audio_port=15000 +hpsdr_local_ipAddress=192.168.1.1 +listen_port=11000 +metis_port=56389 +server_ipAddress=192.168.1.1 +server_port=52685 +socketBufferSize=32 + +[penny] +OCenabled=off +rxState10m=0 +rxState12m=0 +rxState15m=0 +rxState160m=0 +rxState17m=0 +rxState20m=0 +rxState2200m=0 +rxState30m=0 +rxState40m=0 +rxState60m=0 +rxState630m=0 +rxState6m=0 +rxState80m=0 +txState10m=0 +txState12m=0 +txState15m=0 +txState160m=0 +txState17m=0 +txState20m=0 +txState2200m=0 +txState30m=0 +txState40m=0 +txState60m=0 +txState630m=0 +txState6m=0 +txState80m=0 + +[receiver0] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=87 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=31 +averaging=on +averagingCnt=9 +centerFrequency=3909142 +clickVFO=on +dBmPanScaleMax10m=-18 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=-17 +dBmPanScaleMax160m=-4 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-22 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-10 +dBmPanScaleMax40m=-39 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-34 +dBmPanScaleMaxGen=-33 +dBmPanScaleMin10m=-128 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-114 +dBmPanScaleMin160m=-74 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-84 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-104 +dBmPanScaleMin40m=-95 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-90 +dBmPanScaleMinGen=-89 +dspCore=qtdsp +dspMode10m=USB +dspMode12m=LSB +dspMode15m=USB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=USB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28908896 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21213461 +lastCenterFrequency160m=1901555 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14141881 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10112146 +lastCenterFrequency40m=7199791 +lastCenterFrequency60m=5399971 +lastCenterFrequency630m=477624 +lastCenterFrequency6m=50995823 +lastCenterFrequency80m=3799975 +lastCenterFrequencyGen=3909142 +lastVfoFrequency10m=28825000 +lastVfoFrequency12m=24923770 +lastVfoFrequency15m=21005700 +lastVfoFrequency160m=1828000 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14056500 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10119000 +lastVfoFrequency40m=7184000 +lastVfoFrequency60m=5399417 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=50990500 +lastVfoFrequency80m=3799983 +lastVfoFrequencyGen=3940500 +mouseWheelFreqStep=500 +panLocked=off +panMode=FILLEDLINE +vfoFrequency=3940500 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver1] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=off +agcMaximumGain=98 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=25 +averaging=on +averagingCnt=5 +centerFrequency=10014453 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=0 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-9 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-31 +dBmPanScaleMax40m=-7 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-10 +dBmPanScaleMaxGen=-19 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-89 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-100 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-122 +dBmPanScaleMin40m=-98 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-120 +dBmPanScaleMinGen=-110 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=USB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=USB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28000158 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21000158 +lastCenterFrequency160m=1810196 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14232965 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10149614 +lastCenterFrequency40m=7149614 +lastCenterFrequency60m=5406760 +lastCenterFrequency630m=472000 +lastCenterFrequency6m=50000000 +lastCenterFrequency80m=3799728 +lastCenterFrequencyGen=10014453 +lastVfoFrequency10m=28999770 +lastVfoFrequency12m=24890000 +lastVfoFrequency15m=21001023 +lastVfoFrequency160m=1810000 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14000000 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10139000 +lastVfoFrequency40m=7139000 +lastVfoFrequency60m=5407160 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=50000000 +lastVfoFrequency80m=3799728 +lastVfoFrequencyGen=9980000 +mouseWheelFreqStep=1000 +panLocked=off +panMode=FILLEDLINE +vfoFrequency=9980000 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver2] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=67 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=27 +averaging=on +averagingCnt=5 +centerFrequency=1591296 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=0 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-22 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-10 +dBmPanScaleMax40m=-11 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-10 +dBmPanScaleMaxGen=-11 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-109 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-100 +dBmPanScaleMin20m=-131 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-120 +dBmPanScaleMin40m=-89 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-120 +dBmPanScaleMinGen=-89 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=LSB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28000000 +lastCenterFrequency12m=24891024 +lastCenterFrequency15m=21000000 +lastCenterFrequency160m=1965264 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14258266 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10108302 +lastCenterFrequency40m=7000000 +lastCenterFrequency60m=5260000 +lastCenterFrequency630m=475328 +lastCenterFrequency6m=50000000 +lastCenterFrequency80m=3799678 +lastCenterFrequencyGen=1591296 +lastVfoFrequency10m=28000000 +lastVfoFrequency12m=24891024 +lastVfoFrequency15m=21000000 +lastVfoFrequency160m=1979460 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14282804 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10102279 +lastVfoFrequency40m=7000000 +lastVfoFrequency60m=5260000 +lastVfoFrequency630m=472224 +lastVfoFrequency6m=50000000 +lastVfoFrequency80m=3799678 +lastVfoFrequencyGen=1611668 +mouseWheelFreqStep=100 +panLocked=off +panMode=FILLEDLINE +vfoFrequency=1611668 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver3] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=86 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=50 +averaging=on +averagingCnt=5 +centerFrequency=15000160 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=-10 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-57 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-37 +dBmPanScaleMax40m=-5 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-10 +dBmPanScaleMaxGen=-10 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-120 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-136 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-147 +dBmPanScaleMin40m=-88 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-120 +dBmPanScaleMinGen=-101 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=LSB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28000000 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21000000 +lastCenterFrequency160m=1810000 +lastCenterFrequency17m=18068208 +lastCenterFrequency20m=14000160 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10100000 +lastCenterFrequency40m=7000000 +lastCenterFrequency60m=5260000 +lastCenterFrequency630m=472000 +lastCenterFrequency6m=50000000 +lastCenterFrequency80m=3672000 +lastCenterFrequencyGen=15000160 +lastVfoFrequency10m=28000000 +lastVfoFrequency12m=24890000 +lastVfoFrequency15m=21000000 +lastVfoFrequency160m=1810000 +lastVfoFrequency17m=18103800 +lastVfoFrequency20m=14017828 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10101540 +lastVfoFrequency40m=7000000 +lastVfoFrequency60m=5260000 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=50000000 +lastVfoFrequency80m=3672000 +lastVfoFrequencyGen=15017828 +mouseWheelFreqStep=100 +panLocked=off +panMode=FILLEDLINE +vfoFrequency=15017828 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver4] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=88 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=43 +averaging=on +averagingCnt=5 +centerFrequency=15014483 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=-19 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-29 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-25 +dBmPanScaleMax40m=-2 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-10 +dBmPanScaleMaxGen=-29 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-109 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-118 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-115 +dBmPanScaleMin40m=-91 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-120 +dBmPanScaleMinGen=-118 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=LSB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28000000 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21000000 +lastCenterFrequency160m=1810000 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14000000 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10100000 +lastCenterFrequency40m=7156815 +lastCenterFrequency60m=5260000 +lastCenterFrequency630m=472000 +lastCenterFrequency6m=50000000 +lastCenterFrequency80m=3672000 +lastCenterFrequencyGen=15014483 +lastVfoFrequency10m=28000000 +lastVfoFrequency12m=24890000 +lastVfoFrequency15m=21000000 +lastVfoFrequency160m=1810000 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14000000 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10100000 +lastVfoFrequency40m=7178741 +lastVfoFrequency60m=5260000 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=50000000 +lastVfoFrequency80m=3672000 +lastVfoFrequencyGen=15047293 +mouseWheelFreqStep=1 +panLocked=off +panMode=LINE +vfoFrequency=15047293 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver5] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=82 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=25 +averaging=on +averagingCnt=5 +centerFrequency=1599540 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=-10 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-28 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-10 +dBmPanScaleMax40m=-3 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-10 +dBmPanScaleMaxGen=-8 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-120 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-110 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-120 +dBmPanScaleMin40m=-85 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-120 +dBmPanScaleMinGen=-90 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=LSB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28000000 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21000000 +lastCenterFrequency160m=1894564 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14000000 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10120916 +lastCenterFrequency40m=7000000 +lastCenterFrequency60m=5260000 +lastCenterFrequency630m=472000 +lastCenterFrequency6m=53994564 +lastCenterFrequency80m=3672000 +lastCenterFrequencyGen=1599540 +lastVfoFrequency10m=28000000 +lastVfoFrequency12m=24890000 +lastVfoFrequency15m=21000000 +lastVfoFrequency160m=1898300 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14000756 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10121756 +lastVfoFrequency40m=7000756 +lastVfoFrequency60m=5260000 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=53998300 +lastVfoFrequency80m=3672000 +lastVfoFrequencyGen=1594683 +mouseWheelFreqStep=100 +panLocked=off +panMode=LINE +vfoFrequency=1594683 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver6] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=117 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=10 +averaging=on +averagingCnt=5 +centerFrequency=14992688 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=-10 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-23 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-10 +dBmPanScaleMax40m=-8 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=-10 +dBmPanScaleMaxGen=-12 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-120 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-112 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-120 +dBmPanScaleMin40m=-97 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-120 +dBmPanScaleMinGen=-101 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=LSB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28074490 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21000000 +lastCenterFrequency160m=1810000 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14000000 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10100000 +lastCenterFrequency40m=7000000 +lastCenterFrequency60m=5260000 +lastCenterFrequency630m=472000 +lastCenterFrequency6m=50000000 +lastCenterFrequency80m=3567030 +lastCenterFrequencyGen=14992688 +lastVfoFrequency10m=28074490 +lastVfoFrequency12m=24890000 +lastVfoFrequency15m=21000000 +lastVfoFrequency160m=1810000 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14012300 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10100000 +lastVfoFrequency40m=7000000 +lastVfoFrequency60m=5260000 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=50000000 +lastVfoFrequency80m=3580100 +lastVfoFrequencyGen=15004988 +mouseWheelFreqStep=100 +panLocked=off +panMode=LINE +vfoFrequency=15004988 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[receiver7] +agcAttacktime=1 +agcDecaytime=250 +agcFixedGain=30 +agcGain=100 +agcHangTime=100 +agcLines=on +agcMaximumGain=66 +agcMode=MED +agcSlope=0 +attenuator10m=off +attenuator12m=off +attenuator15m=off +attenuator160m=off +attenuator17m=off +attenuator20m=off +attenuator2200m=off +attenuator30m=off +attenuator40m=off +attenuator60m=off +attenuator630m=off +attenuator6m=off +attenuator80m=off +attenuatorGen=off +audioVolume=33 +averaging=on +averagingCnt=5 +centerFrequency=10000000 +clickVFO=on +dBmPanScaleMax10m=-10 +dBmPanScaleMax12m=-10 +dBmPanScaleMax15m=-10 +dBmPanScaleMax160m=-10 +dBmPanScaleMax17m=-10 +dBmPanScaleMax20m=-33 +dBmPanScaleMax2200m=-10 +dBmPanScaleMax30m=-10 +dBmPanScaleMax40m=0 +dBmPanScaleMax60m=-10 +dBmPanScaleMax630m=-10 +dBmPanScaleMax6m=-10 +dBmPanScaleMax80m=0 +dBmPanScaleMaxGen=-10 +dBmPanScaleMin10m=-120 +dBmPanScaleMin12m=-120 +dBmPanScaleMin15m=-120 +dBmPanScaleMin160m=-120 +dBmPanScaleMin17m=-120 +dBmPanScaleMin20m=-103 +dBmPanScaleMin2200m=-120 +dBmPanScaleMin30m=-120 +dBmPanScaleMin40m=-90 +dBmPanScaleMin60m=-120 +dBmPanScaleMin630m=-120 +dBmPanScaleMin6m=-120 +dBmPanScaleMin80m=-110 +dBmPanScaleMinGen=-100 +dspCore=qtdsp +dspMode10m=LSB +dspMode12m=LSB +dspMode15m=LSB +dspMode160m=LSB +dspMode17m=LSB +dspMode20m=LSB +dspMode2200m=LSB +dspMode30m=LSB +dspMode40m=LSB +dspMode60m=LSB +dspMode630m=LSB +dspMode6m=LSB +dspMode80m=LSB +dspModeGen=LSB +filterHi=-150 +filterLo=-3050 +framesPerSecond=25 +freqRulerPosition=5 +grid=on +hairCross=off +lastCenterFrequency10m=28000000 +lastCenterFrequency12m=24890000 +lastCenterFrequency15m=21000000 +lastCenterFrequency160m=1810000 +lastCenterFrequency17m=18068000 +lastCenterFrequency20m=14075076 +lastCenterFrequency2200m=135700 +lastCenterFrequency30m=10100000 +lastCenterFrequency40m=7159744 +lastCenterFrequency60m=5260000 +lastCenterFrequency630m=472000 +lastCenterFrequency6m=50000000 +lastCenterFrequency80m=3799201 +lastCenterFrequencyGen=10000000 +lastVfoFrequency10m=28000000 +lastVfoFrequency12m=24890000 +lastVfoFrequency15m=21000000 +lastVfoFrequency160m=1810000 +lastVfoFrequency17m=18068000 +lastVfoFrequency20m=14084870 +lastVfoFrequency2200m=135700 +lastVfoFrequency30m=10100000 +lastVfoFrequency40m=7137860 +lastVfoFrequency60m=5260000 +lastVfoFrequency630m=472000 +lastVfoFrequency6m=50000000 +lastVfoFrequency80m=3799201 +lastVfoFrequencyGen=9999810 +mouseWheelFreqStep=10 +panLocked=off +panMode=LINE +vfoFrequency=9999810 +waterfallMode=ENHANCED +waterfallOffsetHi=20 +waterfallOffsetLo=-5 + +[server] +10mhzsource=mercury +122_88mhzsource=mercury +class=0 +dither=off +mic_source=penelope +mode=sdr +random=on +sample_rate=96000 +timing=0 + +[user] +callSign=N1GP + +[wideband] +averaging=on +averagingCnt=5 +dBmWideBandScaleMax=-10 +dBmWideBandScaleMin=-140 +panMode=LINE +widebandData=on +widebandDisplay=off + +[window] +minimumGroupBoxWidth=230 +minimumWidgetWidth=235 +multiRxView=0 diff --git a/Source/bin/windowsSettings.ini b/Source/bin/windowsSettings.ini new file mode 100644 index 0000000..d266c25 --- /dev/null +++ b/Source/bin/windowsSettings.ini @@ -0,0 +1,3 @@ +[General] +geometry=@ByteArray(\x1\xd9\xd0\xcb\0\x1\0\0\0\0\x2\x82\0\0\0\x18\0\0\a\x11\0\0\x3\x1a\0\0\x2\x8c\0\0\0\x44\0\0\a\a\0\0\x3\x10\0\0\0\0\0\0) +windowState=@ByteArray(\0\0\0\xff\0\0\0\0\xfd\0\0\0\x1\0\0\0\x1\0\0\0\xf5\0\0\x2\x11\xfc\x2\0\0\0\x5\xfb\0\0\0\x12\0R\0\x61\0\x64\0i\0o\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0\x30\0\xff\xff\xff\xfb\0\0\0\x14\0S\0\x65\0r\0v\0\x65\0r\0\x43\0t\0r\0l\0\0\0\0\xa5\0\0\x2\x11\0\0\x2\x11\0\xff\xff\xff\xfb\0\0\0\x12\0H\0P\0S\0\x44\0R\0\x43\0t\0r\0l\x1\0\0\0\xa5\0\0\x2\x11\0\0\x2\x11\0\xff\xff\xff\xfb\0\0\0\x12\0\x43\0h\0i\0r\0p\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0\x30\0\xff\xff\xff\xfb\0\0\0\x16\0\x44\0i\0s\0p\0l\0\x61\0y\0\x43\0t\0r\0l\0\0\0\0\0\xff\xff\xff\xff\0\0\0\x30\0\xff\xff\xff\0\0\x3\x81\0\0\x2\x11\0\0\0\x4\0\0\0\x4\0\0\0\b\0\0\0\b\xfc\0\0\0\x2\0\0\0\x2\0\0\0\x1\0\0\0\x18\0\x44\0i\0s\0p\0l\0\x61\0y\0P\0\x61\0n\0\x65\0l\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0\0\0\0\x2\0\0\0\x1\0\0\0\x16\0M\0\x61\0i\0n\0\x42\0u\0t\0t\0o\0n\0s\x1\0\0\0\0\xff\xff\xff\xff\0\0\0\0\0\0\0\0) diff --git a/Source/cudaSDR.pri b/Source/cudaSDR.pri new file mode 100644 index 0000000..860c8d4 --- /dev/null +++ b/Source/cudaSDR.pri @@ -0,0 +1,145 @@ +HEADERS += \ + ./src/Util/cusdr_buttons.h \ + ./src/Util/cusdr_colorTriangle.h \ + ./src/Util/cusdr_highResTimer.h \ + ./src/Util/cusdr_image.h \ + ./src/Util/cusdr_imageblur.h \ + ./src/Util/cusdr_led.h \ + ./src/Util/cusdr_painter.h \ + ./src/Util/cusdr_queue.h \ + ./src/Util/cusdr_splash.h \ + ./src/Util/cusdr_styles.h \ + ./src/Util/cusdr_cpuUsage.h \ + ./src/Util/qcircularbuffer.h \ + ./src/AudioEngine/cusdr_audio_engine.h \ + ./src/AudioEngine/cusdr_audio_settingsdialog.h \ + ./src/AudioEngine/cusdr_audio_spectrum.h \ + ./src/AudioEngine/cusdr_audio_spectrumanalyser.h \ + ./src/AudioEngine/cusdr_audio_utils.h \ + ./src/AudioEngine/cusdr_audio_waveform.h \ + ./src/AudioEngine/cusdr_audio_wavfile.h \ + ./src/AudioEngine/cusdr_fspectrum.h \ + ./src/DataEngine/cusdr_audioReceiver.h \ + ./src/DataEngine/cusdr_chirpProcessor.h \ + ./src/DataEngine/cusdr_dataEngine.h \ + ./src/DataEngine/cusdr_dataIO.h \ + ./src/DataEngine/cusdr_discoverer.h \ + ./src/DataEngine/cusdr_receiver.h \ + ./src/DataEngine/soundout.h \ + ./src/DataEngine/fractresampler.h \ + ./src/DataEngine/datatypes.h \ + ./src/QtDSP/fftw3.h \ + ./src/QtDSP/qtdsp_demodulation.h \ + ./src/QtDSP/qtdsp_dspEngine.h \ + ./src/QtDSP/qtdsp_dualModeAverager.h \ + ./src/QtDSP/qtdsp_fft.h \ + ./src/QtDSP/qtdsp_filter.h \ + ./src/QtDSP/qtdsp_powerSpectrum.h \ + ./src/QtDSP/qtdsp_invsinc_coeff.h \ + ./src/QtDSP/qtdsp_qComplex.h \ + ./src/QtDSP/qtdsp_signalMeter.h \ + ./src/QtDSP/qtdsp_wpagc.h \ + ./src/GL/cusdr_oglDisplayPanel.h \ + ./src/GL/cusdr_oglDistancePanel.h \ + ./src/GL/cusdr_oglInfo.h \ + ./src/GL/cusdr_oglReceiverPanel.h \ + ./src/GL/cusdr_oglText.h \ + ./src/GL/cusdr_oglUtils.h \ + ./src/GL/cusdr_oglWidebandPanel.h \ + ./src/cusdr_alexAntennaWidget.h \ + ./src/cusdr_alexFilterWidget.h \ + ./src/cusdr_alexTabWidget.h \ + ./src/cusdr_chirpWidget.h \ + ./src/cusdr_displayWidget.h \ + ./src/cusdr_colorsWidget.h \ + ./src/cusdr_hamDatabase.h \ + ./src/cusdr_hpsdrTabWidget.h \ + ./src/cusdr_hpsdrWidget.h \ + ./src/cusdr_networkWidget.h \ + ./src/cusdr_mainWidget.h \ + ./src/cusdr_extCtrlWidget.h \ + ./src/cusdr_radioTabWidget.h \ + ./src/cusdr_radioWidget.h \ + ./src/cusdr_agcWidget.h \ + ./src/cusdr_displayTabWidget.h \ + ./src/cusdr_radioPopupWidget.h \ + ./src/cusdr_receiverWidget.h \ + #./src/cusdr_server.h \ + ./src/cusdr_serverWidget.h \ + ./src/cusdr_settings.h \ + ./src/cusdr_fonts.h \ + ./src/cusdr_transmitTabWidget.h \ + ./src/cusdr_transmitOptionsWidget.h \ + ./src/cusdr_transmitPAWidget.h \ + ./src/Util/cusdr_cpuUsage_unix.h + +#win32:HEADERS += ./src/Util/cusdr_cpuUsage.h \ + +SOURCES += \ + ./src/Util/cusdr_buttons.cpp \ + ./src/Util/cusdr_colorTriangle.cpp \ + ./src/Util/cusdr_highResTimer.cpp \ + ./src/Util/cusdr_image.cpp \ + ./src/Util/cusdr_imageblur.cpp \ + ./src/Util/cusdr_led.cpp \ + ./src/Util/cusdr_painter.cpp \ + ./src/Util/cusdr_splash.cpp \ + ./src/Util/cusdr_cpuUsage.cpp \ + ./src/AudioEngine/cusdr_audio_engine.cpp \ + ./src/AudioEngine/cusdr_audio_settingsdialog.cpp \ + ./src/AudioEngine/cusdr_audio_spectrumanalyser.cpp \ + ./src/AudioEngine/cusdr_audio_utils.cpp \ + ./src/AudioEngine/cusdr_audio_waveform.cpp \ + ./src/AudioEngine/cusdr_audio_wavfile.cpp \ + ./src/AudioEngine/cusdr_fspectrum.cpp \ + ./src/DataEngine/cusdr_audioReceiver.cpp \ + ./src/DataEngine/cusdr_chirpProcessor.cpp \ + ./src/DataEngine/cusdr_dataEngine.cpp \ + ./src/DataEngine/cusdr_dataIO.cpp \ + ./src/DataEngine/cusdr_discoverer.cpp \ + ./src/DataEngine/cusdr_receiver.cpp \ + ./src/DataEngine/soundout.cpp \ + ./src/DataEngine/fractresampler.cpp \ + ./src/QtDSP/qtdsp_demodulation.cpp \ + ./src/QtDSP/qtdsp_dspEngine.cpp \ + ./src/QtDSP/qtdsp_dualModeAverager.cpp \ + ./src/QtDSP/qtdsp_fft.cpp \ + ./src/QtDSP/qtdsp_filter.cpp \ + ./src/QtDSP/qtdsp_powerSpectrum.cpp \ + ./src/QtDSP/qtdsp_signalMeter.cpp \ + ./src/QtDSP/qtdsp_wpagc.cpp \ + ./src/GL/cusdr_oglDisplayPanel.cpp \ + ./src/GL/cusdr_oglDistancePanel.cpp \ + ./src/GL/cusdr_oglInfo.cpp \ + ./src/GL/cusdr_oglReceiverPanel.cpp \ + ./src/GL/cusdr_oglText.cpp \ + ./src/GL/cusdr_oglWidebandPanel.cpp \ + ./src/cusdr_alexAntennaWidget.cpp \ + ./src/cusdr_alexFilterWidget.cpp \ + ./src/cusdr_alexTabWidget.cpp \ + ./src/cusdr_chirpWidget.cpp \ + ./src/cusdr_displayWidget.cpp \ + ./src/cusdr_colorsWidget.cpp \ + ./src/cusdr_hamDatabase.cpp \ + ./src/cusdr_hpsdrTabWidget.cpp \ + ./src/cusdr_hpsdrWidget.cpp \ + ./src/cusdr_networkWidget.cpp \ + ./src/cusdr_mainWidget.cpp \ + ./src/cusdr_extCtrlWidget.cpp \ + ./src/cusdr_radioTabWidget.cpp \ + ./src/cusdr_radioWidget.cpp \ + ./src/cusdr_agcWidget.cpp \ + ./src/cusdr_displayTabWidget.cpp \ + ./src/cusdr_radioPopupWidget.cpp \ + ./src/cusdr_receiverWidget.cpp \ + #./src/cusdr_server.cpp \ + ./src/cusdr_serverWidget.cpp \ + ./src/cusdr_settings.cpp \ + ./src/cusdr_fonts.cpp \ + ./src/cusdr_transmitTabWidget.cpp \ + ./src/cusdr_transmitOptionsWidget.cpp \ + ./src/cusdr_transmitPAWidget.cpp \ + ./src/main.cpp \ + ./src/Util/cusdr_cpuUsage_unix.cpp + +#win32:SOURCES += ./src/Util/cusdr_cpuUsage.cpp \ diff --git a/Source/cudaSDR.pro b/Source/cudaSDR.pro new file mode 100644 index 0000000..aa4dc4c --- /dev/null +++ b/Source/cudaSDR.pro @@ -0,0 +1,88 @@ +QT += core gui network multimedia opengl + +TARGET = cudaSDR +TEMPLATE = app + +CONFIG += qt warn_on +CONFIG += console +CONFIG += mobility +CONFIG += $$QMAKE_HOST.arch +message(CONFIG: $$QMAKE_HOST.arch) + +MOBILITY += multimedia + +include(cudaSDR.pri) + +RESOURCES += res/cusdr.qrc + +#DEFINES += AUDIO_ENGINE_DEBUG +#DEFINES += _WINDOWS +#DEFINES += _CRT_SECURE_NO_WARNINGS +#DEFINES += QT_LARGEFILE_SUPPORT +#DEFINES += QT_DLL +#DEFINES += QT_MULTIMEDIA_LIB +#DEFINES += QT_OPENGL_LIB +#DEFINES += QT_NETWORK_LIB +#DEFINES += QT_HAVE_MMX +#DEFINES += QT_HAVE_3DNOW +#DEFINES += QT_HAVE_SSE +#DEFINES += QT_HAVE_MMXEXT +#DEFINES += QT_HAVE_SSE2 + +unix { +# CUDA_DIR = $$system(which nvcc | sed 's,/bin/nvcc$,,') + +x86_64 { HOST_ARCH = x86_64-linux } +arm7 { HOST_ARCH = armv7-linux-gnueabihf } + + INCLUDEPATH += \ + ./ \ + src/ \ + src/AudioEngine \ + src/CL \ + src/DataEngine \ + src/GL \ + src/QtDSP \ + src/Util + + LIBS += \ + -lfftw3f -lpulse-simple -lpulse -lasound +} + +# ******************************************************** +# The WIN32 configuration needs to be checked and updated +# ******************************************************** +win32 { + RC_FILE += res/cusdr.rc + + INCLUDEPATH += \ + ./ \ + src/ \ + src/AudioEngine \ + src/CL \ + src/Cuda \ + src/DataEngine \ + src/GL \ + src/QtDSP \ + src/Util \ + $(CUDA_PATH_V6_5)/include + + LIBS += \ + -L"$$(CUDA_PATH_V6_5)/lib/x64" \ + -L"./lib" \ + -lwsock32 \ + -lVersion \ + -lPsapi \ + -lQtOpenCL \ + -lopengl32 \ + -llibfftw3f-3 \ + -lgdi32 \ + -luser32 \ + -lKernel32 +} + +OBJECTS_DIR = ./bld/o +MOC_DIR = ./bld/moc +#UI_DIR = ./bld/ui +RCC_DIR = ./bld/rcc +DESTDIR = ./bin diff --git a/Source/cudaSDR.pro.user b/Source/cudaSDR.pro.user new file mode 100644 index 0000000..af95a52 --- /dev/null +++ b/Source/cudaSDR.pro.user @@ -0,0 +1,208 @@ + + + + + + EnvironmentId + {974be962-b6da-4db1-b656-2716ea8841ad} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Qt 5.3.2 (qt5) + Qt 5.3.2 (qt5) + {c28b2f69-26d0-4219-96bf-795edbc3bba5} + 0 + 0 + 0 + + + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + false + + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 1 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + cudaSDR + + Qt4ProjectManager.Qt4RunConfiguration:/home/mh/RTL/LATEST_RTL/BETTERCODES_SVN/cusdrk/Source/cudaSDR.pro + + cudaSDR.pro + false + true + + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 16 + + + Version + 16 + + diff --git a/Source/res/cusdr.qrc b/Source/res/cusdr.qrc new file mode 100644 index 0000000..f5ff076 --- /dev/null +++ b/Source/res/cusdr.qrc @@ -0,0 +1,36 @@ + + + img/close.png + img/close_high.png + img/hide.png + img/hide_high.png + img/minimize.png + img/minimize_high.png + img/maximize.png + img/maximize_high.png + img/leftTop.png + img/leftMiddle.png + img/leftBottom.png + img/left.png + img/rightTop.png + img/rightMiddle.png + img/rightBottom.png + img/right.png + img/topBorder.png + img/bottomBorder.png + img/drawer.png + img/left_arrow.png + img/right_arrow.png + img/up_arrow.png + img/down_arrow.png + img/up_arrow_off.png + img/down_arrow_off.png + img/cusdrLogo.png + img/cuSDR_32.ico + img/cuSDR_64.ico + img/cusdrLogo2.png + img/cudaSDRLogo.png + img/cusdr4.png + img/hpsdr4.png + + diff --git a/Source/res/cusdr.rc b/Source/res/cusdr.rc new file mode 100644 index 0000000..5fa5e34 --- /dev/null +++ b/Source/res/cusdr.rc @@ -0,0 +1 @@ +IDI_ICON1 ICON DISCARDABLE "img/cuSDR_64.ico" \ No newline at end of file diff --git a/Source/res/img/MainBkg.png b/Source/res/img/MainBkg.png new file mode 100644 index 0000000..bc62949 Binary files /dev/null and b/Source/res/img/MainBkg.png differ diff --git a/Source/res/img/VolumeIcon.icns b/Source/res/img/VolumeIcon.icns new file mode 100644 index 0000000..76e62cd Binary files /dev/null and b/Source/res/img/VolumeIcon.icns differ diff --git a/Source/res/img/VolumeIcon.psd b/Source/res/img/VolumeIcon.psd new file mode 100644 index 0000000..2cf7576 Binary files /dev/null and b/Source/res/img/VolumeIcon.psd differ diff --git a/Source/res/img/bottomBorder.png b/Source/res/img/bottomBorder.png new file mode 100644 index 0000000..c3c3771 Binary files /dev/null and b/Source/res/img/bottomBorder.png differ diff --git a/Source/res/img/close - Kopie.png b/Source/res/img/close - Kopie.png new file mode 100644 index 0000000..698bde1 Binary files /dev/null and b/Source/res/img/close - Kopie.png differ diff --git a/Source/res/img/close.png b/Source/res/img/close.png new file mode 100644 index 0000000..c536d49 Binary files /dev/null and b/Source/res/img/close.png differ diff --git a/Source/res/img/close_high.png b/Source/res/img/close_high.png new file mode 100644 index 0000000..c883913 Binary files /dev/null and b/Source/res/img/close_high.png differ diff --git a/Source/res/img/cuSDR.ico b/Source/res/img/cuSDR.ico new file mode 100644 index 0000000..827b01a Binary files /dev/null and b/Source/res/img/cuSDR.ico differ diff --git a/Source/res/img/cuSDR_32.ico b/Source/res/img/cuSDR_32.ico new file mode 100644 index 0000000..dd04595 Binary files /dev/null and b/Source/res/img/cuSDR_32.ico differ diff --git a/Source/res/img/cuSDR_64.ico b/Source/res/img/cuSDR_64.ico new file mode 100644 index 0000000..187f570 Binary files /dev/null and b/Source/res/img/cuSDR_64.ico differ diff --git a/Source/res/img/cuSDR_big.ico b/Source/res/img/cuSDR_big.ico new file mode 100644 index 0000000..14c8155 Binary files /dev/null and b/Source/res/img/cuSDR_big.ico differ diff --git a/Source/res/img/cudaLogo.xcf b/Source/res/img/cudaLogo.xcf new file mode 100644 index 0000000..ab189c1 Binary files /dev/null and b/Source/res/img/cudaLogo.xcf differ diff --git a/Source/res/img/cudaSDRLogo.png b/Source/res/img/cudaSDRLogo.png new file mode 100644 index 0000000..ce7ef07 Binary files /dev/null and b/Source/res/img/cudaSDRLogo.png differ diff --git a/Source/res/img/cusdr2.png b/Source/res/img/cusdr2.png new file mode 100644 index 0000000..4607170 Binary files /dev/null and b/Source/res/img/cusdr2.png differ diff --git a/Source/res/img/cusdr3.png b/Source/res/img/cusdr3.png new file mode 100644 index 0000000..c2ba633 Binary files /dev/null and b/Source/res/img/cusdr3.png differ diff --git a/Source/res/img/cusdr4.png b/Source/res/img/cusdr4.png new file mode 100644 index 0000000..3bf467a Binary files /dev/null and b/Source/res/img/cusdr4.png differ diff --git a/Source/res/img/cusdrLogo.png b/Source/res/img/cusdrLogo.png new file mode 100644 index 0000000..92135a3 Binary files /dev/null and b/Source/res/img/cusdrLogo.png differ diff --git a/Source/res/img/cusdrLogo2.png b/Source/res/img/cusdrLogo2.png new file mode 100644 index 0000000..1d85332 Binary files /dev/null and b/Source/res/img/cusdrLogo2.png differ diff --git a/Source/res/img/cusdrLogo2_org.png b/Source/res/img/cusdrLogo2_org.png new file mode 100644 index 0000000..9e04aff Binary files /dev/null and b/Source/res/img/cusdrLogo2_org.png differ diff --git a/Source/res/img/cusdrLogo3.png b/Source/res/img/cusdrLogo3.png new file mode 100644 index 0000000..23898c2 Binary files /dev/null and b/Source/res/img/cusdrLogo3.png differ diff --git a/Source/res/img/cusdr_hpsdr.png b/Source/res/img/cusdr_hpsdr.png new file mode 100644 index 0000000..93f1483 Binary files /dev/null and b/Source/res/img/cusdr_hpsdr.png differ diff --git a/Source/res/img/down_arrow.png b/Source/res/img/down_arrow.png new file mode 100644 index 0000000..83dce26 Binary files /dev/null and b/Source/res/img/down_arrow.png differ diff --git a/Source/res/img/down_arrow_off.png b/Source/res/img/down_arrow_off.png new file mode 100644 index 0000000..f6a1cbe Binary files /dev/null and b/Source/res/img/down_arrow_off.png differ diff --git a/Source/res/img/drawer.png b/Source/res/img/drawer.png new file mode 100644 index 0000000..4f9a07a Binary files /dev/null and b/Source/res/img/drawer.png differ diff --git a/Source/res/img/hide.png b/Source/res/img/hide.png new file mode 100644 index 0000000..9c85ed4 Binary files /dev/null and b/Source/res/img/hide.png differ diff --git a/Source/res/img/hide_high.png b/Source/res/img/hide_high.png new file mode 100644 index 0000000..c062a8a Binary files /dev/null and b/Source/res/img/hide_high.png differ diff --git a/Source/res/img/hpsdr4.png b/Source/res/img/hpsdr4.png new file mode 100644 index 0000000..9d83977 Binary files /dev/null and b/Source/res/img/hpsdr4.png differ diff --git a/Source/res/img/hpsdr5.ico b/Source/res/img/hpsdr5.ico new file mode 100644 index 0000000..7d6e97a Binary files /dev/null and b/Source/res/img/hpsdr5.ico differ diff --git a/Source/res/img/left - Kopie.png b/Source/res/img/left - Kopie.png new file mode 100644 index 0000000..9baffd3 Binary files /dev/null and b/Source/res/img/left - Kopie.png differ diff --git a/Source/res/img/left.png b/Source/res/img/left.png new file mode 100644 index 0000000..83afbf1 Binary files /dev/null and b/Source/res/img/left.png differ diff --git a/Source/res/img/leftBottom.png b/Source/res/img/leftBottom.png new file mode 100644 index 0000000..a2b42f5 Binary files /dev/null and b/Source/res/img/leftBottom.png differ diff --git a/Source/res/img/leftMiddle.png b/Source/res/img/leftMiddle.png new file mode 100644 index 0000000..1f47f59 Binary files /dev/null and b/Source/res/img/leftMiddle.png differ diff --git a/Source/res/img/leftTop.png b/Source/res/img/leftTop.png new file mode 100644 index 0000000..1973aa7 Binary files /dev/null and b/Source/res/img/leftTop.png differ diff --git a/Source/res/img/left_arrow.png b/Source/res/img/left_arrow.png new file mode 100644 index 0000000..329fb23 Binary files /dev/null and b/Source/res/img/left_arrow.png differ diff --git a/Source/res/img/maximize.png b/Source/res/img/maximize.png new file mode 100644 index 0000000..1bc9e42 Binary files /dev/null and b/Source/res/img/maximize.png differ diff --git a/Source/res/img/maximize_high.png b/Source/res/img/maximize_high.png new file mode 100644 index 0000000..2d5d64b Binary files /dev/null and b/Source/res/img/maximize_high.png differ diff --git a/Source/res/img/minimize.png b/Source/res/img/minimize.png new file mode 100644 index 0000000..6a39d90 Binary files /dev/null and b/Source/res/img/minimize.png differ diff --git a/Source/res/img/minimize_high.png b/Source/res/img/minimize_high.png new file mode 100644 index 0000000..4fc7a0a Binary files /dev/null and b/Source/res/img/minimize_high.png differ diff --git a/Source/res/img/record.png b/Source/res/img/record.png new file mode 100644 index 0000000..e7493aa Binary files /dev/null and b/Source/res/img/record.png differ diff --git a/Source/res/img/right - Kopie.png b/Source/res/img/right - Kopie.png new file mode 100644 index 0000000..85c6428 Binary files /dev/null and b/Source/res/img/right - Kopie.png differ diff --git a/Source/res/img/right.png b/Source/res/img/right.png new file mode 100644 index 0000000..ccb1d39 Binary files /dev/null and b/Source/res/img/right.png differ diff --git a/Source/res/img/rightBottom.png b/Source/res/img/rightBottom.png new file mode 100644 index 0000000..04384a2 Binary files /dev/null and b/Source/res/img/rightBottom.png differ diff --git a/Source/res/img/rightMiddle.png b/Source/res/img/rightMiddle.png new file mode 100644 index 0000000..9ff3bdd Binary files /dev/null and b/Source/res/img/rightMiddle.png differ diff --git a/Source/res/img/rightTop.png b/Source/res/img/rightTop.png new file mode 100644 index 0000000..27177f1 Binary files /dev/null and b/Source/res/img/rightTop.png differ diff --git a/Source/res/img/right_arrow.png b/Source/res/img/right_arrow.png new file mode 100644 index 0000000..b9288f3 Binary files /dev/null and b/Source/res/img/right_arrow.png differ diff --git a/Source/res/img/settings.png b/Source/res/img/settings.png new file mode 100644 index 0000000..12179dc Binary files /dev/null and b/Source/res/img/settings.png differ diff --git a/Source/res/img/splash.psd b/Source/res/img/splash.psd new file mode 100644 index 0000000..1390d20 Binary files /dev/null and b/Source/res/img/splash.psd differ diff --git a/Source/res/img/topBorder.png b/Source/res/img/topBorder.png new file mode 100644 index 0000000..5c00d86 Binary files /dev/null and b/Source/res/img/topBorder.png differ diff --git a/Source/res/img/topBorder2.png b/Source/res/img/topBorder2.png new file mode 100644 index 0000000..39632d3 Binary files /dev/null and b/Source/res/img/topBorder2.png differ diff --git a/Source/res/img/up_arrow.png b/Source/res/img/up_arrow.png new file mode 100644 index 0000000..e66a2a9 Binary files /dev/null and b/Source/res/img/up_arrow.png differ diff --git a/Source/res/img/up_arrow_off.png b/Source/res/img/up_arrow_off.png new file mode 100644 index 0000000..7a863b2 Binary files /dev/null and b/Source/res/img/up_arrow_off.png differ diff --git a/Source/res/img/upd-error.png b/Source/res/img/upd-error.png new file mode 100644 index 0000000..7ea1fab Binary files /dev/null and b/Source/res/img/upd-error.png differ diff --git a/Source/res/img/upd-info.png b/Source/res/img/upd-info.png new file mode 100644 index 0000000..c7c5d23 Binary files /dev/null and b/Source/res/img/upd-info.png differ diff --git a/Source/res/img/upd-warning.png b/Source/res/img/upd-warning.png new file mode 100644 index 0000000..3cde5d0 Binary files /dev/null and b/Source/res/img/upd-warning.png differ diff --git a/Source/res/img/warn.png b/Source/res/img/warn.png new file mode 100644 index 0000000..26a212e Binary files /dev/null and b/Source/res/img/warn.png differ diff --git a/Source/res/img/warning.png b/Source/res/img/warning.png new file mode 100644 index 0000000..3cde5d0 Binary files /dev/null and b/Source/res/img/warning.png differ diff --git a/Source/res/img/warningMediumIcon.png b/Source/res/img/warningMediumIcon.png new file mode 100644 index 0000000..6a92f67 Binary files /dev/null and b/Source/res/img/warningMediumIcon.png differ diff --git a/Source/res/qrc_cusdr.cpp b/Source/res/qrc_cusdr.cpp new file mode 100644 index 0000000..04cc8d1 --- /dev/null +++ b/Source/res/qrc_cusdr.cpp @@ -0,0 +1,20963 @@ +/**************************************************************************** +** Resource object code +** +** Created: Wed 18. Jul 19:41:47 2012 +** by: The Resource Compiler for Qt version 4.8.0 +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include + +static const unsigned char qt_resource_data[] = { + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/drawer.png + 0x0,0x0,0x0,0xc0, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x13,0x0,0x0,0x0,0xd,0x8,0x2,0x0,0x0,0x0,0xc4,0xee,0xc2,0x70, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4, + 0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x0,0x72,0x49,0x44,0x41,0x54,0x78,0x9c,0x63, + 0xb4,0xb1,0xb1,0x61,0xc0,0x6,0x44,0xa5,0x15,0x4c,0x4d,0xc,0x17,0x2e,0x5c,0x24, + 0x2a,0xc0,0x8b,0x95,0xcd,0x44,0x9e,0x36,0x51,0x1,0x5e,0x2c,0x3a,0x89,0xd1,0x26, + 0x2a,0xad,0x80,0xae,0x93,0x48,0x6d,0xa6,0x26,0x86,0x4c,0xe4,0x69,0x43,0xf1,0x27, + 0x49,0xda,0x10,0xfe,0x24,0x55,0x1b,0xd4,0x9f,0x64,0x68,0x33,0x35,0x31,0x64,0x22, + 0x4f,0xdb,0xc2,0x85,0x8b,0x98,0xc8,0xd3,0x26,0x2a,0xc0,0xcb,0xfc,0xe4,0xf9,0x4b, + 0x32,0xb4,0x31,0x30,0x30,0x30,0x91,0xa7,0x8d,0x81,0x81,0x81,0x11,0x92,0x6e,0x5f, + 0x7f,0xf8,0xc,0x17,0x22,0x86,0xcd,0xc0,0xc0,0x0,0x0,0x7e,0xc,0x9c,0x28,0xdb, + 0x9f,0x2c,0x36,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/close.png + 0x0,0x0,0x1,0x99, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x2,0x0,0x0,0x0,0xb4,0xb4,0x2,0x1d, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4, + 0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x1,0x4b,0x49,0x44,0x41,0x54,0x78,0x9c,0x8d, + 0x8c,0xd1,0x4a,0xc2,0x60,0x1c,0xc5,0xcf,0xbe,0x7d,0x2e,0xcb,0x1b,0x85,0xcd,0x75, + 0x31,0x8,0xb1,0x1c,0x4b,0x6b,0x5d,0xc6,0xae,0xa2,0x10,0xba,0xb6,0x27,0x30,0xe8, + 0x11,0x7a,0xa,0x1f,0xa2,0x27,0xc8,0xeb,0x50,0xda,0xa5,0x44,0x24,0x34,0x48,0x47, + 0x60,0x78,0x23,0x12,0x6e,0xe8,0x8a,0xca,0x6c,0x6b,0x74,0xa1,0x7c,0xad,0x28,0xf4, + 0xf0,0xbf,0x39,0xbf,0x73,0xfe,0x87,0x2b,0x1f,0x9f,0x14,0x8b,0xfb,0xce,0x60,0x80, + 0x79,0xba,0xb5,0xee,0xb8,0x7a,0xbd,0x9e,0x17,0x37,0x10,0x7c,0x0,0x21,0x82,0x9, + 0x0,0xf8,0x13,0x84,0x3e,0x0,0xf8,0xef,0x0,0x10,0x6,0x8,0x43,0x4,0x2f,0xad, + 0x78,0x92,0x3a,0xae,0x8b,0x87,0xeb,0xb9,0xc3,0x58,0x4a,0x38,0xf1,0x80,0x36,0x6f, + 0x9a,0x7b,0xd2,0xdb,0xfc,0x36,0xd0,0x74,0x7a,0x74,0x38,0x7a,0x2,0xe7,0xce,0x40, + 0xa5,0x8a,0xd3,0xd2,0x8f,0x4a,0x84,0xc,0x47,0x22,0xf5,0xbc,0x21,0xc2,0xc7,0xa9, + 0xb7,0xd,0x4d,0x6b,0xd8,0xdf,0xf,0x95,0xaa,0x6d,0x68,0x9a,0x9a,0x9a,0x3a,0xef, + 0x99,0x70,0x6a,0x61,0xe7,0x32,0xf3,0xca,0xb6,0xee,0x5d,0x5e,0x6b,0xd8,0x28,0x1b, + 0x38,0x6b,0xd8,0x86,0xa6,0x8a,0x9f,0x2c,0x3a,0xe8,0x26,0x28,0x80,0x7e,0xbb,0xcb, + 0x90,0xba,0x99,0xb1,0x74,0x45,0xb7,0x7a,0x96,0xae,0x6c,0xad,0xad,0x44,0x23,0x2c, + 0x17,0x28,0x0,0x42,0x9,0x23,0xfd,0x76,0x57,0xef,0xf8,0x17,0x49,0x7a,0xe8,0x5, + 0xbd,0xf5,0x58,0x34,0x2,0x40,0x0,0xf0,0x3c,0x61,0xa7,0x74,0xfc,0x9a,0x18,0xdb, + 0x5e,0xe5,0x6b,0x62,0x4c,0xe9,0xf8,0xd1,0x68,0xd6,0x66,0x92,0x5b,0x63,0x53,0x12, + 0x74,0x99,0xf2,0x3c,0xd1,0x65,0x6a,0x4a,0x82,0xdc,0x1a,0xff,0xde,0x66,0x32,0x25, + 0x21,0x9f,0xe6,0x99,0xcd,0xa7,0x79,0x53,0x12,0xfe,0x6d,0x47,0xab,0x7f,0x12,0x92, + 0xca,0x65,0x9,0xc7,0x2d,0x72,0xa9,0x5c,0x96,0x3,0xb0,0x5b,0x3a,0xc2,0x2,0xba, + 0xaa,0x9e,0x7f,0x1,0x93,0xf4,0x70,0x7a,0xbe,0xa3,0x9a,0x2e,0x0,0x0,0x0,0x0, + 0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/leftMiddle.png + 0x0,0x0,0x0,0x7e, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b, + 0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5, + 0x0,0x0,0x0,0x35,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0x64,0x60,0x60,0xf8,0x1f, + 0x19,0x9f,0xc2,0xf0,0xe8,0xd1,0x63,0x6,0xc6,0xdf,0x5f,0x81,0x5c,0x8,0x90,0x55, + 0xd6,0x80,0xb3,0x41,0xa,0xfe,0x5b,0x3b,0xba,0xff,0xb7,0xb1,0xb1,0xc1,0xc0,0x20, + 0x55,0x43,0x57,0x1,0xc8,0x67,0x20,0xc,0x0,0xd7,0x30,0x65,0x6a,0xf0,0x16,0xc2, + 0x46,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/maximize.png + 0x0,0x0,0x1,0xa1, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x36,0x49,0x44,0x41,0x54,0x38,0x4f,0x9d,0x92,0xcb,0x4a, + 0xc3,0x40,0x14,0x86,0xff,0x99,0x4e,0x43,0xde,0x20,0x10,0xb2,0x10,0x5,0x15,0x11, + 0x51,0x31,0xb,0x71,0xa1,0x7d,0x15,0xf1,0x5,0xa4,0xbe,0x87,0xe0,0xda,0xcb,0xce, + 0x6e,0x44,0x71,0x1d,0x24,0xba,0x70,0x15,0x51,0x10,0x5,0xa1,0x64,0x17,0xa8,0x71, + 0x51,0x93,0x20,0x94,0xdc,0x75,0x2,0x86,0x24,0xd3,0x45,0xdb,0x81,0x1f,0xce,0x7c, + 0xf3,0x9f,0x33,0x67,0x2e,0xa4,0xdb,0x3d,0xca,0x75,0x7d,0xb,0xae,0xeb,0x62,0xd2, + 0xa1,0x28,0xa,0x2c,0xeb,0x9,0xc4,0x30,0x8c,0x5c,0x55,0x55,0x4,0x41,0x80,0x2c, + 0xcb,0x10,0x45,0x51,0x51,0x23,0xc,0x43,0x24,0x49,0x52,0xc6,0x3c,0x48,0xd3,0xb4, + 0xf0,0x50,0x4a,0x8b,0x98,0x5c,0xf6,0x7a,0xb9,0x6d,0xdb,0x93,0x6e,0x5a,0xf8,0x64, + 0x59,0x46,0x8b,0x31,0x10,0xde,0xf6,0x54,0x99,0x15,0x33,0x1b,0x7e,0xfb,0xb5,0xdc, + 0x4e,0x67,0x17,0x6b,0x3b,0x7b,0x42,0xbd,0xd7,0xc7,0x7b,0x98,0xe6,0x43,0x8d,0x53, + 0xcf,0x1b,0xa2,0xaa,0x65,0x7d,0xfb,0xef,0xdc,0xa1,0x20,0xce,0x9b,0x5e,0xf6,0xf6, + 0xfe,0x1,0x4d,0xd3,0xca,0x8a,0x51,0x14,0xe3,0xf0,0x60,0x5f,0xd8,0xf9,0xf8,0xf4, + 0x1c,0x9e,0xff,0x53,0x72,0xc7,0x71,0xc0,0x46,0xe1,0x8,0x7d,0xbb,0x5f,0x42,0x3f, + 0xf0,0x31,0xf8,0xfa,0x14,0x92,0x39,0xaf,0xfa,0xb8,0x81,0xb6,0x25,0x19,0x55,0xd1, + 0x16,0xab,0xcd,0xff,0xd7,0xc6,0x71,0x2a,0x49,0x12,0xaa,0xe2,0x15,0x9b,0x8c,0xcf, + 0xc7,0x71,0xd6,0xec,0xcf,0xbc,0xbd,0xc6,0xc9,0xd9,0x85,0xd0,0xf6,0xdd,0xcd,0x95, + 0xc0,0xc8,0xd2,0xea,0xfa,0xcc,0xef,0x4c,0x67,0xfd,0x20,0xc5,0x85,0xad,0x2c,0x2e, + 0x80,0xb5,0xa5,0x52,0x39,0x8,0xe2,0x38,0x11,0xc4,0x79,0xd5,0xc7,0xf3,0x88,0x36, + 0x37,0x9f,0xeb,0x9b,0x1b,0x53,0x37,0x60,0x3d,0xbf,0xe0,0x17,0x4b,0xc,0x9c,0x2, + 0x3b,0xfe,0xf0,0xc9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/cuSDR_32.ico + 0x0,0x0,0x10,0xbe, + 0x0, + 0x0,0x1,0x0,0x1,0x0,0x20,0x20,0x0,0x0,0x1,0x0,0x20,0x0,0xa8,0x10,0x0, + 0x0,0x16,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x20,0x0,0x0,0x0,0x40,0x0,0x0, + 0x0,0x1,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf7,0xf6,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf6,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf6,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf8,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf8,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xef,0xea,0x4, + 0x68,0xef,0xea,0x4,0x68,0xef,0xea,0x4,0x68,0xef,0xea,0x4,0x68,0xef,0xeb,0x4, + 0x68,0xf0,0xeb,0x4,0x68,0xf0,0xeb,0x4,0x68,0xf0,0xeb,0x4,0x68,0xf0,0xec,0x4, + 0x68,0xf0,0xec,0x4,0x68,0xf0,0xec,0x3,0x68,0xf0,0xec,0x3,0x68,0xf0,0xec,0x3, + 0x68,0xf1,0xed,0x3,0x68,0xf1,0xec,0x3,0x68,0xf1,0xec,0x3,0x68,0xf1,0xed,0x3, + 0x68,0xf1,0xee,0x3,0x68,0xf1,0xed,0x3,0x68,0xf1,0xed,0x3,0x68,0xf2,0xed,0x3, + 0x68,0xf2,0xee,0x3,0x68,0xf2,0xee,0x3,0x68,0xf2,0xee,0x3,0x68,0xf2,0xee,0x2, + 0x68,0xf2,0xef,0x2,0x68,0xf2,0xef,0x2,0x68,0xf3,0xef,0x2,0x68,0xf3,0xef,0x2, + 0x68,0xf3,0xf0,0x2,0x68,0xf2,0xf0,0x2,0x68,0xf2,0xf0,0x2,0x68,0xe1,0xd4,0xb, + 0x68,0xe2,0xd4,0xb,0x68,0xe2,0xd4,0xb,0x68,0xe2,0xd4,0xb,0x68,0xe2,0xd5,0xa, + 0x68,0xe2,0xd5,0xa,0x68,0xe2,0xd5,0xa,0x68,0xe2,0xd5,0xa,0x68,0xe3,0xd5,0xa, + 0x68,0xe3,0xd6,0xa,0x68,0xe3,0xd6,0xa,0x68,0xe3,0xd6,0xa,0x68,0xe3,0xd6,0xa, + 0x68,0xe3,0xd6,0xa,0x68,0xe4,0xd7,0xa,0x68,0xe4,0xd7,0xa,0x68,0xe3,0xd7,0xa, + 0x68,0xe4,0xd8,0xa,0x68,0xe4,0xd8,0xa,0x68,0xe4,0xd8,0x9,0x68,0xe4,0xd8,0x9, + 0x68,0xe4,0xd9,0x9,0x68,0xe4,0xd9,0x9,0x68,0xe5,0xd9,0x9,0x68,0xe5,0xd9,0x9, + 0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x8, + 0x68,0xe6,0xda,0x9,0x68,0xe6,0xdb,0x9,0x68,0xe6,0xdb,0x8,0x68,0xd4,0xbd,0x11, + 0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbe,0x11, + 0x68,0xd5,0xbf,0x11,0x68,0xd5,0xbf,0x11,0x68,0xd5,0xbf,0x11,0x68,0xd6,0xbf,0x11, + 0x68,0xd6,0xbf,0x11,0x68,0xd6,0xc0,0x11,0x68,0xd6,0xc0,0x10,0x68,0xd6,0xc0,0x10, + 0x68,0xd6,0xc1,0x10,0x68,0xd6,0xc1,0x10,0x68,0xd7,0xc1,0x10,0x68,0xd7,0xc1,0x10, + 0x68,0xd7,0xc2,0x10,0x68,0xd7,0xc2,0x10,0x68,0xd7,0xc2,0x10,0x68,0xd7,0xc2,0x10, + 0x68,0xd8,0xc2,0x10,0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc3,0x10, + 0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc4,0xf,0x68,0xd8,0xc4,0xf,0x68,0xd9,0xc4,0xf, + 0x68,0xd9,0xc4,0xf,0x68,0xd8,0xc4,0xf,0x68,0xd9,0xc5,0xf,0x68,0xc7,0xa8,0x18, + 0x68,0xc7,0xa9,0x18,0x68,0xc7,0xa9,0x18,0x67,0xc8,0xa9,0x18,0x67,0xc8,0xa9,0x18, + 0x67,0xc8,0xa9,0x18,0x67,0xc8,0xaa,0x18,0x67,0xc8,0xaa,0x18,0x67,0xc9,0xaa,0x18, + 0x68,0xc8,0xaa,0x18,0x68,0xc8,0xab,0x18,0x68,0xc9,0xab,0x18,0x67,0xc9,0xab,0x18, + 0x67,0xc9,0xab,0x17,0x67,0xc9,0xab,0x18,0x67,0xc9,0xac,0x17,0x68,0xc9,0xac,0x17, + 0x68,0xc9,0xac,0x17,0x68,0xca,0xac,0x17,0x68,0xca,0xad,0x17,0x68,0xca,0xad,0x17, + 0x67,0xca,0xac,0x17,0x68,0xca,0xac,0x17,0x68,0xca,0xad,0x17,0x67,0xcb,0xad,0x17, + 0x67,0xca,0xae,0x17,0x67,0xcb,0xae,0x17,0x67,0xcb,0xae,0x17,0x68,0xcb,0xae,0x17, + 0x68,0xcb,0xae,0x16,0x67,0xcb,0xaf,0x16,0x68,0xcc,0xaf,0x16,0x68,0xbc,0x94,0x1e, + 0x68,0xbc,0x94,0x1e,0x67,0xbc,0x94,0x1e,0x68,0xbc,0x94,0x1e,0x69,0xbc,0x96,0x1f, + 0x6a,0xbc,0x95,0x1e,0x6a,0xbc,0x95,0x1e,0x69,0xbc,0x95,0x1e,0x68,0xbd,0x96,0x1e, + 0x68,0xbd,0x96,0x1e,0x68,0xbd,0x95,0x1e,0x67,0xbd,0x96,0x1e,0x69,0xbd,0x96,0x1e, + 0x6a,0xbd,0x96,0x1d,0x69,0xbd,0x96,0x1e,0x69,0xbe,0x97,0x1d,0x68,0xbe,0x97,0x1d, + 0x68,0xbe,0x97,0x1d,0x67,0xbe,0x98,0x1d,0x67,0xbe,0x97,0x1d,0x68,0xbe,0x98,0x1d, + 0x69,0xbf,0x9a,0x1e,0x6b,0xbf,0x99,0x1e,0x6a,0xbe,0x98,0x1d,0x69,0xbf,0x99,0x1d, + 0x68,0xbf,0x99,0x1d,0x68,0xbf,0x99,0x1d,0x6a,0xbf,0x9a,0x1e,0x6b,0xbf,0x9b,0x1e, + 0x6b,0xbf,0x9a,0x1c,0x69,0xbf,0x9a,0x1d,0x67,0xc0,0x9a,0x1c,0x67,0xaf,0x80,0x24, + 0x67,0xb0,0x80,0x25,0x68,0xb3,0x84,0x26,0x6d,0xb8,0x8a,0x29,0x76,0xbc,0x8e,0x2c, + 0x7d,0xbc,0x8e,0x2b,0x7d,0xb9,0x8b,0x2a,0x77,0xb6,0x87,0x27,0x70,0xb2,0x83,0x25, + 0x6b,0xb1,0x82,0x24,0x69,0xb2,0x84,0x25,0x6b,0xb8,0x89,0x28,0x73,0xba,0x8d,0x2a, + 0x77,0xb8,0x8a,0x28,0x74,0xb5,0x87,0x26,0x6f,0xb3,0x85,0x24,0x6b,0xb1,0x84,0x24, + 0x69,0xb1,0x84,0x23,0x68,0xb2,0x83,0x23,0x68,0xb3,0x85,0x24,0x6a,0xba,0x8c,0x28, + 0x75,0xc1,0x93,0x2d,0x83,0xc1,0x94,0x2d,0x82,0xb9,0x8c,0x27,0x74,0xb3,0x86,0x24, + 0x6a,0xb4,0x87,0x24,0x6c,0xbb,0x8f,0x29,0x77,0xc2,0x95,0x2d,0x84,0xc1,0x95,0x2d, + 0x83,0xba,0x8e,0x27,0x74,0xb4,0x87,0x22,0x6a,0xb3,0x87,0x22,0x68,0xa4,0x6d,0x2a, + 0x67,0xa6,0x6f,0x2b,0x6b,0xb6,0x81,0x32,0x83,0xc3,0x92,0x3a,0xa6,0xc8,0x97,0x3a, + 0xb8,0xc9,0x97,0x3a,0xb8,0xc6,0x94,0x3a,0xad,0xc0,0x8d,0x37,0x9a,0xb7,0x84,0x33, + 0x86,0xb0,0x7b,0x2f,0x78,0xb3,0x7f,0x30,0x7f,0xc0,0x8f,0x37,0x9b,0xc6,0x94,0x3a, + 0xad,0xc4,0x93,0x39,0xa6,0xbf,0x8d,0x37,0x96,0xb8,0x84,0x33,0x86,0xb1,0x7c,0x2f, + 0x79,0xaa,0x74,0x2b,0x6e,0xa6,0x71,0x2a,0x6a,0xad,0x79,0x2d,0x72,0xbf,0x8d,0x36, + 0x95,0xcb,0x9a,0x3c,0xbc,0xca,0x9a,0x3b,0xba,0xbf,0x8d,0x35,0x94,0xb2,0x7d,0x2f, + 0x78,0xb6,0x84,0x31,0x82,0xc4,0x94,0x38,0xa3,0xcc,0x9c,0x3b,0xc0,0xcb,0x9c,0x3c, + 0xbb,0xbe,0x8c,0x34,0x90,0xac,0x78,0x2b,0x6f,0xa8,0x72,0x29,0x68,0x98,0x5e,0x2b, + 0x67,0x9f,0x66,0x2e,0x70,0xbc,0x88,0x3a,0xa4,0xca,0x98,0x3e,0xda,0xe0,0xc1,0x85, + 0xf2,0xdc,0xb9,0x75,0xf2,0xcd,0x9b,0x3e,0xe9,0xc9,0x97,0x3a,0xdb,0xc6,0x93,0x3e, + 0xc3,0xbd,0x8a,0x3b,0xa8,0xbe,0x8c,0x3b,0xac,0xc9,0x96,0x3c,0xd1,0xd4,0xa8,0x58, + 0xea,0xca,0x96,0x34,0xe5,0xca,0x97,0x3a,0xd8,0xc7,0x95,0x3e,0xc6,0xc0,0x8c,0x3c, + 0xac,0xb3,0x7f,0x36,0x90,0xa9,0x71,0x31,0x7b,0xac,0x75,0x33,0x80,0xc2,0x8f,0x3b, + 0xb4,0xd5,0xaa,0x5a,0xe8,0xd7,0xb0,0x65,0xea,0xc5,0x93,0x3e,0xbe,0xbb,0x87,0x39, + 0x9e,0xc2,0x8f,0x3d,0xb4,0xcc,0x99,0x3d,0xdb,0xe2,0xc5,0x8d,0xf4,0xcd,0x9c,0x3f, + 0xdf,0xbe,0x8a,0x3a,0xa5,0xa5,0x6c,0x30,0x73,0x9c,0x62,0x2d,0x68,0x8e,0x55,0x27, + 0x67,0x97,0x5f,0x2a,0x71,0xb9,0x86,0x37,0xaf,0xd1,0xa9,0x5e,0xe9,0xf7,0xf0,0xe4, + 0xfe,0xf6,0xef,0xe0,0xfe,0xfb,0xf8,0xf2,0xff,0xf0,0xe3,0xc8,0xfd,0xd7,0xb3,0x6e, + 0xf2,0xc6,0x95,0x3a,0xe1,0xc7,0x97,0x3f,0xdf,0xce,0xa0,0x4a,0xf1,0xff,0xff,0xff, + 0xff,0xf9,0xf3,0xe9,0xff,0xef,0xe0,0xc2,0xfc,0xdc,0xbb,0x7c,0xf5,0xcc,0x9e,0x4a, + 0xe6,0xc2,0x91,0x39,0xcc,0xb9,0x86,0x39,0xab,0xb3,0x7f,0x36,0x9c,0xc1,0x8e,0x39, + 0xc3,0xd8,0xb2,0x6e,0xf3,0xe5,0xcc,0x9d,0xfb,0xc9,0x98,0x3e,0xe5,0xc6,0x95,0x3e, + 0xd6,0xca,0x9a,0x40,0xe6,0xe6,0xcd,0x9e,0xf9,0xed,0xde,0xc0,0xfb,0xc7,0x96,0x3e, + 0xda,0xb3,0x81,0x36,0x9d,0x9a,0x62,0x2b,0x71,0x91,0x58,0x28,0x67,0x83,0x4d,0x23, + 0x67,0x8a,0x54,0x26,0x6d,0xa9,0x77,0x32,0x99,0xbb,0x8c,0x3a,0xc7,0xc4,0x95,0x40, + 0xe3,0xc8,0x9a,0x42,0xf3,0xcb,0x9e,0x45,0xfd,0xd2,0xab,0x61,0xff,0xfa,0xf5,0xee, + 0xfe,0xee,0xdf,0xc2,0xfd,0xc8,0x99,0x40,0xfa,0xc6,0x95,0x37,0xfd,0xf9,0xf5,0xed, + 0xff,0xd6,0xb1,0x6c,0xff,0xd5,0xb0,0x6a,0xff,0xf2,0xe7,0xd3,0xff,0xfd,0xfc,0xfa, + 0xfe,0xda,0xbd,0x82,0xf7,0xc1,0x90,0x36,0xe2,0xbe,0x8e,0x3b,0xcb,0xc0,0x91,0x3c, + 0xd5,0xca,0x9e,0x48,0xf3,0xf6,0xee,0xdf,0xff,0xc5,0x93,0x34,0xf9,0xc7,0x97,0x3c, + 0xf7,0xf4,0xeb,0xda,0xfd,0xe5,0xce,0xa3,0xfd,0xc4,0x94,0x3b,0xe6,0xb7,0x86,0x39, + 0xb7,0x9f,0x6a,0x2e,0x83,0x8a,0x54,0x25,0x6c,0x87,0x50,0x25,0x68,0x79,0x45,0x1f, + 0x67,0x7b,0x46,0x20,0x69,0x8d,0x5a,0x27,0x7c,0xa5,0x74,0x31,0x9f,0xb7,0x88,0x38, + 0xca,0xc0,0x92,0x3c,0xec,0xc2,0x92,0x35,0xfb,0xc4,0x95,0x3b,0xff,0xcd,0xa6,0x58, + 0xff,0xff,0xff,0xff,0xff,0xdd,0xc2,0x8d,0xfe,0xc2,0x92,0x35,0xfd,0xdf,0xc4,0x93, + 0xfe,0xe3,0xcd,0xa3,0xff,0xc4,0x95,0x3b,0xfc,0xc0,0x8f,0x32,0xf5,0xcd,0xa8,0x61, + 0xf5,0xee,0xe3,0xcc,0xfd,0xef,0xe3,0xcb,0xfc,0xc2,0x94,0x3e,0xf0,0xc2,0x93,0x3d, + 0xed,0xc4,0x97,0x40,0xf7,0xf5,0xed,0xdf,0xfe,0xe5,0xcf,0xa7,0xff,0xfb,0xf8,0xf1, + 0xff,0xdd,0xc2,0x8e,0xfe,0xc3,0x94,0x39,0xf8,0xbd,0x8e,0x3b,0xd8,0xa8,0x78,0x32, + 0xa1,0x8d,0x59,0x27,0x79,0x7f,0x49,0x20,0x6a,0x7d,0x47,0x20,0x68,0x6e,0x3b,0x1a, + 0x67,0x6f,0x3c,0x1b,0x69,0x81,0x50,0x22,0x79,0xa3,0x73,0x30,0xa7,0xb7,0x89,0x38, + 0xdb,0xc5,0x9c,0x50,0xf6,0xed,0xe0,0xc7,0xfe,0xff,0xff,0xff,0xfe,0xfe,0xfe,0xfe, + 0xff,0xfc,0xfa,0xf7,0xff,0xc7,0x9e,0x51,0xfa,0xbf,0x91,0x3b,0xf5,0xc2,0x97,0x43, + 0xfa,0xfb,0xf8,0xf3,0xff,0xbc,0x8e,0x34,0xf7,0xba,0x8c,0x3a,0xe1,0xb7,0x89,0x39, + 0xd8,0xbc,0x8d,0x37,0xeb,0xdd,0xc4,0x96,0xfc,0xf1,0xe7,0xd5,0xfe,0xbd,0x8f,0x35, + 0xfb,0xc0,0x92,0x3c,0xfd,0xe0,0xc9,0x9e,0xfe,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe, + 0xff,0xf0,0xe5,0xd1,0xff,0xc6,0x9c,0x4c,0xfb,0xbc,0x8e,0x3b,0xe8,0xaf,0x80,0x35, + 0xbf,0x99,0x69,0x2c,0x93,0x7f,0x4c,0x22,0x74,0x72,0x3e,0x1c,0x68,0x65,0x33,0x17, + 0x67,0x67,0x36,0x18,0x69,0x86,0x55,0x24,0x86,0xaa,0x7d,0x33,0xc4,0xd3,0xb8,0x85, + 0xf4,0xff,0xff,0xff,0xff,0xda,0xc2,0x94,0xff,0xcb,0xa8,0x66,0xff,0xc5,0x9f,0x55, + 0xff,0xbc,0x8f,0x39,0xfc,0xb8,0x8b,0x38,0xee,0xb4,0x87,0x38,0xdd,0xb9,0x8c,0x3a, + 0xed,0xf4,0xec,0xde,0xfe,0xd7,0xbd,0x8b,0xfa,0xb3,0x86,0x34,0xe0,0xae,0x81,0x35, + 0xcd,0xb4,0x87,0x37,0xdf,0xba,0x8c,0x37,0xf7,0xfb,0xf9,0xf6,0xff,0xd0,0xaf,0x72, + 0xfe,0xbd,0x90,0x3b,0xff,0xc2,0x98,0x48,0xff,0xff,0xff,0xff,0xff,0xcb,0xa8,0x64, + 0xff,0xd8,0xbe,0x8d,0xfe,0xfa,0xf7,0xf2,0xff,0xec,0xdf,0xc7,0xfc,0xbc,0x92,0x46, + 0xeb,0xaa,0x7c,0x32,0xc3,0x8c,0x5c,0x27,0x8b,0x67,0x36,0x18,0x68,0x61,0x30,0x15, + 0x67,0x64,0x33,0x17,0x6a,0x86,0x57,0x24,0x8a,0xaa,0x7d,0x33,0xcb,0xe5,0xd5,0xb8, + 0xf9,0xf3,0xeb,0xdd,0xff,0xbc,0x91,0x3e,0xff,0xbb,0x8d,0x39,0xff,0xba,0x8c,0x36, + 0xff,0xd0,0xb2,0x78,0xfc,0xb5,0x89,0x39,0xe7,0xab,0x7e,0x34,0xcb,0xb2,0x85,0x36, + 0xdf,0xde,0xca,0xa4,0xfb,0xfb,0xf7,0xf1,0xfe,0xbd,0x93,0x46,0xf4,0xb6,0x8b,0x3d, + 0xe9,0xb9,0x8d,0x3d,0xef,0xc1,0x99,0x4d,0xfb,0xfd,0xfc,0xfa,0xff,0xd0,0xb2,0x78, + 0xfe,0xbb,0x8e,0x3b,0xfe,0xbc,0x90,0x3b,0xfe,0xed,0xe2,0xcd,0xff,0xe2,0xd0,0xab, + 0xff,0xb8,0x8a,0x32,0xff,0xb8,0x89,0x2f,0xff,0xeb,0xdf,0xc6,0xfe,0xfe,0xfd,0xfc, + 0xff,0xb6,0x8a,0x3f,0xe0,0x96,0x68,0x2b,0xa0,0x63,0x32,0x16,0x68,0x5d,0x2d,0x14, + 0x67,0x5f,0x2f,0x15,0x69,0x79,0x4b,0x1f,0x7f,0x9f,0x72,0x2f,0xb5,0xb7,0x8d,0x42, + 0xe6,0xe7,0xd7,0xbb,0xfc,0xfb,0xf8,0xf3,0xff,0xf0,0xe6,0xd4,0xff,0xf0,0xe6,0xd3, + 0xff,0xf7,0xf2,0xe9,0xfe,0xb4,0x89,0x3d,0xe3,0xa4,0x77,0x31,0xbe,0xab,0x7e,0x34, + 0xcf,0xd1,0xb6,0x85,0xf5,0xff,0xff,0xff,0xff,0xfb,0xf9,0xf5,0xff,0xf7,0xf1,0xe8, + 0xfe,0xf7,0xf2,0xe9,0xff,0xf8,0xf3,0xeb,0xff,0xd5,0xbb,0x8b,0xf9,0xb6,0x8a,0x39, + 0xf1,0xb8,0x8c,0x3b,0xf4,0xed,0xe2,0xcd,0xfe,0xfe,0xfe,0xfd,0xff,0xff,0xff,0xff, + 0xff,0xef,0xe5,0xd3,0xff,0xf1,0xe8,0xd7,0xff,0xfb,0xf9,0xf4,0xff,0xf6,0xf1,0xe8, + 0xfe,0xb4,0x89,0x3f,0xdf,0x94,0x65,0x29,0x9e,0x60,0x2f,0x15,0x68,0x5a,0x2b,0x12, + 0x67,0x5a,0x2a,0x12,0x68,0x66,0x36,0x17,0x70,0x84,0x56,0x24,0x8c,0x9f,0x72,0x2f, + 0xb9,0xaa,0x7c,0x2c,0xd9,0xb6,0x8c,0x41,0xea,0xce,0xb1,0x7e,0xf4,0xdd,0xcb,0xa9, + 0xf7,0xc2,0xa0,0x63,0xec,0xa6,0x7a,0x31,0xc8,0x91,0x63,0x2a,0x9f,0x98,0x6b,0x2c, + 0xaa,0xa8,0x7a,0x2c,0xd3,0xbd,0x98,0x55,0xec,0xb9,0x90,0x47,0xed,0xbe,0x99,0x55, + 0xed,0xb8,0x8f,0x46,0xea,0xab,0x7c,0x28,0xe2,0xa8,0x7c,0x2f,0xd1,0xa4,0x77,0x31, + 0xc1,0xa8,0x7c,0x33,0xcc,0xaf,0x81,0x31,0xe3,0xca,0xab,0x73,0xf2,0xda,0xc5,0x9e, + 0xf6,0xdd,0xcb,0xa7,0xf8,0xd7,0xc0,0x95,0xf6,0xc4,0xa1,0x63,0xf0,0xab,0x7c,0x29, + 0xe0,0xa2,0x75,0x30,0xbc,0x80,0x52,0x22,0x89,0x5b,0x2b,0x13,0x68,0x57,0x28,0x11, + 0x67,0x57,0x28,0x12,0x68,0x59,0x29,0x12,0x69,0x63,0x34,0x16,0x71,0x78,0x4a,0x1e, + 0x83,0x8c,0x5f,0x27,0x9b,0x99,0x6c,0x2c,0xb0,0x9f,0x72,0x2e,0xbd,0xa1,0x74,0x2e, + 0xc1,0x9c,0x6f,0x2c,0xb6,0x8a,0x5c,0x26,0x97,0x70,0x41,0x1b,0x7b,0x74,0x46,0x1d, + 0x7f,0x8c,0x5e,0x26,0x9a,0x99,0x6c,0x2c,0xaf,0x9a,0x6d,0x2d,0xb3,0x98,0x6c,0x2b, + 0xb0,0x97,0x6a,0x2b,0xac,0x91,0x64,0x29,0xa2,0x85,0x57,0x24,0x90,0x7a,0x4c,0x1f, + 0x84,0x83,0x55,0x24,0x8f,0x95,0x68,0x2b,0xa8,0x9f,0x72,0x2d,0xba,0xa2,0x75,0x2f, + 0xc2,0xa3,0x76,0x2f,0xc4,0xa1,0x74,0x2e,0xc1,0x9d,0x70,0x2d,0xb7,0x92,0x66,0x29, + 0xa4,0x7e,0x51,0x21,0x88,0x65,0x36,0x17,0x71,0x58,0x29,0x12,0x67,0x54,0x25,0x10, + 0x68,0x54,0x25,0x10,0x68,0x54,0x25,0x10,0x68,0x54,0x25,0x10,0x68,0x59,0x2a,0x12, + 0x6b,0x64,0x36,0x17,0x74,0x72,0x44,0x1d,0x7f,0x7b,0x4e,0x20,0x89,0x7d,0x50,0x21, + 0x8b,0x76,0x48,0x1e,0x83,0x67,0x39,0x17,0x75,0x5c,0x2d,0x13,0x6d,0x5e,0x2f,0x14, + 0x6f,0x67,0x39,0x18,0x76,0x6e,0x40,0x1b,0x7b,0x6f,0x41,0x1b,0x7d,0x6f,0x41,0x1b, + 0x7c,0x6c,0x3e,0x1a,0x7a,0x65,0x37,0x17,0x74,0x5c,0x2e,0x14,0x6e,0x59,0x2a,0x12, + 0x6b,0x5d,0x2f,0x13,0x6e,0x68,0x3a,0x18,0x76,0x71,0x43,0x1c,0x7e,0x76,0x48,0x1e, + 0x83,0x77,0x49,0x1e,0x84,0x75,0x47,0x1d,0x82,0x6f,0x41,0x1b,0x7c,0x66,0x37,0x17, + 0x75,0x5c,0x2d,0x13,0x6d,0x56,0x27,0x11,0x69,0x55,0x26,0x10,0x68,0x51,0x23,0xf, + 0x68,0x51,0x22,0xf,0x68,0x51,0x23,0xf,0x68,0x51,0x23,0xf,0x67,0x55,0x27,0x11, + 0x6b,0x6b,0x3d,0x19,0x7b,0x83,0x56,0x24,0x95,0x8e,0x61,0x28,0xa4,0x8d,0x61,0x28, + 0xa3,0x84,0x57,0x24,0x96,0x76,0x49,0x1e,0x86,0x72,0x45,0x1d,0x82,0x7b,0x4e,0x20, + 0x8b,0x7c,0x4f,0x20,0x8c,0x75,0x48,0x1e,0x85,0x78,0x4b,0x1e,0x88,0x7f,0x52,0x22, + 0x90,0x78,0x4b,0x1f,0x88,0x62,0x34,0x16,0x74,0x54,0x25,0x10,0x6a,0x51,0x22,0xe, + 0x67,0x52,0x23,0x10,0x69,0x52,0x23,0x10,0x69,0x54,0x25,0x10,0x6a,0x55,0x26,0x10, + 0x6b,0x55,0x26,0x11,0x6b,0x54,0x26,0x10,0x6a,0x53,0x24,0x10,0x6a,0x52,0x24,0x10, + 0x69,0x52,0x23,0x10,0x68,0x52,0x23,0xf,0x68,0x52,0x23,0x10,0x67,0x4e,0x1f,0xd, + 0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xd,0x67,0x4e,0x20,0xe,0x68,0x5d,0x30,0x13, + 0x73,0x86,0x59,0x24,0x9b,0xa2,0x76,0x2d,0xce,0xaa,0x81,0x3c,0xe3,0xaa,0x7e,0x33, + 0xe2,0xa5,0x79,0x2d,0xd6,0x9e,0x73,0x2e,0xc5,0x9d,0x71,0x2e,0xc1,0xa1,0x76,0x2c, + 0xcd,0xa2,0x75,0x2c,0xcd,0x9e,0x72,0x2e,0xc3,0x9f,0x73,0x2f,0xc6,0xa3,0x76,0x2d, + 0xd0,0x9a,0x6e,0x2d,0xbc,0x78,0x4c,0x1f,0x8b,0x55,0x28,0x11,0x6d,0x4e,0x1f,0xe, + 0x68,0x4d,0x1f,0xd,0x67,0x4e,0x20,0xe,0x67,0x4e,0x1f,0xe,0x67,0x4e,0x20,0xe, + 0x68,0x4e,0x20,0xe,0x68,0x4e,0x20,0xd,0x68,0x4e,0x20,0xe,0x67,0x4f,0x20,0xe, + 0x67,0x4e,0x21,0xe,0x67,0x4f,0x20,0xe,0x68,0x4e,0x20,0xe,0x68,0x49,0x1c,0xc, + 0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc,0x67,0x4b,0x1e,0xc,0x69,0x61,0x34,0x16, + 0x78,0x91,0x65,0x29,0xaf,0xac,0x88,0x50,0xeb,0xb5,0xa4,0xa1,0xff,0xb5,0x9e,0x8f, + 0xff,0xb3,0x98,0x79,0xfc,0xae,0x86,0x3d,0xf4,0xae,0x83,0x33,0xf2,0xb1,0x94,0x6a, + 0xf9,0xb2,0x96,0x75,0xfb,0xae,0x84,0x36,0xf3,0xae,0x83,0x32,0xf3,0xb2,0x94,0x6d, + 0xfa,0xa7,0x7e,0x38,0xdd,0x84,0x59,0x24,0x9c,0x57,0x2a,0x11,0x71,0x4b,0x1d,0xc, + 0x68,0x4a,0x1d,0xc,0x68,0x4a,0x1d,0xc,0x68,0x4a,0x1d,0xc,0x68,0x4b,0x1d,0xc, + 0x68,0x4b,0x1d,0xc,0x68,0x4a,0x1d,0xc,0x68,0x4a,0x1d,0xc,0x68,0x4a,0x1d,0xc, + 0x68,0x4b,0x1d,0xc,0x68,0x4a,0x1d,0xc,0x68,0x4b,0x1d,0xc,0x68,0x46,0x1a,0xb, + 0x68,0x46,0x19,0xb,0x68,0x46,0x1a,0xb,0x67,0x47,0x1b,0xb,0x69,0x5b,0x2e,0x13, + 0x76,0x89,0x5e,0x26,0xa7,0xa7,0x7d,0x34,0xe3,0xb2,0x9b,0x86,0xfe,0xb0,0x89,0x42, + 0xff,0xb0,0x87,0x39,0xff,0xb1,0x8c,0x4e,0xff,0xb0,0x87,0x3a,0xfe,0xb3,0xa2,0x9d, + 0xff,0xb1,0x90,0x5c,0xff,0xb2,0x9d,0x8d,0xfe,0xb0,0x85,0x35,0xfe,0xb2,0x9a,0x84, + 0xfe,0xa8,0x7e,0x38,0xe4,0x87,0x5b,0x25,0xa3,0x57,0x2a,0x11,0x73,0x48,0x1a,0xb, + 0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb, + 0x68,0x47,0x1b,0xb,0x68,0x47,0x1a,0xb,0x68,0x47,0x1b,0xb,0x68,0x47,0x1b,0xb, + 0x68,0x47,0x1a,0xb,0x68,0x48,0x1a,0xb,0x68,0x48,0x1b,0xb,0x68,0x43,0x17,0x9, + 0x68,0x43,0x17,0x9,0x68,0x43,0x17,0x9,0x67,0x44,0x17,0x9,0x68,0x4c,0x20,0xd, + 0x6d,0x71,0x46,0x1c,0x8b,0x97,0x6c,0x2c,0xc1,0xa9,0x7f,0x37,0xeb,0xb1,0x9b,0x8d, + 0xfd,0xaf,0x8c,0x54,0xff,0xaf,0x86,0x3a,0xff,0xaf,0x83,0x31,0xff,0xb1,0x9d,0x91, + 0xff,0xb0,0x8b,0x4d,0xfe,0xaf,0x8b,0x4e,0xfe,0xb1,0x9b,0x87,0xff,0xb1,0x9a,0x84, + 0xfe,0xa7,0x7e,0x39,0xe7,0x87,0x5d,0x26,0xa7,0x55,0x29,0x11,0x73,0x44,0x18,0x9, + 0x69,0x44,0x18,0xa,0x67,0x44,0x18,0xa,0x68,0x44,0x17,0x9,0x68,0x44,0x17,0x9, + 0x68,0x44,0x18,0xa,0x68,0x44,0x17,0xa,0x68,0x44,0x18,0xa,0x68,0x44,0x18,0xa, + 0x68,0x44,0x18,0xa,0x68,0x44,0x17,0x9,0x68,0x44,0x18,0xa,0x68,0x40,0x14,0x8, + 0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x8,0x68,0x40,0x15,0x9,0x67,0x41,0x16,0x8, + 0x69,0x51,0x26,0xf,0x73,0x75,0x4a,0x1e,0x92,0x95,0x6a,0x2a,0xc0,0xa5,0x7c,0x35, + 0xe6,0xad,0x8e,0x61,0xf8,0xb0,0x9a,0x89,0xff,0xad,0x88,0x48,0xfc,0xad,0x87,0x47, + 0xfb,0xaf,0x92,0x6c,0xfc,0xab,0x81,0x33,0xf7,0xac,0x89,0x4f,0xf9,0xb0,0x9e,0x96, + 0xff,0xa5,0x7c,0x39,0xe3,0x85,0x5a,0x24,0xa5,0x52,0x27,0xf,0x73,0x41,0x15,0x9, + 0x69,0x41,0x15,0x9,0x67,0x41,0x15,0x9,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9, + 0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9, + 0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9,0x68,0x3d,0x11,0x7, + 0x68,0x3d,0x12,0x7,0x68,0x3d,0x11,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x7, + 0x68,0x3f,0x14,0x8,0x69,0x4d,0x22,0xd,0x72,0x6d,0x42,0x1a,0x8c,0x8b,0x60,0x27, + 0xb1,0x9a,0x6f,0x2a,0xce,0x9e,0x73,0x28,0xda,0x9f,0x74,0x2d,0xda,0x9f,0x74,0x2f, + 0xd9,0x9e,0x72,0x2a,0xd6,0x9b,0x71,0x2e,0xd0,0x9d,0x72,0x2d,0xd4,0x9e,0x73,0x28, + 0xd9,0x95,0x6a,0x2b,0xc4,0x72,0x48,0x1c,0x92,0x48,0x1d,0xc,0x6e,0x3d,0x12,0x7, + 0x68,0x3d,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3d,0x12,0x7,0x68,0x3e,0x12,0x7, + 0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x7, + 0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x39,0xf,0x6, + 0x68,0x3a,0xf,0x6,0x68,0x3a,0xf,0x6,0x68,0x3a,0xf,0x6,0x68,0x39,0xf,0x6, + 0x67,0x3a,0xf,0x6,0x68,0x3b,0x10,0x6,0x69,0x45,0x1a,0xa,0x6f,0x59,0x2e,0x12, + 0x7c,0x6c,0x42,0x1a,0x8e,0x76,0x4c,0x1e,0x98,0x75,0x4a,0x1d,0x97,0x73,0x49,0x1d, + 0x96,0x72,0x48,0x1d,0x94,0x6d,0x43,0x1b,0x8e,0x71,0x46,0x1c,0x92,0x76,0x4c,0x1e, + 0x99,0x6b,0x41,0x1a,0x8c,0x50,0x25,0xf,0x76,0x3c,0x12,0x7,0x6a,0x3a,0x10,0x6, + 0x67,0x3b,0xf,0x6,0x68,0x3a,0x10,0x6,0x68,0x3a,0xf,0x6,0x68,0x3a,0x10,0x6, + 0x68,0x3a,0x10,0x5,0x68,0x3a,0x10,0x6,0x68,0x3a,0x10,0x6,0x68,0x3b,0x10,0x6, + 0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x6,0x68,0x3a,0x10,0x6,0x68,0x35,0xc,0x4, + 0x68,0x37,0xc,0x4,0x68,0x36,0xc,0x4,0x68,0x35,0xc,0x4,0x68,0x36,0xc,0x4, + 0x68,0x36,0xd,0x5,0x67,0x36,0xb,0x4,0x67,0x36,0xc,0x4,0x68,0x3a,0xf,0x5, + 0x6a,0x3e,0x14,0x7,0x6d,0x42,0x18,0x9,0x6f,0x42,0x18,0x9,0x6f,0x41,0x17,0x9, + 0x6f,0x40,0x16,0x9,0x6e,0x3f,0x15,0x7,0x6d,0x41,0x17,0x8,0x6e,0x44,0x19,0xa, + 0x6f,0x3f,0x15,0x8,0x6d,0x39,0xf,0x5,0x6a,0x36,0xc,0x5,0x68,0x37,0xd,0x4, + 0x67,0x36,0xd,0x5,0x68,0x37,0xd,0x4,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5, + 0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x4, + 0x68,0x37,0xc,0x5,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x32,0x9,0x3, + 0x68,0x32,0x9,0x2,0x68,0x32,0xa,0x2,0x68,0x32,0x8,0x2,0x68,0x33,0xa,0x4, + 0x68,0x32,0x9,0x2,0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3,0x67,0x33,0x9,0x3, + 0x67,0x33,0x9,0x4,0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3, + 0x68,0x33,0x9,0x3,0x69,0x32,0x9,0x4,0x67,0x33,0x9,0x3,0x68,0x33,0xa,0x3, + 0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x4,0x67,0x33,0x9,0x2,0x67,0x33,0x9,0x4, + 0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3, + 0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3,0x68,0x33,0xa,0x3,0x68,0x33,0x9,0x3, + 0x68,0x33,0xb,0x3,0x68,0x33,0x9,0x3,0x68,0x33,0xa,0x3,0x68,0x2f,0x6,0x2, + 0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2, + 0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2, + 0x68,0x2f,0x6,0x2,0x67,0x30,0x6,0x2,0x67,0x30,0x6,0x2,0x67,0x2f,0x7,0x2, + 0x67,0x30,0x6,0x2,0x67,0x2f,0x6,0x2,0x68,0x30,0x7,0x2,0x67,0x30,0x7,0x2, + 0x67,0x30,0x7,0x2,0x67,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2, + 0x68,0x30,0x6,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2, + 0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2, + 0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x2c,0x3,0x0, + 0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0, + 0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x0, + 0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x1, + 0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0, + 0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2d,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2c,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2d,0x4,0x1,0x68,0x2d,0x4,0x1,0x68,0x2d,0x4,0x1,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x3,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x3,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2b,0x2,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2b,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf9,0xe7,0xc0,0x60,0xf0,0x83,0xc0,0x0,0x20, + 0x3,0xc0,0x0,0x0,0x3,0xc0,0x0,0x0,0x3,0xe0,0x0,0x0,0x7,0xe0,0x0,0x0, + 0x3,0xc0,0x0,0x0,0x1,0xc0,0x0,0x0,0x1,0xe0,0x0,0x0,0x1,0xe0,0x0,0x0, + 0x1,0xf0,0x18,0x0,0x3,0xfe,0x3f,0xff,0x1f,0xfc,0x0,0x3f,0xff,0xf8,0x0,0x1f, + 0xff,0xf8,0x0,0x1f,0xff,0xf8,0x0,0x1f,0xff,0xf8,0x0,0x1f,0xff,0xfc,0x0,0x1f, + 0xff,0xfe,0x0,0x1f,0xff,0xff,0x80,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/rightMiddle.png + 0x0,0x0,0x0,0x85, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b, + 0x0,0x0,0x0,0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5, + 0x0,0x0,0x0,0x3c,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0x8c,0x8c,0x4f,0xf9,0xcf, + 0x0,0x4,0x8f,0xef,0xde,0x0,0x51,0x60,0xf0,0x9f,0x95,0x9b,0x41,0x4e,0x4e,0x96, + 0x61,0xf9,0xc2,0x39,0xc,0xc,0x36,0x36,0x36,0xff,0xd1,0xb1,0xb5,0xa3,0xfb,0x7f, + 0xa8,0xc6,0xff,0x43,0x43,0x1,0xc8,0xb5,0x20,0x8c,0xec,0x13,0x64,0x5f,0x0,0x0, + 0xf5,0xa6,0x66,0x4e,0x97,0x59,0xa6,0xcb,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44, + 0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/rightTop.png + 0x0,0x0,0x0,0xa6, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x3b,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0x8c,0x8c,0x4f, + 0xf9,0xcf,0x80,0x3,0x2c,0x5f,0x38,0x87,0x81,0xe5,0xd1,0xa3,0x87,0xc,0x8c,0xbf, + 0xbf,0x63,0x28,0x91,0x55,0xd6,0x0,0x8b,0x31,0x61,0xd3,0xfc,0x9f,0x95,0x1b,0x2e, + 0x8c,0x55,0x1,0xb2,0x26,0x7a,0x28,0x90,0x93,0x93,0x67,0x80,0xb9,0x18,0x9b,0x83, + 0x1,0x23,0x52,0xa,0xe3,0xad,0xa9,0x9f,0x7c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e, + 0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/minimize_high.png + 0x0,0x0,0x1,0xd3, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x68,0x49,0x44,0x41,0x54,0x38,0x4f,0x63,0x2c,0x2e,0x2e, + 0xf9,0x6f,0x6a,0x6a,0xc2,0xf0,0xf2,0xe5,0x4b,0x6,0x62,0x81,0xb8,0xb8,0x38,0xc3, + 0xe9,0xd3,0x67,0x18,0x18,0x77,0xef,0xde,0xfd,0x5f,0x4a,0x4a,0x8a,0xe1,0xd3,0xa7, + 0x4f,0xc,0xff,0xfe,0xfd,0x63,0xf8,0xf5,0xeb,0x17,0xd8,0x8c,0x9f,0x3f,0x7f,0x32, + 0xfc,0xf9,0xf3,0x7,0xce,0x6,0x31,0xfe,0xfe,0xfd,0xb,0x56,0xc3,0xc4,0xc4,0x4, + 0x66,0x33,0x2e,0x5b,0xbe,0xfc,0xff,0xdd,0xbb,0x77,0x89,0xb5,0x14,0xac,0x8e,0x83, + 0x83,0x83,0x81,0x99,0x85,0x85,0x81,0x11,0xe4,0x6c,0x92,0x74,0x22,0x29,0x66,0x79, + 0xf7,0xfe,0x23,0x56,0xbd,0x7e,0xbe,0x5e,0xc,0x1,0x1,0x1,0x18,0x72,0x1b,0x36, + 0x6c,0x60,0xd8,0xb4,0x79,0x1b,0x58,0x9c,0x31,0x30,0x28,0x18,0xab,0xcd,0x8e,0xee, + 0xde,0x40,0xff,0xff,0xc4,0xd0,0x5c,0x9c,0x93,0xc1,0x10,0x14,0x1c,0x2,0xd1,0xac, + 0xaa,0xae,0xfd,0x5f,0x46,0x46,0x6,0xcc,0x9,0xb,0xd,0x64,0xc8,0x48,0x4f,0xc7, + 0xd0,0x30,0x79,0xf2,0x14,0x86,0x1d,0x3b,0x76,0x80,0xc5,0x57,0xac,0x58,0xce,0xe0, + 0x1f,0x18,0xca,0xf0,0xe4,0xc9,0x13,0x6,0x46,0x19,0x5,0x25,0xb8,0xcd,0xd7,0x2e, + 0x5d,0xc0,0xe9,0x7d,0x90,0x6,0x10,0xd8,0xb8,0x7e,0x35,0x83,0x96,0x9e,0x1,0x98, + 0xcd,0xc4,0xca,0xc6,0xc1,0x0,0xc3,0x20,0x1,0x15,0xd,0x2d,0xc,0xc,0x12,0xbf, + 0x7d,0xf7,0x36,0x18,0x83,0x0,0x4c,0x3d,0x13,0x1b,0x1b,0x1b,0x3,0xc,0x83,0x24, + 0xb8,0x79,0xf8,0x30,0x30,0xb2,0x38,0x88,0xd,0x53,0xcf,0x84,0xd3,0x9d,0x68,0x12, + 0xa7,0x8f,0x1d,0x62,0x0,0xe1,0xfa,0xc6,0x16,0xb8,0xc,0x5c,0x33,0xb,0x2b,0x1b, + 0x58,0x10,0xd9,0x25,0xc8,0x2e,0x32,0xb5,0xb2,0x63,0xd0,0x33,0x32,0x61,0xd8,0xbc, + 0x65,0x2b,0x3,0x48,0xad,0xb0,0x90,0x30,0x3,0xb,0xcc,0x98,0x3f,0xc0,0x64,0xd9, + 0xda,0xde,0x5,0x36,0x1d,0x1d,0x80,0xc4,0x41,0x1a,0x60,0x16,0xf0,0x70,0x71,0x32, + 0xbc,0x7d,0xf7,0x16,0x92,0xc2,0xb6,0xec,0xdc,0x43,0xac,0xeb,0xe1,0xea,0x7c,0xdc, + 0x5d,0x18,0x18,0xd5,0x75,0xc,0xfe,0x83,0x18,0xa4,0x2,0x90,0x85,0x0,0x1,0x1a, + 0x7c,0xb9,0xe4,0x54,0xe5,0xc5,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42, + 0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/leftBottom.png + 0x0,0x0,0x0,0xc1, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x18,0x8,0x6,0x0,0x0,0x0,0xc7,0xd9,0xbc,0x10, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x56,0x49,0x44,0x41,0x54,0x38,0x4f,0x63,0x64,0x60,0x60, + 0xf8,0x1f,0x19,0x9f,0xc2,0xf0,0xf8,0xee,0xd,0x20,0x13,0x1,0x64,0x95,0x35,0xc0, + 0x1c,0x26,0x14,0x51,0x24,0xe,0x48,0xc3,0xa3,0x47,0xf,0x11,0xa,0xfe,0xb3,0x72, + 0x63,0x55,0xb,0x37,0x81,0xf1,0xf7,0x57,0xc,0x5,0x8c,0xbf,0xbf,0xe3,0xb6,0x2, + 0xa6,0x1a,0xa7,0x1b,0x46,0x15,0xa0,0x6,0xe8,0xd0,0xa,0x28,0x6c,0x9,0xe6,0x3f, + 0x2b,0x27,0x3d,0xd2,0x3,0x23,0x2c,0xd9,0xe3,0x4a,0xdd,0x0,0x7f,0x48,0x13,0xb1, + 0xf0,0xa0,0x37,0xcd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/left.png + 0x0,0x0,0x0,0xb8, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x15,0x8,0x6,0x0,0x0,0x0,0x7b,0x47,0xaf,0xce, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x4d,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0x64,0x60,0x60, + 0xf8,0x1f,0x19,0x9f,0xc2,0xf0,0xe8,0xd1,0x63,0x6,0xc6,0xdf,0x5f,0x81,0x5c,0x8, + 0x90,0x55,0xd6,0x0,0x8a,0x3d,0x64,0x60,0x82,0x9,0x20,0x4b,0xc2,0x55,0x1,0x19, + 0x70,0x5,0xff,0x59,0xb9,0x91,0xc5,0xe1,0x6c,0xb8,0x2,0xac,0xb2,0xc8,0x26,0xc, + 0x9,0x5,0x4,0xc3,0x81,0x72,0x5f,0xc,0x89,0x90,0xa4,0x3c,0x1c,0x8,0x7a,0x13, + 0x97,0x15,0x0,0xf3,0x59,0x14,0xdb,0x97,0xdb,0x26,0x3d,0x0,0x0,0x0,0x0,0x49, + 0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/hide.png + 0x0,0x0,0x1,0xb3, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x48,0x49,0x44,0x41,0x54,0x38,0x4f,0x95,0x52,0x41,0x4b, + 0x2,0x41,0x18,0x7d,0x33,0xda,0xba,0x9d,0x2a,0x10,0x4,0xe9,0x50,0x2e,0x18,0x2b, + 0x1d,0x3a,0x75,0xd1,0x5f,0x90,0x18,0x54,0xbf,0x43,0x8,0xec,0x10,0x44,0x6c,0x10, + 0x41,0xc7,0xc0,0xff,0x90,0xf7,0x3c,0x7a,0xd5,0x4b,0x3f,0xa0,0x2d,0x73,0xbd,0x7b, + 0xd1,0x75,0x2f,0xb9,0x8b,0xb3,0xdb,0xce,0xc0,0x6c,0x81,0x8d,0xda,0x83,0x7,0x6f, + 0xf7,0xfb,0xde,0xf7,0xe6,0x9b,0x5d,0x62,0x59,0x56,0x64,0x9a,0x26,0x46,0xa3,0x11, + 0xd6,0x45,0x2e,0x97,0x83,0x6d,0xdb,0x20,0x9d,0x4e,0x27,0xca,0xe7,0xf3,0xf0,0x3c, + 0xf,0x61,0x18,0x22,0x8,0x2,0x31,0xc3,0xf7,0x7d,0xcc,0xe7,0xf3,0x44,0x73,0xc1, + 0x18,0x13,0x3d,0x94,0x52,0xa1,0xc9,0x73,0xab,0x15,0x39,0x8e,0xb3,0x6e,0xa8,0xe8, + 0xd3,0x75,0x1d,0xa9,0x74,0x1a,0xa4,0xd1,0xb8,0x8a,0xa4,0xb3,0x52,0x29,0xc3,0x3c, + 0x2e,0x2b,0x7,0xd9,0xaf,0x3d,0x74,0xbb,0xbd,0xa4,0x4e,0xc7,0x93,0x29,0x7e,0xe8, + 0x62,0xe6,0x7,0x4a,0x8e,0x27,0xee,0xaf,0xde,0x29,0xc8,0xd9,0xf9,0x45,0x92,0xfc, + 0x35,0x9b,0xc1,0x8f,0x29,0x51,0xab,0x9d,0xa2,0xdd,0x7e,0x49,0x9e,0x33,0xf1,0x71, + 0x37,0x63,0x4a,0xa4,0x58,0x48,0xef,0xb4,0x8c,0x2e,0xd2,0x18,0xb,0x1,0x42,0x5, + 0xab,0xd5,0x13,0x14,0xc,0x3,0xd9,0x6c,0x16,0x9f,0x83,0xa1,0x78,0xc7,0xeb,0xf2, + 0x64,0x3,0x67,0x8,0xb2,0xbb,0x57,0x48,0x92,0xe5,0xc4,0xcb,0x7a,0x5d,0xc8,0xed, + 0x9d,0x2d,0xb8,0xf1,0x5a,0x1c,0x4f,0xcd,0xe6,0xc2,0x5d,0x90,0xfd,0x62,0x69,0xc1, + 0x2c,0xbb,0x6e,0x6f,0xae,0x71,0xff,0xf0,0xa8,0xbc,0x40,0xaa,0x69,0x1a,0x54,0xe4, + 0xae,0x65,0xf5,0x78,0x41,0x35,0x3e,0xde,0xfb,0x4b,0xbf,0xff,0x52,0xf3,0xaa,0x3f, + 0x87,0x1c,0x1c,0x1e,0x29,0x77,0x5e,0x65,0xa6,0xa5,0xa2,0x81,0xf4,0x86,0xf6,0x27, + 0x23,0x10,0x65,0x8d,0xfb,0x44,0x32,0x17,0xff,0xc5,0x5b,0xdf,0xc1,0x37,0x4b,0x2f, + 0x9a,0x4b,0x30,0xf6,0xb7,0xd4,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42, + 0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/right_arrow.png + 0x0,0x0,0x0,0xc5, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x2,0x0,0x0,0x0,0xb4,0xb4,0x2,0x1d, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x43,0x49,0x44,0x41, + 0x54,0x28,0x53,0x63,0x60,0x18,0xdc,0xe0,0xff,0xff,0xff,0x24,0x38,0x10,0xa8,0x9a, + 0x4,0xd,0x10,0xd5,0xc4,0x6a,0x80,0xab,0xc6,0xae,0x1,0x59,0x1a,0x93,0x8d,0xee, + 0x87,0x6,0x54,0x80,0xac,0x1,0x28,0x43,0xc0,0xc7,0x70,0xd5,0x84,0x95,0x2,0x4d, + 0x82,0xa8,0x26,0x4a,0x29,0x44,0x35,0xb1,0x4a,0x49,0x88,0x17,0x6a,0x2a,0x5,0x0, + 0x91,0xc9,0x67,0x27,0x3c,0x15,0x75,0xd8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44, + 0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/minimize.png + 0x0,0x0,0x1,0xf3, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x88,0x49,0x44,0x41,0x54,0x38,0x4f,0x95,0x52,0x4b,0x4b, + 0x2,0x51,0x18,0x3d,0x33,0x8e,0x93,0xf9,0xa8,0xa5,0x20,0xee,0x23,0x6a,0x21,0x94, + 0x15,0x84,0x64,0x51,0x48,0x51,0x41,0xb,0xa3,0xbd,0xb4,0xf,0xec,0x87,0xb4,0x69, + 0x15,0xb6,0xa8,0xe8,0xfd,0x0,0x93,0x30,0x8d,0x68,0xd3,0x46,0x5b,0x16,0x5,0x32, + 0xab,0xdc,0x18,0xa8,0xa3,0xf9,0x68,0xc6,0x51,0xf3,0x5e,0x73,0x90,0xc6,0x85,0x1e, + 0x38,0x70,0xe6,0xbb,0xe7,0x7c,0xdf,0xc7,0x9d,0xcb,0xf8,0xfd,0xdb,0x75,0xa7,0x73, + 0x1c,0xa9,0x54,0xa,0xdd,0xc2,0x6a,0xb5,0x22,0x1e,0x7f,0x1,0x13,0x8d,0x46,0xeb, + 0x36,0x9b,0xd,0xf9,0x7c,0x1e,0xb5,0x5a,0xd,0xb2,0x2c,0xd3,0x1e,0x92,0x24,0x41, + 0x51,0x14,0x55,0x13,0x51,0xad,0x56,0xa9,0x87,0x65,0x59,0xaa,0x99,0xe3,0x93,0x93, + 0xba,0x20,0x8,0xdd,0xe,0xa5,0x3e,0x83,0xc1,0x0,0x1d,0xc7,0x81,0x21,0x6b,0xf7, + 0x94,0x6c,0x33,0x73,0x99,0x6c,0xae,0x63,0x76,0x75,0x65,0x9,0xc3,0x13,0xd3,0x9a, + 0xb3,0xf7,0xd8,0x33,0x82,0xb7,0x77,0xb4,0xce,0x89,0x62,0xa6,0x63,0xf8,0xf3,0x2b, + 0xb,0xe1,0xfa,0x4a,0x73,0x36,0xeb,0x59,0x84,0x78,0x78,0xd4,0xc,0xbf,0xbe,0x7d, + 0xc0,0x6e,0xb7,0xd3,0x8f,0x75,0xef,0x1a,0xc6,0xdc,0xb,0x54,0xd7,0xfe,0x2e,0x8b, + 0xe8,0xd8,0x63,0x4,0xe1,0x70,0x98,0xd6,0xa7,0x66,0xdc,0x10,0x73,0x5,0x24,0x93, + 0x49,0xb0,0x65,0xa9,0x8c,0x84,0x90,0xa0,0x1c,0x99,0x74,0xa1,0x58,0x2c,0x51,0x96, + 0x25,0x59,0xa5,0xc3,0x35,0xd7,0xd0,0xa,0x65,0xa5,0xa2,0x50,0x2f,0xc9,0x71,0x7a, + 0xde,0xa0,0xae,0x96,0xfb,0xce,0xc3,0xb7,0xe1,0xd5,0xac,0x1a,0x38,0xbd,0xa0,0x1, + 0x82,0x42,0xb1,0x80,0x56,0x86,0xe5,0x79,0x1e,0x2d,0x32,0xc,0xb,0x93,0x79,0x40, + 0xc3,0xf6,0x7a,0x63,0x9a,0xea,0x67,0xbb,0xfd,0x4d,0x3b,0x7b,0x1,0x10,0x46,0x2e, + 0xcf,0xd4,0x8,0xd7,0x52,0xa4,0xa3,0x8e,0x65,0x68,0xd7,0xff,0x20,0xf5,0xad,0x4d, + 0x1f,0xa4,0x9f,0x12,0x38,0x9d,0x1e,0x7d,0x46,0x13,0x6,0x2d,0x16,0xa8,0x61,0xa5, + 0xf1,0x2c,0x9f,0x42,0x41,0xec,0xee,0x1f,0x68,0xc2,0xd1,0x9b,0x73,0x72,0x39,0x94, + 0x4,0x66,0x63,0x3f,0xd2,0x99,0x74,0xf3,0x85,0x85,0xee,0x1f,0xba,0xdd,0x5e,0xf5, + 0x2d,0x7b,0xe6,0xc1,0xc,0x8d,0x3a,0xea,0x44,0xf4,0xa,0x32,0xf0,0x17,0xe8,0x5a, + 0xa7,0x49,0x36,0x8e,0x3f,0xd9,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42, + 0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/close_high.png + 0x0,0x0,0x1,0xb7, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x4c,0x49,0x44,0x41,0x54,0x38,0x4f,0x63,0x3c,0x5b,0x3c, + 0xf3,0xbf,0x9c,0x9c,0x1c,0xc3,0xa3,0x47,0x8f,0x18,0x88,0x5,0x30,0xf5,0x8c,0xff, + 0x97,0xec,0xf9,0xcf,0xa0,0xad,0xc2,0xc0,0xf0,0xe7,0x17,0x50,0xef,0x3f,0x20,0xfd, + 0x13,0x62,0xc6,0x6f,0x20,0xfd,0xef,0x37,0x94,0xfd,0x3,0x42,0xff,0xfb,0x3,0xc4, + 0x20,0x35,0x5f,0x18,0xbe,0xdd,0xf8,0xcc,0xc0,0xf8,0x7f,0xf3,0xda,0xff,0xc,0x4f, + 0x6f,0x10,0x6b,0x29,0x44,0x1d,0x3b,0x37,0x3,0xc3,0xff,0x3f,0x40,0xcd,0x1d,0x59, + 0xff,0x49,0xd3,0x89,0x50,0xcd,0xf8,0xbf,0x24,0x10,0x55,0x73,0xf7,0x3a,0x6,0x86, + 0xd2,0x20,0x4c,0xf3,0xb0,0x88,0x33,0xfe,0x4f,0xb0,0x44,0xd1,0x7c,0xfd,0xe6,0x7b, + 0x6,0xcd,0x63,0xd7,0x51,0xd,0x0,0x6a,0xbc,0x6e,0xa5,0xc9,0xa0,0xa9,0x2e,0x88, + 0x62,0x28,0xe3,0x2b,0x3d,0x9e,0xff,0xc2,0xf2,0x92,0x28,0x82,0x37,0xdf,0x30,0x43, + 0xc,0x48,0xb4,0x62,0x60,0x98,0x7f,0xc,0xac,0x51,0x5d,0xe4,0x2f,0x8a,0x9a,0xb7, + 0xf,0x9f,0x33,0x30,0x3e,0x56,0x66,0xc1,0xf0,0xb3,0x94,0x96,0x22,0xc3,0xe5,0x87, + 0xdf,0x18,0xf4,0x2f,0x3e,0x61,0xb8,0xa8,0x2f,0xc3,0xa0,0x2b,0xcf,0xc5,0xf0,0xec, + 0xda,0x7d,0xc,0xaf,0x30,0x3e,0x55,0x67,0xc3,0xd0,0xfc,0xef,0xcf,0x3f,0x6,0x99, + 0x3b,0xbf,0x19,0x76,0x8,0xb0,0x30,0x78,0x7c,0xf8,0xc3,0xf0,0x44,0x85,0x95,0x81, + 0x89,0x85,0x9,0x43,0x33,0x13,0x33,0x33,0x13,0x3,0x3a,0x6,0x69,0xdc,0x25,0xc2, + 0xca,0xa0,0x27,0xc1,0xc,0xa6,0x41,0x7c,0x6c,0xea,0x30,0x8c,0x13,0xbf,0xfa,0x9d, + 0x61,0x9f,0x28,0x1b,0x83,0xbe,0x38,0xb,0x58,0x3,0x88,0x6,0xf1,0x41,0xe2,0xe8, + 0x0,0x43,0x33,0x48,0xa1,0xb6,0x18,0x33,0x8a,0x3a,0x10,0x1f,0x24,0x8e,0xe,0x18, + 0x5f,0x68,0x71,0x90,0x9d,0x48,0x98,0x32,0x35,0xbc,0x19,0x98,0x18,0x19,0x49,0xc6, + 0x20,0x7d,0x8c,0x40,0xa7,0xfc,0xf,0xc,0xa,0x26,0x39,0x85,0xae,0x5f,0xb7,0x96, + 0x1,0x0,0xbb,0x6c,0x75,0x2f,0x3f,0x1a,0x4c,0x30,0x0,0x0,0x0,0x0,0x49,0x45, + 0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/cusdr4.png + 0x0,0x0,0x7,0xfe, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x37,0x0,0x0,0x0,0x19,0x8,0x6,0x0,0x0,0x0,0x95,0x7d,0xb6,0x0, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0, + 0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1, + 0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0x8,0x1d, + 0xe,0x24,0xf,0x4d,0xe7,0x53,0xf2,0x0,0x0,0x7,0x7e,0x49,0x44,0x41,0x54,0x58, + 0xc3,0xed,0x97,0x5b,0x8c,0x5d,0x65,0x19,0x86,0x9f,0x77,0xad,0xb5,0xf,0x73,0xd8, + 0xb3,0x3b,0xb4,0x43,0x4f,0xd3,0x13,0xb6,0x85,0x82,0xd0,0x52,0x15,0xea,0x21,0x1a, + 0x4c,0xc4,0x8,0xd1,0xc4,0xa4,0x8d,0xa7,0xb,0x2f,0xbc,0x50,0x2f,0x24,0x41,0x23, + 0x1e,0xe2,0x5,0x6,0x4d,0x20,0xea,0x95,0xc4,0x60,0xb8,0x96,0x84,0x80,0x9,0x89, + 0x8a,0x31,0x62,0xd5,0xc4,0x3,0xd0,0x52,0x66,0xea,0x60,0xe9,0x71,0x9c,0xce,0xb4, + 0xd3,0xc3,0x1c,0x3a,0xb3,0xf7,0xcc,0x3e,0xad,0xb5,0x5e,0x2f,0xe6,0x1f,0x32,0x94, + 0x86,0xc4,0x4,0xb9,0xea,0x77,0xb5,0xb2,0xd6,0xff,0xff,0xf9,0xdf,0xef,0x7b,0xbf, + 0xf7,0x7b,0x17,0x5c,0x8f,0xeb,0x71,0x3d,0xde,0xcd,0xd0,0xff,0xeb,0xe0,0xfd,0x43, + 0x2d,0x1,0x92,0x84,0x6d,0x49,0x32,0xe0,0x67,0x76,0x17,0xbd,0x72,0x8d,0x24,0x1, + 0xb6,0xcd,0xd2,0x23,0xac,0x5c,0xb3,0xe2,0xac,0xe5,0xfb,0x46,0xcb,0x67,0x11,0x36, + 0x3e,0xbb,0xa7,0xe4,0x77,0x5,0xdc,0x81,0xe1,0x76,0x4,0x24,0xb6,0x4b,0x40,0x59, + 0x52,0x9,0x88,0x81,0xe,0xb0,0x60,0x7b,0x11,0xc8,0x80,0x38,0x7c,0x2b,0x6,0xf0, + 0x79,0xb8,0x70,0x66,0x3b,0x5,0x3a,0x1,0x44,0xc,0x94,0x81,0xb2,0xed,0x92,0xa4, + 0x38,0x24,0x22,0x3,0x5a,0x40,0x13,0x68,0xda,0xee,0x5c,0xd,0x52,0xef,0x30,0xb0, + 0x82,0xed,0xa,0xb0,0x56,0xd2,0x6,0xdb,0xeb,0x80,0x7e,0x49,0x5,0xa0,0x6,0x9c, + 0xb6,0x7d,0x52,0x52,0xd,0xe8,0xb7,0xbd,0x45,0xd2,0x8d,0xb6,0xe3,0x0,0x26,0xd, + 0x17,0x9d,0x5,0xa6,0x25,0x35,0x80,0xaa,0xed,0x41,0x60,0xbd,0xa4,0x55,0xb6,0x8b, + 0x81,0xd,0x6d,0x60,0x4e,0xd2,0x24,0x70,0x16,0x98,0xb4,0x5d,0x7f,0x76,0x4f,0x29, + 0x7b,0xc7,0xc1,0x1d,0x18,0x6e,0x17,0x6d,0xf,0x48,0xba,0xd,0x78,0x9f,0xed,0x5d, + 0x92,0xd6,0x3,0xd5,0x50,0xc9,0x79,0x49,0x47,0x6d,0xff,0x59,0xd2,0xa4,0xed,0x9d, + 0xc0,0x3e,0x49,0x5b,0x6d,0x27,0xa1,0x9a,0x29,0xd0,0x0,0x2e,0x49,0x1a,0xb5,0x3d, + 0x23,0x69,0x2d,0xb0,0xb,0xd8,0x6c,0xbb,0x22,0xa9,0x60,0x9b,0x90,0x8c,0x9a,0xed, + 0x9,0x49,0x43,0xb6,0xff,0x26,0xe9,0x75,0x60,0x7e,0x99,0xd6,0xc9,0xff,0x70,0x79, + 0x5d,0xdd,0xb,0xcb,0xef,0x81,0x8,0xa8,0x4a,0xda,0xd,0xdc,0x67,0x7b,0x5f,0x7f, + 0x41,0x9b,0xee,0xe9,0x57,0x75,0x77,0x25,0x2a,0xdc,0xd4,0xa5,0xe8,0x1f,0x73,0x79, + 0xfb,0x89,0x89,0xbc,0xf,0x68,0xd9,0xbe,0x0,0xec,0x95,0x74,0xd7,0x67,0xd6,0x68, + 0x63,0x33,0x57,0xd4,0x15,0xe1,0x1c,0x31,0xd6,0xc8,0xdb,0x47,0x17,0x98,0xb5,0x3d, + 0x5,0xcc,0x1,0xd5,0x4a,0xcc,0xc6,0x4f,0xad,0x89,0x6e,0xd8,0x5b,0x51,0x72,0x63, + 0x51,0x11,0x98,0xe9,0xe,0x3e,0xb6,0xe0,0xf4,0xf9,0xa9,0x7c,0xe6,0x42,0x9b,0xf5, + 0x40,0x1b,0x98,0xb2,0xbd,0x10,0x92,0xf4,0xf6,0xe0,0x56,0xf4,0x4f,0xd1,0x76,0xbc, + 0x7f,0xa8,0x85,0x24,0x87,0xcc,0xe5,0xcb,0x3d,0x61,0xbb,0x2c,0x69,0x33,0x70,0x57, + 0x4,0x1f,0xde,0xbf,0x2e,0xbe,0xf5,0xd3,0x6b,0x54,0x1c,0x6f,0xc1,0xb1,0x5,0x33, + 0xde,0xcc,0xf9,0x68,0x7f,0x5c,0x7c,0x69,0xce,0x83,0x47,0xe6,0xbd,0x35,0x50,0xf5, + 0xd6,0x87,0x6f,0x8a,0xb7,0xdd,0xda,0x1b,0xc5,0xd3,0x1d,0xbb,0x96,0xda,0xb9,0xe1, + 0xde,0xd5,0x49,0xa9,0x2f,0xa1,0xef,0xe9,0xb,0xd9,0x86,0xe7,0xa7,0xdd,0xb0,0x9d, + 0xdc,0xd3,0x1f,0x95,0xef,0x5b,0x13,0x45,0x5d,0x11,0x8c,0x35,0x61,0xa4,0x96,0x53, + 0x8e,0xa5,0x3b,0x2b,0x51,0xe1,0x93,0xab,0xa3,0xb5,0xf,0x9f,0x4e,0xd3,0x63,0x8b, + 0x1a,0x6,0xfa,0x42,0x8f,0xbe,0x3d,0xb8,0xfd,0x43,0xad,0x62,0xe8,0x9f,0x75,0xc0, + 0x3a,0x49,0x3d,0x41,0x9c,0x96,0x39,0xdd,0xb4,0x9d,0x86,0xf7,0x15,0xdb,0x1b,0x80, + 0xdb,0xb7,0x77,0x6b,0xd3,0xfe,0xb5,0x71,0xf1,0x47,0x67,0x52,0x86,0x6b,0x39,0x80, + 0x25,0x69,0xb8,0x96,0xe6,0x67,0x1a,0x64,0x40,0xaf,0xa4,0xa2,0xed,0xea,0xaa,0x84, + 0xe8,0x62,0x2b,0xf7,0xf7,0x4e,0x65,0x33,0xb5,0xd4,0x97,0x80,0x58,0x30,0xb0,0xbb, + 0x12,0x55,0xbf,0xbb,0x2d,0x2e,0x9c,0x58,0x4c,0x93,0x93,0x8b,0xf0,0x9b,0x29,0x2b, + 0x56,0xc6,0x17,0xd6,0x27,0x3c,0x39,0xd1,0xe1,0xc4,0xe2,0x92,0x50,0x7e,0x6b,0x8b, + 0xb4,0xb6,0x14,0xd1,0xcc,0x69,0xd9,0x6e,0x6,0x50,0x6f,0xb0,0x2b,0xb9,0x96,0x84, + 0x2f,0xa9,0x98,0xd7,0xda,0xbc,0x37,0xd0,0x67,0x7,0xb0,0x2a,0x5c,0x34,0xb7,0x9d, + 0x4b,0x5a,0xc,0xa,0x58,0x91,0xd4,0x13,0xfa,0x66,0xcd,0x44,0xcb,0xce,0x6d,0x3e, + 0x3b,0x20,0xce,0x36,0x60,0x36,0x5d,0x3a,0xf7,0x70,0xd,0x87,0x35,0x3,0xb6,0xa3, + 0x75,0x25,0xf5,0xaf,0x2e,0xa0,0xa7,0x2f,0xe6,0xad,0x7a,0xc6,0x38,0x70,0x4a,0x52, + 0x9f,0xed,0xae,0xe1,0xba,0x7b,0x58,0x12,0xe,0x49,0x60,0x9b,0x3b,0x2b,0x31,0x27, + 0x16,0x72,0x4e,0x36,0xe0,0xde,0xd5,0x91,0xbf,0xbc,0x21,0xd6,0x5c,0xc7,0xfe,0xf6, + 0xf1,0xf6,0xe4,0x58,0x4b,0x47,0x80,0x63,0x92,0x66,0x56,0x24,0xff,0xcd,0xe0,0xe, + 0xc,0xb7,0x15,0x24,0x7c,0x10,0x74,0x37,0xf8,0xe3,0xc0,0xde,0x5d,0x3d,0x6c,0x1e, + 0x2c,0xa9,0xeb,0xe0,0x8c,0x5b,0x31,0xd6,0xed,0x7d,0x8a,0xe,0xcf,0xbb,0x21,0x29, + 0xbb,0xa9,0x8b,0xee,0x9d,0x5d,0x2a,0xfe,0x61,0x86,0xa9,0xdc,0x9e,0x5e,0xcc,0x75, + 0xfe,0x7,0xa7,0xd2,0xf8,0x8b,0xeb,0xe2,0xea,0xcf,0x6f,0x49,0x22,0x24,0x4d,0xb5, + 0xcc,0x89,0x6,0xf1,0xef,0xa7,0xd2,0xbe,0xd1,0x6,0x5b,0x24,0x45,0x77,0x56,0x54, + 0x49,0xd,0xbf,0x9d,0x72,0x23,0x88,0x49,0xb7,0xed,0x7e,0xa0,0xfb,0x1b,0x9b,0xe2, + 0xc2,0xc8,0x2,0x3e,0xbd,0xe8,0xc,0xd0,0xc6,0xb2,0xa2,0xc1,0x32,0x3a,0xbd,0x68, + 0x7e,0x71,0x4b,0x42,0x66,0xf4,0xcc,0x85,0xac,0xf3,0xdc,0xe5,0x7c,0xc,0x38,0x4, + 0x3e,0x28,0xe9,0x30,0x30,0x13,0x46,0xca,0x35,0x2b,0x97,0x0,0x6b,0x6d,0xef,0x93, + 0x74,0x7f,0x51,0xdc,0xf5,0xd0,0xb6,0x64,0x4b,0x6a,0xa2,0x17,0xaf,0xe4,0xe4,0x76, + 0x79,0xdf,0xaa,0x88,0xfb,0x7,0x22,0xbd,0x52,0xcb,0x7a,0xb6,0x77,0xc1,0xf7,0xb7, + 0x25,0x51,0x6f,0x22,0x5e,0x98,0x69,0x97,0x2c,0xcd,0x1,0x73,0x27,0x17,0x9d,0x3f, + 0x72,0x26,0xdd,0xba,0xbe,0xa4,0xbe,0xfe,0x2,0xba,0xa1,0x20,0x7d,0x6d,0x30,0x66, + 0xa0,0x98,0x14,0x1e,0x1d,0xcd,0xfa,0x33,0xc3,0x9e,0x5e,0x45,0xcf,0x5d,0xb6,0x43, + 0x32,0x37,0x2,0x3,0xd5,0x44,0x95,0x7,0x36,0xc7,0xd5,0x4a,0x8c,0x1f,0x19,0xcd, + 0x66,0x73,0xc8,0x81,0xde,0x1d,0xdd,0x2a,0x17,0x4,0xbb,0xfb,0x62,0xc6,0x16,0x73, + 0x1e,0x1e,0xcd,0xf2,0x7a,0xea,0x3a,0x30,0x26,0xe9,0x45,0xdb,0x2f,0x2,0xe3,0x40, + 0x73,0xa5,0xe8,0x45,0x57,0x55,0xad,0x1b,0xd8,0x9,0x7c,0xac,0x37,0xf2,0xdd,0x3f, + 0x7c,0x4f,0xbc,0xed,0xd0,0x5c,0x1e,0x3d,0x3a,0x9a,0xea,0xaf,0x57,0x2c,0x4b,0xfa, + 0xc4,0xea,0x48,0xbf,0xbe,0x98,0xd3,0x17,0x13,0x7d,0x67,0x5b,0x12,0xfd,0x6a,0x32, + 0x23,0xcd,0x73,0x3a,0xa6,0x14,0xa8,0xbb,0xa,0x28,0xe4,0xc0,0xb9,0x96,0xfd,0xda, + 0x2,0x6a,0x64,0xa6,0x10,0x89,0xd7,0xea,0x76,0x2b,0xb7,0x7a,0x13,0xa2,0xf5,0x25, + 0xe9,0x4f,0x33,0x39,0x92,0x4a,0xa5,0x48,0xab,0x3f,0xb7,0x2e,0xde,0xf8,0xcb,0x5d, + 0x71,0xff,0x5c,0x4a,0xfa,0xd0,0xc9,0xf4,0x64,0x3d,0x63,0xc4,0xf6,0x59,0xa0,0x71, + 0x77,0x9f,0x78,0x62,0x22,0xcb,0xbf,0x32,0xd2,0x4e,0x8b,0xb1,0xfc,0xe0,0xe6,0x58, + 0x92,0x62,0xa0,0x14,0x6,0xbb,0xae,0x76,0x3f,0x6f,0xaa,0x9c,0x6d,0x1,0x3d,0xc0, + 0x16,0xe0,0xe6,0xaf,0xe,0xc6,0x9b,0x8e,0xd4,0xe0,0xe0,0xac,0xb5,0xab,0x47,0x6, + 0xf9,0xd8,0x42,0xee,0x6a,0x4c,0xbc,0xab,0x47,0xfe,0xd2,0xfa,0x58,0x4f,0x4e,0xa4, + 0xd9,0xa9,0x45,0x48,0xa2,0x28,0x6,0xba,0xb1,0xb7,0x6e,0x2c,0x2b,0xb7,0x49,0xca, + 0x91,0xca,0x1b,0xca,0x8a,0x3e,0x52,0x95,0x37,0x94,0xc5,0x93,0x13,0x69,0xe3,0x8f, + 0x33,0x9e,0x97,0x54,0xbe,0xb1,0x40,0x25,0x35,0xf1,0x87,0xaa,0x62,0x4f,0x25,0xd2, + 0x8e,0x1e,0x15,0x26,0x1a,0x79,0xf6,0x93,0xb1,0xec,0xd2,0x91,0x1a,0xc7,0x80,0x91, + 0x30,0xc8,0xef,0x90,0xbd,0x69,0x63,0x49,0x9c,0x6e,0xb0,0x50,0xcb,0x75,0xe5,0x9b, + 0xc7,0x3b,0xc9,0xd7,0x7,0xe3,0x81,0xc7,0x76,0x24,0x95,0x9f,0x8e,0x76,0xb6,0x5f, + 0x4e,0xf5,0x1,0xe0,0x3f,0xc0,0xa5,0x3,0xc3,0xed,0xe6,0x33,0xbb,0x8b,0x6f,0xa5, + 0xe5,0xb2,0x7,0xc,0x52,0xca,0xfb,0xab,0x51,0xb2,0xbd,0xdb,0xde,0x50,0x8a,0xb3, + 0xe1,0x5a,0xde,0x1c,0xae,0xe5,0xf3,0x40,0xfb,0xa9,0x8b,0x79,0xf5,0x83,0x55,0x75, + 0x3d,0x3e,0x9e,0xd5,0x4f,0x2f,0xba,0x2e,0x28,0xe,0xcd,0x67,0x6b,0x24,0x35,0xcb, + 0x11,0x85,0xc7,0x76,0x24,0xdd,0xb9,0x8d,0x80,0xd1,0x86,0xf3,0xbf,0xcc,0x7a,0xe1, + 0xd5,0x73,0xf9,0xf9,0xd9,0x94,0xd3,0xb6,0x17,0x24,0x6d,0xee,0x2f,0xb0,0x6b,0x75, + 0x51,0x95,0x3b,0x2a,0x51,0xf6,0xca,0x7c,0xde,0x78,0xea,0x82,0x67,0xcf,0xb5,0x18, + 0x33,0x1c,0x7,0x86,0x80,0xe3,0x41,0x5c,0x36,0x6f,0xef,0x91,0xea,0x39,0xf9,0x64, + 0xcb,0x67,0x24,0x1d,0xcd,0x50,0xfc,0xf8,0x44,0x7e,0xcb,0xbe,0x3e,0xef,0x7c,0x70, + 0x4b,0x32,0xf0,0xb3,0xb3,0xd9,0x6d,0xd3,0x1d,0x86,0x80,0x61,0x60,0x86,0x25,0x2a, + 0xbf,0xa5,0x72,0xe,0xee,0xe0,0x2c,0x30,0xf2,0xf9,0xa3,0x9d,0x8,0xe8,0x91,0xd4, + 0x4,0x2e,0x83,0xce,0x83,0xdb,0x87,0xe6,0xbd,0xea,0xd0,0xbc,0xbb,0x6c,0xd7,0x81, + 0x3a,0xa2,0xf2,0xe3,0xd1,0x6c,0x8d,0xa4,0x72,0x33,0xa7,0xf7,0x81,0xd7,0x3b,0x37, + 0x54,0x13,0x95,0xce,0x34,0x5c,0x97,0x74,0xc5,0xf6,0x39,0x49,0xc7,0x81,0xd7,0x81, + 0xb6,0xed,0xbd,0x2f,0xcf,0xab,0xfe,0xd2,0x48,0xa7,0xa,0xd4,0x25,0x5d,0xb0,0x3d, + 0xe,0x9c,0x2,0x4e,0x84,0x3e,0xaa,0xd9,0xde,0xa,0x4c,0x8e,0x37,0x39,0xff,0xbb, + 0xcb,0x79,0x23,0x8,0xc6,0xb,0xb6,0x5b,0x92,0xf6,0xfe,0x73,0x2e,0x9f,0xab,0x65, + 0xec,0x8c,0x71,0xdb,0x5e,0x72,0xe8,0x61,0xfe,0xbe,0x95,0x96,0xcf,0xee,0x29,0xf9, + 0xc0,0x70,0x7b,0x1,0xf8,0x77,0x58,0xf4,0xaf,0x60,0x58,0x1b,0xc0,0xe5,0xe0,0x2a, + 0xda,0x61,0xa6,0x95,0x82,0xef,0x6b,0x86,0x3e,0xed,0xf,0xc6,0xb6,0x3a,0x93,0x6a, + 0x60,0xba,0xe3,0xa2,0xa4,0x86,0xed,0xcb,0xc0,0x39,0x60,0xdc,0xf6,0x25,0x49,0x91, + 0xed,0x8b,0xb6,0x47,0x25,0x75,0xd9,0x9e,0xb5,0x7d,0x9,0xb8,0x0,0x4c,0x1,0xf3, + 0xc0,0x62,0x30,0xd2,0x93,0xb6,0x5f,0x6e,0xe6,0xe8,0xef,0x73,0x8e,0x6c,0xbf,0x2a, + 0xe9,0xb0,0xa4,0x3a,0x70,0x5e,0xd2,0xc5,0x91,0x7a,0x7e,0xb3,0xa4,0x86,0xc4,0x31, + 0x60,0x7e,0xa5,0x52,0x5e,0x4b,0x2d,0xdb,0xb6,0x27,0x25,0xcd,0x7,0x70,0x71,0x70, + 0xe8,0xd,0xa0,0xb9,0xc2,0xa5,0x47,0x41,0xbe,0x73,0x49,0x89,0xed,0x82,0xed,0x58, + 0x52,0x39,0x80,0x8d,0x6d,0x77,0x80,0x45,0x60,0x21,0xec,0xed,0x84,0x7d,0x75,0x49, + 0x67,0x6c,0x47,0x40,0x2b,0x24,0xa1,0x15,0x6,0x70,0xbe,0xec,0xec,0xf7,0xf,0xb5, + 0xa6,0x81,0x97,0x6d,0x8f,0x85,0x7d,0x17,0x97,0x18,0x44,0x27,0xd0,0x7b,0xa,0x38, + 0x6c,0x3b,0xb,0xd5,0x9f,0xbd,0x1a,0x9c,0xde,0xee,0x5f,0x2c,0xfc,0x3b,0xe5,0xcb, + 0xac,0xd,0xd5,0xd5,0xa,0x2a,0xbf,0xf1,0xf,0x6,0x28,0x64,0x3c,0x5a,0xfe,0x16, + 0xc0,0xe7,0x2b,0x55,0x6c,0xd9,0x8b,0x86,0xbd,0xbe,0x96,0xca,0xad,0x30,0x13,0x71, + 0x18,0xfc,0xa,0x86,0x21,0x5b,0x71,0x87,0x24,0x7c,0x23,0x24,0x2e,0xbb,0xd6,0x39, + 0xd7,0xe3,0x7a,0x5c,0x8f,0x77,0x2f,0xfe,0xb,0x93,0x15,0x70,0x93,0x8,0xc6,0xce, + 0x44,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/cuSDR_64.ico + 0x0,0x0,0x42,0x3e, + 0x0, + 0x0,0x1,0x0,0x1,0x0,0x40,0x40,0x0,0x0,0x1,0x0,0x20,0x0,0x28,0x42,0x0, + 0x0,0x16,0x0,0x0,0x0,0x28,0x0,0x0,0x0,0x40,0x0,0x0,0x0,0x80,0x0,0x0, + 0x0,0x1,0x0,0x20,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf6,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf6,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf6,0xf6,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf6,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf6,0x0,0x68,0xf7,0xf6,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf6,0x0, + 0x68,0xf7,0xf8,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf6,0xf6,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf6,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf6,0x0, + 0x68,0xf8,0xf6,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf6,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf6,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf8,0x0,0x68,0xf8,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf8,0xf7,0x0,0x68,0xf8,0xf8,0x0,0x68,0xf8,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf8,0xf8,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf8,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf8,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf8,0xf7,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf8,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf8,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf6,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf8,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf6,0xf6,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf7,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf6,0xf7,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf6,0x0,0x68,0xf7,0xf8,0x0,0x68,0xf7,0xf7,0x0, + 0x68,0xf7,0xf7,0x0,0x68,0xf8,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf7,0xf6,0x0, + 0x68,0xf7,0xf6,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf6,0xf7,0x0,0x68,0xf2,0xef,0x2, + 0x68,0xf2,0xef,0x2,0x68,0xf2,0xef,0x2,0x68,0xf2,0xef,0x2,0x68,0xf2,0xef,0x2, + 0x68,0xf2,0xef,0x2,0x68,0xf3,0xef,0x2,0x68,0xf3,0xf0,0x2,0x68,0xf3,0xf0,0x2, + 0x68,0xf3,0xf0,0x2,0x68,0xf3,0xf0,0x2,0x68,0xf3,0xf0,0x2,0x68,0xf3,0xf0,0x2, + 0x68,0xf3,0xf0,0x2,0x68,0xf3,0xf0,0x2,0x68,0xf3,0xf1,0x1,0x68,0xf3,0xf1,0x2, + 0x68,0xf3,0xf1,0x2,0x68,0xf3,0xf1,0x1,0x68,0xf3,0xf1,0x2,0x68,0xf4,0xf1,0x1, + 0x68,0xf4,0xf1,0x1,0x68,0xf3,0xf2,0x1,0x68,0xf3,0xf1,0x1,0x68,0xf4,0xf2,0x1, + 0x68,0xf4,0xf2,0x1,0x68,0xf4,0xf2,0x1,0x68,0xf4,0xf2,0x1,0x68,0xf4,0xf2,0x1, + 0x68,0xf4,0xf2,0x1,0x68,0xf4,0xf2,0x1,0x68,0xf4,0xf3,0x1,0x68,0xf4,0xf3,0x1, + 0x68,0xf5,0xf3,0x1,0x68,0xf4,0xf3,0x1,0x68,0xf4,0xf3,0x1,0x68,0xf4,0xf3,0x1, + 0x68,0xf5,0xf3,0x1,0x68,0xf5,0xf3,0x1,0x68,0xf5,0xf4,0x1,0x68,0xf5,0xf3,0x0, + 0x68,0xf5,0xf3,0x1,0x68,0xf5,0xf3,0x1,0x68,0xf5,0xf4,0x0,0x68,0xf5,0xf3,0x0, + 0x68,0xf5,0xf4,0x1,0x68,0xf5,0xf3,0x1,0x68,0xf5,0xf4,0x1,0x68,0xf5,0xf4,0x0, + 0x68,0xf5,0xf4,0x0,0x68,0xf5,0xf5,0x0,0x68,0xf5,0xf5,0x0,0x68,0xf5,0xf4,0x1, + 0x68,0xf6,0xf5,0x0,0x68,0xf5,0xf5,0x0,0x68,0xf5,0xf4,0x0,0x68,0xf5,0xf5,0x0, + 0x68,0xf6,0xf5,0x0,0x68,0xf5,0xf5,0x0,0x68,0xf6,0xf5,0x0,0x68,0xf6,0xf5,0x0, + 0x68,0xf6,0xf5,0x0,0x68,0xf6,0xf5,0x0,0x68,0xf6,0xf5,0x0,0x68,0xec,0xe4,0x5, + 0x68,0xec,0xe4,0x5,0x68,0xec,0xe4,0x5,0x68,0xeb,0xe4,0x6,0x68,0xec,0xe4,0x5, + 0x68,0xec,0xe4,0x5,0x68,0xec,0xe4,0x5,0x68,0xec,0xe5,0x5,0x68,0xec,0xe5,0x5, + 0x68,0xec,0xe5,0x5,0x68,0xec,0xe5,0x5,0x68,0xec,0xe5,0x5,0x68,0xec,0xe5,0x5, + 0x68,0xec,0xe5,0x5,0x68,0xed,0xe6,0x5,0x68,0xed,0xe6,0x5,0x68,0xed,0xe6,0x5, + 0x68,0xed,0xe6,0x5,0x68,0xec,0xe6,0x5,0x68,0xed,0xe6,0x5,0x68,0xed,0xe6,0x5, + 0x68,0xed,0xe6,0x4,0x68,0xed,0xe6,0x5,0x68,0xed,0xe6,0x4,0x68,0xed,0xe6,0x4, + 0x68,0xed,0xe7,0x5,0x68,0xee,0xe7,0x4,0x68,0xed,0xe7,0x4,0x68,0xee,0xe7,0x4, + 0x68,0xee,0xe7,0x4,0x68,0xee,0xe7,0x4,0x68,0xed,0xe8,0x4,0x68,0xee,0xe7,0x4, + 0x68,0xee,0xe8,0x4,0x68,0xee,0xe8,0x4,0x68,0xee,0xe8,0x4,0x68,0xee,0xe8,0x4, + 0x68,0xee,0xe8,0x4,0x68,0xee,0xe8,0x4,0x68,0xee,0xe8,0x4,0x68,0xef,0xe9,0x4, + 0x68,0xee,0xe8,0x4,0x68,0xef,0xe9,0x4,0x68,0xee,0xe9,0x4,0x68,0xee,0xe9,0x4, + 0x68,0xef,0xe9,0x4,0x68,0xef,0xe9,0x4,0x68,0xef,0xea,0x4,0x68,0xef,0xe9,0x4, + 0x68,0xef,0xea,0x3,0x68,0xef,0xea,0x3,0x68,0xf0,0xea,0x3,0x68,0xee,0xea,0x3, + 0x68,0xf0,0xea,0x3,0x68,0xef,0xea,0x3,0x68,0xef,0xea,0x3,0x68,0xf0,0xea,0x4, + 0x68,0xef,0xea,0x3,0x68,0xf0,0xeb,0x3,0x68,0xf0,0xeb,0x3,0x68,0xf0,0xeb,0x3, + 0x68,0xf0,0xeb,0x3,0x68,0xf0,0xeb,0x4,0x68,0xf0,0xeb,0x3,0x68,0xe4,0xd9,0x9, + 0x68,0xe4,0xd9,0xa,0x68,0xe5,0xd9,0x9,0x68,0xe5,0xd9,0x9,0x68,0xe5,0xd9,0x8, + 0x68,0xe4,0xd9,0x9,0x68,0xe5,0xda,0x9,0x68,0xe5,0xd9,0x8,0x68,0xe5,0xda,0x9, + 0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x9, + 0x68,0xe5,0xda,0x9,0x68,0xe5,0xda,0x9,0x68,0xe6,0xdb,0x9,0x68,0xe6,0xdb,0x9, + 0x68,0xe6,0xdb,0x9,0x68,0xe6,0xdb,0x9,0x68,0xe6,0xdb,0x9,0x68,0xe6,0xdb,0x9, + 0x68,0xe6,0xdb,0x9,0x68,0xe6,0xdb,0x8,0x68,0xe6,0xdc,0x8,0x68,0xe6,0xdb,0x8, + 0x68,0xe6,0xdc,0x8,0x68,0xe6,0xdc,0x9,0x68,0xe7,0xdc,0x7,0x68,0xe7,0xdc,0x8, + 0x68,0xe7,0xdc,0x8,0x68,0xe7,0xdc,0x9,0x68,0xe7,0xdc,0x8,0x68,0xe7,0xdc,0x8, + 0x68,0xe7,0xdc,0x8,0x68,0xe7,0xdd,0x8,0x68,0xe7,0xdd,0x8,0x68,0xe7,0xdd,0x8, + 0x68,0xe7,0xdd,0x8,0x68,0xe7,0xdd,0x8,0x68,0xe7,0xdd,0x8,0x68,0xe7,0xdd,0x8, + 0x68,0xe7,0xdd,0x8,0x68,0xe7,0xde,0x7,0x68,0xe8,0xde,0x8,0x68,0xe7,0xde,0x8, + 0x68,0xe7,0xde,0x8,0x68,0xe7,0xde,0x8,0x68,0xe8,0xde,0x8,0x68,0xe8,0xde,0x8, + 0x68,0xe8,0xdf,0x7,0x68,0xe8,0xdf,0x8,0x68,0xe8,0xdf,0x7,0x68,0xe8,0xdf,0x7, + 0x68,0xe8,0xdf,0x7,0x68,0xe9,0xdf,0x7,0x68,0xe8,0xdf,0x7,0x68,0xe8,0xdf,0x7, + 0x68,0xe9,0xe0,0x6,0x68,0xe8,0xdf,0x7,0x68,0xe9,0xe0,0x7,0x68,0xe9,0xe0,0x7, + 0x68,0xe9,0xe0,0x7,0x68,0xe9,0xe0,0x6,0x68,0xe9,0xe0,0x7,0x68,0xde,0xce,0xd, + 0x68,0xde,0xce,0xd,0x68,0xde,0xce,0xd,0x68,0xde,0xce,0xc,0x68,0xde,0xce,0xc, + 0x68,0xde,0xce,0xd,0x68,0xdf,0xce,0xc,0x68,0xdf,0xce,0xd,0x68,0xde,0xce,0xd, + 0x68,0xde,0xcf,0xc,0x68,0xdf,0xcf,0xc,0x68,0xdf,0xcf,0xc,0x68,0xde,0xcf,0xc, + 0x68,0xdf,0xcf,0xc,0x68,0xdf,0xcf,0xc,0x68,0xdf,0xd0,0xc,0x68,0xdf,0xd0,0xc, + 0x68,0xdf,0xd0,0xd,0x68,0xe0,0xd0,0xc,0x68,0xdf,0xd0,0xc,0x68,0xdf,0xd0,0xc, + 0x68,0xdf,0xd0,0xc,0x68,0xe0,0xd0,0xc,0x68,0xe0,0xd1,0xc,0x68,0xe0,0xd1,0xc, + 0x68,0xe0,0xd0,0xc,0x68,0xe0,0xd1,0xc,0x68,0xe0,0xd1,0xc,0x68,0xe0,0xd1,0xc, + 0x68,0xe0,0xd1,0xc,0x68,0xe0,0xd1,0xc,0x68,0xe0,0xd1,0xb,0x68,0xe0,0xd1,0xc, + 0x68,0xe1,0xd2,0xc,0x68,0xe0,0xd1,0xb,0x68,0xe1,0xd2,0xb,0x68,0xe1,0xd2,0xb, + 0x68,0xe1,0xd2,0xb,0x68,0xe1,0xd3,0xb,0x68,0xe1,0xd2,0xb,0x68,0xe1,0xd2,0xb, + 0x68,0xe0,0xd3,0xb,0x68,0xe1,0xd3,0xc,0x68,0xe1,0xd3,0xb,0x68,0xe1,0xd3,0xb, + 0x68,0xe1,0xd3,0xb,0x68,0xe1,0xd3,0xb,0x68,0xe1,0xd4,0xb,0x68,0xe2,0xd3,0xb, + 0x68,0xe1,0xd3,0xb,0x68,0xe2,0xd3,0xb,0x68,0xe1,0xd4,0xb,0x68,0xe1,0xd4,0xb, + 0x68,0xe2,0xd4,0xb,0x68,0xe2,0xd4,0xb,0x68,0xe2,0xd4,0xb,0x68,0xe2,0xd4,0xb, + 0x68,0xe2,0xd5,0xb,0x68,0xe2,0xd5,0xb,0x68,0xe2,0xd5,0xb,0x68,0xe2,0xd5,0xb, + 0x68,0xe2,0xd5,0xb,0x68,0xe2,0xd5,0xb,0x68,0xe2,0xd5,0xa,0x68,0xd7,0xc3,0x10, + 0x68,0xd7,0xc3,0x10,0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc3,0x10, + 0x68,0xd7,0xc3,0x10,0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc4,0x10,0x68,0xd8,0xc4,0x10, + 0x68,0xd8,0xc3,0x10,0x68,0xd8,0xc4,0x10,0x68,0xd8,0xc4,0x10,0x68,0xd9,0xc4,0xf, + 0x68,0xd9,0xc4,0xf,0x68,0xd8,0xc5,0x10,0x68,0xd9,0xc4,0x10,0x68,0xd9,0xc5,0xf, + 0x68,0xd9,0xc5,0x10,0x68,0xd9,0xc5,0xf,0x68,0xd9,0xc5,0xf,0x68,0xd9,0xc5,0xf, + 0x68,0xd9,0xc5,0xf,0x68,0xd9,0xc5,0xf,0x68,0xd9,0xc5,0xf,0x68,0xd9,0xc5,0xf, + 0x68,0xd9,0xc6,0xf,0x68,0xd9,0xc6,0xf,0x68,0xd9,0xc6,0xf,0x68,0xd9,0xc6,0xf, + 0x68,0xd9,0xc6,0xf,0x68,0xda,0xc6,0xf,0x68,0xda,0xc6,0xf,0x68,0xd9,0xc6,0xf, + 0x68,0xda,0xc6,0xf,0x68,0xda,0xc7,0xf,0x68,0xda,0xc7,0xf,0x68,0xda,0xc7,0xf, + 0x68,0xda,0xc7,0xf,0x68,0xda,0xc7,0xf,0x68,0xda,0xc7,0xe,0x68,0xda,0xc7,0xe, + 0x68,0xda,0xc7,0xf,0x68,0xdb,0xc7,0xe,0x68,0xda,0xc7,0xf,0x68,0xdb,0xc8,0xe, + 0x68,0xdb,0xc8,0xe,0x68,0xdb,0xc8,0xe,0x68,0xdb,0xc8,0xe,0x68,0xdb,0xc8,0xe, + 0x68,0xdb,0xc8,0xe,0x68,0xdb,0xc8,0xe,0x68,0xdb,0xc9,0xe,0x68,0xdb,0xc9,0xe, + 0x68,0xdb,0xc9,0xe,0x68,0xdb,0xc9,0xe,0x68,0xdb,0xc9,0xe,0x68,0xdc,0xc9,0xe, + 0x68,0xdc,0xc9,0xe,0x68,0xdc,0xc9,0xe,0x68,0xdc,0xca,0xe,0x68,0xdb,0xca,0xe, + 0x68,0xdc,0xca,0xe,0x68,0xdc,0xca,0xe,0x68,0xdc,0xca,0xe,0x68,0xd1,0xb7,0x13, + 0x68,0xd1,0xb8,0x13,0x68,0xd1,0xb8,0x13,0x68,0xd1,0xb8,0x13,0x68,0xd1,0xb8,0x13, + 0x68,0xd2,0xb8,0x13,0x68,0xd1,0xb9,0x13,0x68,0xd2,0xb9,0x13,0x68,0xd2,0xb9,0x13, + 0x68,0xd2,0xb9,0x13,0x68,0xd2,0xb9,0x13,0x68,0xd1,0xb9,0x13,0x68,0xd2,0xb9,0x13, + 0x68,0xd2,0xb9,0x13,0x68,0xd2,0xba,0x13,0x68,0xd2,0xb9,0x13,0x68,0xd2,0xb9,0x13, + 0x68,0xd2,0xba,0x13,0x68,0xd2,0xb9,0x12,0x68,0xd2,0xba,0x13,0x68,0xd2,0xba,0x13, + 0x68,0xd2,0xba,0x13,0x68,0xd2,0xba,0x12,0x68,0xd2,0xbb,0x13,0x68,0xd3,0xba,0x12, + 0x68,0xd3,0xba,0x12,0x68,0xd3,0xbb,0x12,0x68,0xd3,0xbb,0x12,0x68,0xd3,0xbb,0x12, + 0x68,0xd3,0xbb,0x12,0x68,0xd3,0xbb,0x12,0x68,0xd3,0xbc,0x12,0x68,0xd3,0xbb,0x12, + 0x68,0xd3,0xbb,0x13,0x68,0xd3,0xbc,0x12,0x68,0xd3,0xbc,0x12,0x68,0xd4,0xbc,0x12, + 0x68,0xd3,0xbc,0x12,0x68,0xd4,0xbc,0x12,0x68,0xd4,0xbc,0x12,0x68,0xd4,0xbc,0x12, + 0x68,0xd4,0xbc,0x12,0x68,0xd4,0xbc,0x12,0x68,0xd4,0xbd,0x12,0x68,0xd4,0xbd,0x12, + 0x68,0xd4,0xbd,0x12,0x68,0xd5,0xbd,0x12,0x68,0xd4,0xbd,0x12,0x68,0xd5,0xbd,0x12, + 0x68,0xd4,0xbe,0x12,0x68,0xd5,0xbd,0x11,0x68,0xd4,0xbe,0x12,0x68,0xd5,0xbe,0x11, + 0x68,0xd4,0xbe,0x11,0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbe,0x11, + 0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbf,0x12,0x68,0xd5,0xbe,0x11,0x68,0xd5,0xbf,0x11, + 0x68,0xd5,0xbf,0x11,0x68,0xd5,0xbf,0x11,0x68,0xd6,0xbf,0x11,0x68,0xca,0xad,0x16, + 0x68,0xca,0xad,0x17,0x68,0xca,0xad,0x16,0x68,0xca,0xad,0x16,0x68,0xca,0xad,0x17, + 0x68,0xca,0xad,0x16,0x68,0xcb,0xad,0x16,0x68,0xca,0xad,0x17,0x68,0xcb,0xae,0x16, + 0x68,0xcb,0xae,0x16,0x68,0xcb,0xae,0x16,0x68,0xcb,0xae,0x16,0x68,0xcb,0xae,0x16, + 0x68,0xcb,0xae,0x16,0x68,0xcb,0xae,0x16,0x68,0xcb,0xaf,0x16,0x68,0xcb,0xae,0x16, + 0x68,0xcb,0xaf,0x16,0x68,0xcb,0xaf,0x16,0x68,0xcb,0xaf,0x16,0x68,0xcb,0xaf,0x16, + 0x68,0xcc,0xaf,0x16,0x68,0xcc,0xaf,0x16,0x68,0xcb,0xaf,0x16,0x68,0xcb,0xaf,0x16, + 0x68,0xcc,0xaf,0x16,0x68,0xcb,0xb0,0x16,0x68,0xcc,0xb0,0x15,0x68,0xcc,0xb0,0x16, + 0x68,0xcb,0xb0,0x16,0x68,0xcc,0xb0,0x15,0x68,0xcc,0xb0,0x16,0x68,0xcc,0xb0,0x15, + 0x68,0xcc,0xb0,0x16,0x68,0xcc,0xb1,0x15,0x68,0xcc,0xb1,0x15,0x68,0xcc,0xb1,0x15, + 0x68,0xcc,0xb1,0x15,0x68,0xcd,0xb1,0x15,0x68,0xcd,0xb1,0x15,0x68,0xcd,0xb2,0x15, + 0x68,0xcd,0xb1,0x15,0x68,0xcd,0xb2,0x15,0x68,0xcd,0xb2,0x15,0x68,0xcd,0xb2,0x15, + 0x68,0xcd,0xb2,0x15,0x68,0xcd,0xb2,0x15,0x68,0xce,0xb2,0x15,0x68,0xcd,0xb2,0x15, + 0x68,0xcd,0xb2,0x15,0x68,0xcd,0xb3,0x15,0x68,0xce,0xb3,0x15,0x68,0xce,0xb3,0x15, + 0x68,0xcd,0xb3,0x15,0x68,0xce,0xb3,0x15,0x68,0xce,0xb3,0x15,0x68,0xce,0xb3,0x15, + 0x68,0xce,0xb4,0x15,0x68,0xce,0xb3,0x14,0x68,0xce,0xb4,0x14,0x68,0xcf,0xb4,0x14, + 0x68,0xce,0xb4,0x14,0x68,0xce,0xb4,0x14,0x68,0xcf,0xb4,0x14,0x68,0xc4,0xa3,0x1a, + 0x68,0xc4,0xa3,0x1a,0x68,0xc4,0xa3,0x19,0x68,0xc4,0xa3,0x1a,0x68,0xc4,0xa3,0x19, + 0x68,0xc5,0xa3,0x19,0x68,0xc5,0xa3,0x19,0x67,0xc5,0xa3,0x19,0x67,0xc5,0xa3,0x19, + 0x67,0xc5,0xa3,0x19,0x67,0xc5,0xa3,0x19,0x67,0xc5,0xa4,0x19,0x67,0xc5,0xa4,0x19, + 0x67,0xc5,0xa4,0x19,0x67,0xc5,0xa4,0x19,0x68,0xc5,0xa4,0x19,0x68,0xc5,0xa4,0x19, + 0x68,0xc5,0xa4,0x19,0x68,0xc5,0xa4,0x19,0x68,0xc5,0xa4,0x19,0x68,0xc6,0xa5,0x19, + 0x68,0xc5,0xa5,0x19,0x68,0xc6,0xa5,0x19,0x68,0xc6,0xa5,0x19,0x67,0xc6,0xa5,0x19, + 0x67,0xc6,0xa5,0x19,0x67,0xc6,0xa5,0x19,0x67,0xc6,0xa5,0x19,0x68,0xc6,0xa5,0x19, + 0x68,0xc6,0xa6,0x18,0x68,0xc6,0xa6,0x18,0x68,0xc6,0xa6,0x18,0x68,0xc6,0xa6,0x18, + 0x68,0xc6,0xa6,0x18,0x68,0xc6,0xa6,0x19,0x68,0xc6,0xa6,0x19,0x68,0xc7,0xa6,0x19, + 0x68,0xc7,0xa6,0x18,0x68,0xc7,0xa7,0x18,0x68,0xc7,0xa7,0x18,0x68,0xc7,0xa7,0x18, + 0x67,0xc7,0xa7,0x18,0x67,0xc7,0xa7,0x18,0x68,0xc7,0xa7,0x18,0x68,0xc7,0xa7,0x18, + 0x68,0xc7,0xa7,0x18,0x68,0xc7,0xa7,0x18,0x67,0xc7,0xa7,0x18,0x67,0xc7,0xa8,0x18, + 0x68,0xc7,0xa8,0x18,0x68,0xc8,0xa8,0x18,0x68,0xc7,0xa8,0x18,0x68,0xc7,0xa8,0x18, + 0x67,0xc7,0xa8,0x18,0x67,0xc7,0xa8,0x18,0x68,0xc8,0xa8,0x18,0x68,0xc8,0xa9,0x18, + 0x68,0xc8,0xa9,0x18,0x68,0xc8,0xa8,0x18,0x67,0xc8,0xa9,0x18,0x67,0xc8,0xa9,0x18, + 0x68,0xc8,0xa9,0x18,0x68,0xc8,0xa9,0x17,0x68,0xc8,0xa9,0x18,0x68,0xbe,0x99,0x1c, + 0x68,0xbe,0x99,0x1d,0x68,0xbe,0x99,0x1d,0x68,0xbe,0x99,0x1c,0x68,0xbe,0x9a,0x1c, + 0x67,0xbf,0x99,0x1d,0x67,0xbf,0x99,0x1c,0x68,0xbf,0x9a,0x1d,0x68,0xbf,0x9a,0x1c, + 0x68,0xbf,0x9a,0x1c,0x68,0xbf,0x9a,0x1c,0x68,0xbf,0x9a,0x1c,0x68,0xbf,0x9a,0x1c, + 0x68,0xbf,0x9a,0x1c,0x68,0xbf,0x9a,0x1c,0x67,0xbf,0x9a,0x1c,0x67,0xc0,0x9b,0x1c, + 0x68,0xbf,0x9a,0x1c,0x68,0xc0,0x9b,0x1c,0x68,0xc0,0x9b,0x1c,0x68,0xbf,0x9b,0x1c, + 0x68,0xc0,0x9b,0x1c,0x67,0xc0,0x9b,0x1c,0x67,0xbf,0x9b,0x1c,0x69,0xc0,0x9b,0x1c, + 0x68,0xc0,0x9b,0x1c,0x68,0xc0,0x9b,0x1c,0x68,0xc0,0x9c,0x1c,0x67,0xc1,0x9c,0x1c, + 0x67,0xc0,0x9c,0x1c,0x67,0xc0,0x9c,0x1b,0x68,0xc1,0x9c,0x1b,0x68,0xc1,0x9c,0x1b, + 0x68,0xc1,0x9c,0x1b,0x68,0xc0,0x9c,0x1b,0x68,0xc1,0x9d,0x1b,0x68,0xc1,0x9d,0x1b, + 0x68,0xc1,0x9d,0x1b,0x68,0xc1,0x9d,0x1b,0x68,0xc1,0x9d,0x1b,0x67,0xc0,0x9d,0x1b, + 0x68,0xc1,0x9d,0x1b,0x68,0xc1,0x9d,0x1b,0x68,0xc1,0x9e,0x1c,0x69,0xc2,0x9d,0x1c, + 0x69,0xc1,0x9d,0x1b,0x68,0xc1,0x9e,0x1b,0x68,0xc2,0x9d,0x1b,0x68,0xc2,0x9e,0x1b, + 0x67,0xc1,0x9e,0x1b,0x68,0xc2,0x9e,0x1b,0x68,0xc1,0x9e,0x1b,0x67,0xc2,0x9e,0x1b, + 0x68,0xc2,0x9f,0x1b,0x68,0xc2,0x9e,0x1b,0x68,0xc2,0x9e,0x1b,0x69,0xc2,0x9e,0x1b, + 0x69,0xc2,0x9e,0x1b,0x68,0xc2,0x9f,0x1a,0x68,0xc2,0x9f,0x1a,0x68,0xc3,0x9f,0x1b, + 0x67,0xc2,0x9f,0x1b,0x68,0xc3,0xa0,0x1b,0x68,0xc2,0x9f,0x1a,0x68,0xb9,0x8f,0x20, + 0x68,0xb9,0x8f,0x1f,0x68,0xb9,0x8f,0x1f,0x68,0xb9,0x8f,0x1f,0x67,0xb9,0x8f,0x1f, + 0x68,0xb9,0x90,0x1f,0x69,0xb9,0x90,0x20,0x69,0xb9,0x90,0x20,0x6a,0xba,0x91,0x21, + 0x6b,0xba,0x92,0x21,0x6b,0xba,0x91,0x21,0x6b,0xb9,0x91,0x20,0x6b,0xba,0x91,0x20, + 0x6a,0xb9,0x91,0x20,0x69,0xb9,0x91,0x1f,0x69,0xba,0x91,0x1f,0x69,0xb9,0x91,0x1f, + 0x68,0xba,0x91,0x1f,0x68,0xb9,0x90,0x1f,0x67,0xba,0x91,0x1f,0x67,0xba,0x91,0x1f, + 0x68,0xba,0x91,0x1f,0x69,0xba,0x91,0x1f,0x69,0xba,0x92,0x1f,0x69,0xba,0x92,0x20, + 0x6a,0xbb,0x92,0x1f,0x6a,0xba,0x92,0x1f,0x69,0xba,0x92,0x1f,0x69,0xb9,0x92,0x1e, + 0x69,0xba,0x92,0x1f,0x68,0xba,0x92,0x1f,0x68,0xba,0x92,0x1f,0x68,0xbb,0x93,0x1f, + 0x67,0xbb,0x92,0x1f,0x67,0xbb,0x93,0x1e,0x68,0xbb,0x93,0x1e,0x68,0xbb,0x93,0x1e, + 0x68,0xbb,0x93,0x1e,0x67,0xbb,0x93,0x1f,0x68,0xbb,0x93,0x1e,0x69,0xbb,0x94,0x1f, + 0x69,0xbc,0x94,0x1f,0x6b,0xbd,0x95,0x20,0x6c,0xbd,0x95,0x20,0x6d,0xbe,0x96,0x21, + 0x6d,0xbd,0x95,0x20,0x6c,0xbc,0x95,0x20,0x6a,0xbc,0x95,0x1e,0x69,0xbb,0x93,0x1e, + 0x68,0xbc,0x94,0x1e,0x68,0xbc,0x94,0x1e,0x68,0xbc,0x94,0x1e,0x68,0xbc,0x95,0x1f, + 0x6a,0xbe,0x95,0x1f,0x6b,0xbe,0x96,0x20,0x6c,0xbe,0x97,0x21,0x6e,0xbe,0x98,0x20, + 0x6e,0xbe,0x97,0x20,0x6c,0xbd,0x96,0x1f,0x6b,0xbc,0x96,0x1e,0x69,0xbb,0x95,0x1e, + 0x68,0xbc,0x95,0x1e,0x68,0xbc,0x96,0x1d,0x68,0xbc,0x96,0x1d,0x68,0xb2,0x85,0x23, + 0x68,0xb2,0x85,0x23,0x68,0xb2,0x85,0x23,0x67,0xb2,0x85,0x24,0x68,0xb3,0x86,0x22, + 0x69,0xb5,0x88,0x24,0x6c,0xb6,0x8a,0x25,0x6e,0xb8,0x8b,0x26,0x71,0xb9,0x8c,0x27, + 0x73,0xba,0x8e,0x27,0x74,0xba,0x8d,0x27,0x74,0xb9,0x8d,0x27,0x72,0xb9,0x8b,0x26, + 0x71,0xb8,0x8a,0x25,0x6f,0xb6,0x89,0x25,0x6c,0xb5,0x88,0x23,0x6b,0xb3,0x87,0x23, + 0x6a,0xb3,0x87,0x23,0x69,0xb3,0x87,0x23,0x69,0xb3,0x87,0x23,0x69,0xb4,0x87,0x23, + 0x68,0xb4,0x88,0x23,0x6a,0xb6,0x89,0x24,0x6c,0xb8,0x8c,0x25,0x6e,0xb9,0x8b,0x26, + 0x70,0xb9,0x8d,0x25,0x70,0xb9,0x8b,0x25,0x6f,0xb7,0x8b,0x24,0x6d,0xb6,0x89,0x23, + 0x6c,0xb5,0x89,0x23,0x6b,0xb4,0x88,0x22,0x6a,0xb4,0x88,0x22,0x69,0xb4,0x88,0x22, + 0x69,0xb4,0x88,0x22,0x68,0xb4,0x88,0x22,0x68,0xb5,0x88,0x22,0x67,0xb4,0x89,0x22, + 0x67,0xb4,0x89,0x22,0x68,0xb5,0x89,0x22,0x68,0xb6,0x8a,0x22,0x6a,0xb7,0x8b,0x23, + 0x6d,0xbb,0x8f,0x25,0x72,0xbd,0x91,0x28,0x77,0xbf,0x94,0x28,0x7a,0xbf,0x92,0x29, + 0x79,0xbd,0x91,0x27,0x76,0xba,0x8f,0x24,0x70,0xb8,0x8c,0x23,0x6c,0xb6,0x8b,0x21, + 0x69,0xb5,0x8a,0x22,0x69,0xb6,0x8a,0x22,0x69,0xb6,0x8b,0x22,0x6b,0xb9,0x8e,0x24, + 0x6e,0xbc,0x91,0x26,0x72,0xbe,0x94,0x27,0x77,0xc0,0x95,0x29,0x7a,0xc0,0x95,0x28, + 0x7a,0xbd,0x93,0x27,0x76,0xbb,0x90,0x25,0x71,0xb9,0x8e,0x23,0x6d,0xb7,0x8c,0x22, + 0x69,0xb6,0x8b,0x21,0x69,0xb6,0x8b,0x21,0x67,0xb6,0x8b,0x21,0x68,0xac,0x7b,0x26, + 0x68,0xac,0x7c,0x26,0x68,0xac,0x7b,0x26,0x67,0xad,0x7c,0x26,0x6a,0xb0,0x7f,0x28, + 0x6d,0xb4,0x84,0x2a,0x73,0xb8,0x88,0x2c,0x7a,0xbc,0x8c,0x2e,0x82,0xbe,0x8f,0x30, + 0x86,0xbf,0x8f,0x30,0x88,0xbf,0x8f,0x30,0x87,0xbd,0x8f,0x30,0x85,0xbc,0x8d,0x2e, + 0x82,0xba,0x8a,0x2d,0x7d,0xb8,0x88,0x2c,0x79,0xb5,0x85,0x2a,0x74,0xb2,0x82,0x29, + 0x70,0xb1,0x80,0x27,0x6d,0xaf,0x7e,0x26,0x6b,0xaf,0x7e,0x26,0x6a,0xb0,0x80,0x26, + 0x6b,0xb3,0x82,0x28,0x6f,0xb7,0x87,0x2a,0x76,0xba,0x8a,0x2d,0x7c,0xbc,0x8c,0x2e, + 0x80,0xbc,0x8d,0x2d,0x80,0xbb,0x8c,0x2c,0x7d,0xb9,0x89,0x2c,0x79,0xb7,0x87,0x2a, + 0x76,0xb5,0x85,0x29,0x72,0xb3,0x83,0x27,0x6f,0xb1,0x82,0x27,0x6d,0xb0,0x80,0x26, + 0x6b,0xae,0x7f,0x26,0x6a,0xaf,0x7f,0x25,0x69,0xae,0x7f,0x25,0x68,0xaf,0x7e,0x25, + 0x68,0xaf,0x7f,0x25,0x68,0xb0,0x80,0x25,0x69,0xb3,0x83,0x27,0x6e,0xb7,0x88,0x2a, + 0x75,0xbd,0x8e,0x2d,0x80,0xc2,0x93,0x30,0x8a,0xc4,0x96,0x32,0x91,0xc4,0x96,0x32, + 0x91,0xc1,0x93,0x30,0x89,0xbc,0x8e,0x2c,0x7f,0xb7,0x88,0x29,0x74,0xb2,0x84,0x26, + 0x6d,0xb0,0x82,0x25,0x6b,0xb2,0x83,0x26,0x6c,0xb5,0x86,0x28,0x71,0xba,0x8b,0x2a, + 0x79,0xbf,0x91,0x2e,0x83,0xc3,0x96,0x31,0x8e,0xc5,0x98,0x32,0x93,0xc5,0x97,0x31, + 0x91,0xc2,0x94,0x30,0x8b,0xbc,0x8f,0x2c,0x7f,0xb8,0x89,0x28,0x73,0xb3,0x85,0x25, + 0x6d,0xb1,0x82,0x24,0x69,0xb0,0x82,0x24,0x67,0xb0,0x82,0x24,0x68,0xa6,0x71,0x29, + 0x68,0xa6,0x71,0x29,0x68,0xa7,0x71,0x29,0x67,0xaa,0x76,0x2b,0x6d,0xb0,0x7c,0x2d, + 0x75,0xb6,0x84,0x31,0x82,0xbd,0x8c,0x35,0x90,0xc3,0x91,0x37,0x9d,0xc5,0x95,0x38, + 0xa4,0xc6,0x95,0x39,0xa8,0xc6,0x96,0x39,0xa7,0xc5,0x95,0x38,0xa4,0xc3,0x92,0x37, + 0x9f,0xc1,0x90,0x36,0x98,0xbe,0x8c,0x34,0x90,0xba,0x88,0x32,0x87,0xb6,0x83,0x30, + 0x7e,0xb2,0x7f,0x2e,0x78,0xaf,0x7a,0x2c,0x72,0xae,0x79,0x2b,0x70,0xaf,0x7b,0x2c, + 0x73,0xb4,0x81,0x2e,0x7c,0xbb,0x89,0x32,0x88,0xc0,0x8f,0x35,0x94,0xc2,0x92,0x36, + 0x9b,0xc3,0x92,0x36,0x9c,0xc1,0x91,0x36,0x98,0xbf,0x8e,0x34,0x92,0xbc,0x8b,0x32, + 0x8b,0xb9,0x87,0x31,0x84,0xb6,0x84,0x2f,0x7e,0xb2,0x80,0x2e,0x78,0xb0,0x7d,0x2c, + 0x73,0xae,0x7a,0x2a,0x6f,0xab,0x77,0x29,0x6c,0xa9,0x76,0x28,0x6a,0xa9,0x75,0x28, + 0x69,0xa9,0x75,0x28,0x69,0xab,0x78,0x29,0x6c,0xb0,0x7e,0x2c,0x74,0xb9,0x87,0x30, + 0x82,0xc1,0x91,0x35,0x95,0xc7,0x97,0x38,0xa7,0xca,0x9b,0x3a,0xb1,0xca,0x9b,0x39, + 0xb1,0xc6,0x97,0x38,0xa4,0xc0,0x90,0x34,0x93,0xb9,0x87,0x30,0x81,0xb2,0x7f,0x2d, + 0x75,0xaf,0x7d,0x2a,0x70,0xb2,0x7f,0x2b,0x74,0xb7,0x86,0x2e,0x7e,0xbe,0x8d,0x33, + 0x8d,0xc4,0x95,0x36,0x9d,0xc9,0x9a,0x39,0xac,0xcb,0x9c,0x3a,0xb4,0xca,0x9c,0x39, + 0xb2,0xc7,0x98,0x38,0xa5,0xc0,0x90,0x33,0x92,0xb8,0x87,0x2f,0x7f,0xb0,0x7f,0x2b, + 0x71,0xac,0x79,0x28,0x6a,0xab,0x78,0x27,0x67,0xab,0x78,0x27,0x68,0xa0,0x67,0x2c, + 0x68,0xa1,0x67,0x2c,0x68,0xa0,0x67,0x2c,0x67,0xa9,0x72,0x30,0x73,0xb2,0x7c,0x34, + 0x82,0xbc,0x88,0x38,0x96,0xc3,0x91,0x3c,0xac,0xc8,0x96,0x3e,0xbe,0xcb,0x99,0x3f, + 0xc8,0xcc,0x9b,0x40,0xcc,0xcc,0x9b,0x40,0xcc,0xcb,0x9a,0x3f,0xc8,0xcb,0x99,0x3f, + 0xc3,0xc8,0x96,0x3d,0xbb,0xc5,0x93,0x3c,0xb1,0xc2,0x8f,0x3b,0xa5,0xbd,0x89,0x39, + 0x99,0xb8,0x83,0x35,0x8d,0xb3,0x7d,0x33,0x82,0xb1,0x7b,0x32,0x7d,0xb2,0x7d,0x33, + 0x81,0xb9,0x84,0x36,0x8e,0xc0,0x8e,0x3a,0xa1,0xc6,0x93,0x3c,0xb2,0xc9,0x97,0x3d, + 0xbd,0xca,0x98,0x3d,0xbf,0xc9,0x97,0x3d,0xbc,0xc6,0x95,0x3c,0xb3,0xc4,0x92,0x3b, + 0xab,0xc1,0x8e,0x3a,0xa2,0xbe,0x8b,0x38,0x98,0xba,0x85,0x36,0x8e,0xb5,0x80,0x34, + 0x85,0xb0,0x7b,0x31,0x7c,0xad,0x76,0x2f,0x75,0xa8,0x72,0x2d,0x70,0xa6,0x6f,0x2c, + 0x6d,0xa6,0x6e,0x2c,0x6c,0xa8,0x72,0x2d,0x70,0xb1,0x7b,0x31,0x7b,0xbb,0x88,0x36, + 0x91,0xc5,0x93,0x3b,0xac,0xcb,0x9b,0x3e,0xc4,0xce,0x9e,0x3f,0xd0,0xce,0x9d,0x40, + 0xcf,0xcb,0x9b,0x3e,0xc2,0xc5,0x92,0x3a,0xab,0xbc,0x89,0x36,0x92,0xb4,0x80,0x33, + 0x81,0xb1,0x7c,0x31,0x7c,0xb5,0x81,0x33,0x84,0xbc,0x89,0x36,0x93,0xc4,0x92,0x3a, + 0xa8,0xca,0x99,0x3d,0xbc,0xcd,0x9d,0x3e,0xcc,0xcf,0x9f,0x40,0xd4,0xce,0x9f,0x3f, + 0xd0,0xcb,0x9a,0x3d,0xc0,0xc4,0x92,0x3a,0xa5,0xb9,0x86,0x34,0x8b,0xaf,0x79,0x2f, + 0x76,0xa7,0x71,0x2c,0x6b,0xa4,0x6d,0x2a,0x67,0xa4,0x6d,0x2a,0x68,0x9b,0x61,0x2c, + 0x68,0x9b,0x61,0x2c,0x68,0x9a,0x60,0x2c,0x67,0xa8,0x70,0x31,0x79,0xb5,0x7f,0x36, + 0x8f,0xc0,0x8c,0x3c,0xac,0xc8,0x96,0x3f,0xc6,0xcc,0x9a,0x41,0xda,0xcd,0x9b,0x3d, + 0xe4,0xcd,0x9b,0x3c,0xe8,0xce,0x9c,0x3d,0xe8,0xce,0x9c,0x3e,0xe5,0xcd,0x9c,0x40, + 0xe1,0xcc,0x9b,0x41,0xdb,0xcb,0x99,0x40,0xd2,0xc8,0x96,0x3f,0xc7,0xc5,0x91,0x3e, + 0xb9,0xc0,0x8c,0x3c,0xab,0xbb,0x86,0x39,0x9d,0xb7,0x82,0x37,0x94,0xb9,0x84,0x39, + 0x97,0xbe,0x8a,0x3b,0xa5,0xc5,0x93,0x3e,0xbb,0xcb,0x98,0x40,0xd0,0xcc,0x99,0x3e, + 0xdb,0xce,0x9c,0x41,0xde,0xcd,0x9b,0x41,0xdc,0xcc,0x9a,0x41,0xd5,0xca,0x98,0x40, + 0xcd,0xc8,0x96,0x3f,0xc5,0xc5,0x92,0x3e,0xba,0xc2,0x8e,0x3d,0xaf,0xbd,0x89,0x3b, + 0xa1,0xb9,0x83,0x38,0x95,0xb2,0x7c,0x36,0x88,0xad,0x75,0x33,0x7e,0xa8,0x6f,0x31, + 0x75,0xa5,0x6c,0x30,0x72,0xa8,0x6f,0x31,0x76,0xb1,0x79,0x35,0x84,0xbd,0x88,0x3a, + 0x9f,0xc7,0x94,0x3f,0xbf,0xcd,0x9b,0x41,0xd9,0xd4,0xa9,0x56,0xe8,0xd2,0xa3,0x4a, + 0xe6,0xcd,0x9b,0x41,0xd8,0xc8,0x95,0x3f,0xc1,0xc0,0x8c,0x3b,0xa6,0xb9,0x83,0x38, + 0x94,0xb7,0x82,0x37,0x90,0xbc,0x87,0x39,0x9b,0xc3,0x8f,0x3c,0xaf,0xc8,0x96,0x3f, + 0xc5,0xcd,0x9b,0x41,0xd8,0xcf,0x9e,0x3f,0xe5,0xd5,0xaa,0x57,0xeb,0xd2,0xa2,0x4b, + 0xe5,0xcc,0x9a,0x40,0xd1,0xc4,0x91,0x3d,0xb3,0xb8,0x83,0x38,0x93,0xac,0x74,0x33, + 0x7b,0xa2,0x68,0x2e,0x6d,0x9e,0x64,0x2d,0x67,0x9f,0x64,0x2d,0x68,0x96,0x5c,0x2a, + 0x68,0x95,0x5c,0x2a,0x68,0x95,0x5b,0x29,0x66,0xa8,0x71,0x31,0x7f,0xb6,0x82,0x38, + 0x9a,0xc2,0x8f,0x3d,0xbb,0xc9,0x98,0x40,0xd8,0xcf,0xa2,0x4c,0xeb,0xf3,0xe7,0xcf, + 0xfb,0xfa,0xf5,0xec,0xfd,0xf3,0xe7,0xd0,0xfc,0xe6,0xcf,0xa1,0xf9,0xd7,0xae,0x62, + 0xf5,0xcb,0x9a,0x39,0xf0,0xcc,0x9b,0x3e,0xeb,0xcc,0x9b,0x41,0xe3,0xca,0x99,0x40, + 0xd8,0xc6,0x95,0x3f,0xcb,0xc3,0x90,0x3d,0xbd,0xc0,0x8d,0x3b,0xb2,0xc0,0x8e,0x3c, + 0xb3,0xc3,0x91,0x3d,0xbf,0xc8,0x97,0x3f,0xd3,0xcb,0x9b,0x3e,0xe5,0xe5,0xcd,0x9e, + 0xf5,0xcf,0xa0,0x45,0xf2,0xcc,0x9a,0x38,0xf1,0xcd,0x9b,0x3c,0xed,0xcd,0x9d,0x40, + 0xe8,0xcc,0x9c,0x41,0xe2,0xca,0x99,0x40,0xda,0xc8,0x97,0x3f,0xd0,0xc5,0x93,0x3e, + 0xc3,0xc0,0x8e,0x3c,0xb5,0xbb,0x88,0x39,0xa5,0xb5,0x80,0x37,0x96,0xae,0x79,0x35, + 0x88,0xaa,0x72,0x32,0x7f,0xa9,0x73,0x32,0x7f,0xb1,0x7c,0x35,0x8d,0xbd,0x8a,0x3a, + 0xa9,0xc7,0x95,0x3f,0xcb,0xcd,0x9b,0x3f,0xe4,0xf1,0xe2,0xc7,0xfa,0xe8,0xd2,0xa6, + 0xf8,0xcc,0x9a,0x3c,0xe8,0xc9,0x98,0x40,0xd4,0xc4,0x91,0x3d,0xbd,0xbe,0x8c,0x3b, + 0xad,0xbf,0x8b,0x3b,0xac,0xc2,0x90,0x3d,0xb9,0xc8,0x96,0x3f,0xcb,0xcb,0x9b,0x41, + 0xde,0xce,0x9d,0x40,0xec,0xdb,0xb6,0x70,0xf6,0xfe,0xfd,0xfa,0xfe,0xd6,0xae,0x61, + 0xee,0xcb,0x99,0x40,0xd7,0xc3,0x8f,0x3d,0xb8,0xb6,0x81,0x37,0x95,0xa8,0x71,0x32, + 0x7b,0x9d,0x64,0x2d,0x6d,0x99,0x5f,0x2c,0x67,0x99,0x5f,0x2c,0x68,0x90,0x57,0x28, + 0x68,0x90,0x58,0x28,0x68,0x8f,0x56,0x27,0x66,0xa5,0x6f,0x30,0x82,0xb5,0x81,0x38, + 0x9f,0xc1,0x8f,0x3c,0xc1,0xc6,0x95,0x39,0xdf,0xe9,0xd4,0xad,0xf7,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfb,0xf8,0xf2,0xfe,0xea,0xd7,0xb0,0xfb,0xd8,0xb4,0x6e,0xf6,0xca,0x98,0x3b, + 0xee,0xc9,0x99,0x3f,0xe5,0xc8,0x97,0x3f,0xdb,0xc5,0x94,0x3e,0xd1,0xc5,0x94,0x3e, + 0xd0,0xc7,0x97,0x3f,0xd8,0xca,0x9a,0x40,0xe5,0xd0,0xa3,0x4d,0xf2,0xfb,0xf8,0xf1, + 0xfe,0xff,0xff,0xff,0xff,0xfc,0xfb,0xf7,0xff,0xf0,0xe2,0xc7,0xfc,0xe4,0xca,0x98, + 0xfa,0xd8,0xb3,0x6d,0xf6,0xcd,0x9e,0x42,0xf0,0xca,0x98,0x3b,0xe9,0xc9,0x99,0x40, + 0xe0,0xc7,0x96,0x3f,0xd4,0xc3,0x91,0x3d,0xc6,0xbe,0x8c,0x3a,0xb5,0xb8,0x85,0x38, + 0xa4,0xb1,0x7d,0x36,0x95,0xaf,0x7a,0x34,0x8f,0xb3,0x7f,0x36,0x98,0xbd,0x8a,0x3b, + 0xb1,0xc6,0x95,0x3e,0xd0,0xcb,0x99,0x3d,0xe9,0xf2,0xe6,0xcf,0xfc,0xfc,0xfb,0xf7, + 0xff,0xcd,0x9d,0x41,0xf2,0xca,0x9a,0x40,0xe4,0xc7,0x96,0x3f,0xd3,0xc4,0x93,0x3e, + 0xc9,0xc5,0x93,0x3e,0xca,0xc7,0x96,0x3f,0xd5,0xca,0x9a,0x40,0xe4,0xcc,0x9b,0x3d, + 0xef,0xe1,0xc3,0x8b,0xf9,0xff,0xff,0xff,0xff,0xf3,0xe7,0xd2,0xfc,0xcc,0x9e,0x46, + 0xea,0xc7,0x96,0x3e,0xd2,0xbe,0x8c,0x3b,0xb2,0xb0,0x7c,0x35,0x92,0xa2,0x6c,0x2f, + 0x79,0x98,0x60,0x2b,0x6d,0x94,0x5a,0x2a,0x67,0x94,0x5a,0x29,0x68,0x8c,0x54,0x26, + 0x68,0x8c,0x54,0x25,0x68,0x8a,0x52,0x26,0x66,0xa0,0x6b,0x2e,0x81,0xaf,0x7d,0x35, + 0x9c,0xbd,0x8b,0x3b,0xbe,0xc4,0x94,0x3d,0xda,0xd1,0xaa,0x5f,0xef,0xe5,0xcf,0xa4, + 0xf9,0xe5,0xcf,0xa4,0xfb,0xe6,0xcf,0xa4,0xfd,0xef,0xe2,0xc7,0xfe,0xfd,0xfb,0xf9, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe,0xfe,0xf7,0xf0,0xe2, + 0xfe,0xcf,0xa3,0x50,0xf5,0xc9,0x9a,0x3e,0xef,0xc9,0x98,0x3f,0xe9,0xc8,0x98,0x3f, + 0xe7,0xc9,0x9a,0x3f,0xec,0xca,0x9b,0x40,0xf3,0xcf,0xa2,0x4c,0xf8,0xfa,0xf5,0xed, + 0xfe,0xfe,0xfe,0xfd,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfe,0xfe,0xfd,0xfe,0xfd,0xfc,0xf9,0xfe,0xe5,0xcd,0xa1,0xfb,0xca,0x9a,0x3e, + 0xf2,0xc9,0x99,0x3f,0xeb,0xc7,0x97,0x3f,0xe1,0xc3,0x93,0x3d,0xd3,0xc0,0x8e,0x3b, + 0xc3,0xba,0x88,0x39,0xb2,0xb6,0x84,0x38,0xa7,0xb6,0x84,0x38,0xa8,0xbc,0x8b,0x3a, + 0xba,0xc4,0x93,0x3d,0xd3,0xc9,0x99,0x3e,0xea,0xe8,0xd3,0xac,0xfa,0xfe,0xfe,0xfd, + 0xfe,0xd7,0xb3,0x6c,0xf9,0xca,0x9b,0x40,0xf0,0xc9,0x99,0x3f,0xe7,0xc8,0x97,0x3f, + 0xe2,0xc7,0x98,0x3f,0xe4,0xca,0x9a,0x40,0xea,0xcb,0x9a,0x3e,0xf2,0xec,0xdb,0xb9, + 0xfc,0xff,0xff,0xff,0xff,0xf1,0xe5,0xcf,0xfd,0xca,0x98,0x3b,0xf0,0xc7,0x97,0x3f, + 0xe0,0xc1,0x8f,0x3c,0xc6,0xb5,0x84,0x38,0xa6,0xa7,0x73,0x32,0x89,0x9a,0x63,0x2b, + 0x75,0x92,0x5a,0x28,0x6b,0x8e,0x56,0x28,0x67,0x8f,0x56,0x28,0x68,0x86,0x4f,0x24, + 0x68,0x86,0x4f,0x24,0x68,0x85,0x4e,0x23,0x66,0x98,0x63,0x2b,0x7c,0xa8,0x74,0x32, + 0x92,0xb5,0x83,0x37,0xb0,0xbe,0x8d,0x3b,0xca,0xc2,0x92,0x3b,0xdc,0xc4,0x93,0x38, + 0xe7,0xc6,0x94,0x39,0xee,0xc7,0x96,0x3a,0xf4,0xc7,0x96,0x38,0xf9,0xc8,0x96,0x37, + 0xfc,0xd1,0xa9,0x5b,0xfe,0xdf,0xc3,0x8d,0xfe,0xf3,0xe8,0xd4,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xe7,0xd3,0xab,0xfb,0xc9,0x9a,0x40,0xf7,0xc8,0x99,0x3e, + 0xf6,0xc9,0x9a,0x3f,0xf7,0xc9,0x9a,0x40,0xfa,0xca,0x9b,0x40,0xfc,0xf5,0xed,0xdc, + 0xfe,0xfc,0xfb,0xf7,0xff,0xcf,0xa3,0x4e,0xff,0xd8,0xb5,0x72,0xfe,0xe5,0xcf,0xa4, + 0xff,0xf5,0xec,0xdb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfd,0xfb,0xf8, + 0xff,0xe9,0xd4,0xaf,0xfb,0xce,0xa4,0x54,0xf3,0xc5,0x95,0x3b,0xea,0xc4,0x95,0x3e, + 0xde,0xc0,0x90,0x3c,0xcf,0xbc,0x8c,0x3a,0xc2,0xbb,0x8a,0x3a,0xbd,0xbd,0x8d,0x3b, + 0xc6,0xc3,0x93,0x3d,0xd8,0xc7,0x98,0x3f,0xeb,0xda,0xb9,0x7b,0xf9,0xff,0xff,0xff, + 0xff,0xe6,0xd0,0xa5,0xfd,0xc9,0x99,0x3e,0xf9,0xc9,0x9a,0x40,0xf5,0xc9,0x9a,0x40, + 0xf2,0xc8,0x98,0x3c,0xf3,0xd0,0xa7,0x57,0xf8,0xf3,0xe9,0xd6,0xfd,0xff,0xff,0xff, + 0xff,0xec,0xdc,0xbc,0xfd,0xc9,0x9b,0x42,0xf3,0xc7,0x97,0x3f,0xe4,0xc0,0x90,0x3c, + 0xce,0xb8,0x86,0x38,0xb2,0xab,0x78,0x33,0x96,0x9d,0x68,0x2d,0x7e,0x92,0x5c,0x28, + 0x71,0x8c,0x54,0x26,0x6a,0x89,0x52,0x25,0x67,0x8a,0x52,0x25,0x68,0x80,0x4a,0x21, + 0x68,0x80,0x4a,0x21,0x68,0x80,0x49,0x21,0x67,0x8e,0x59,0x27,0x75,0x9b,0x68,0x2d, + 0x85,0xa8,0x76,0x32,0x9c,0xb3,0x82,0x36,0xb2,0xba,0x8a,0x39,0xc4,0xbe,0x8e,0x3b, + 0xd3,0xc2,0x92,0x3d,0xe0,0xc4,0x95,0x3d,0xeb,0xc6,0x97,0x3e,0xf4,0xc7,0x98,0x3f, + 0xfb,0xc8,0x99,0x3f,0xfd,0xc8,0x99,0x3f,0xfe,0xc6,0x96,0x39,0xff,0xdb,0xbb,0x7f, + 0xff,0xfd,0xfb,0xf8,0xff,0xff,0xff,0xff,0xff,0xfb,0xf8,0xf4,0xff,0xcb,0x9f,0x4c, + 0xfc,0xc8,0x99,0x3f,0xfd,0xc8,0x99,0x40,0xfd,0xc8,0x98,0x3d,0xfe,0xe0,0xc7,0x95, + 0xfe,0xff,0xff,0xff,0xfe,0xe1,0xc8,0x97,0xff,0xc7,0x98,0x3a,0xff,0xc8,0x99,0x3f, + 0xfd,0xc7,0x97,0x3a,0xfd,0xcc,0xa1,0x4e,0xfd,0xee,0xe0,0xc6,0xfe,0xfd,0xfc,0xfb, + 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdd,0xc1,0x8b,0xf9,0xc6,0x96,0x3e, + 0xf0,0xc3,0x94,0x3d,0xe6,0xc1,0x91,0x3d,0xdb,0xbf,0x90,0x3c,0xd3,0xbf,0x8f,0x3b, + 0xd5,0xc2,0x93,0x3d,0xe0,0xc5,0x96,0x3e,0xee,0xcb,0x9f,0x4b,0xf9,0xff,0xff,0xff, + 0xff,0xfb,0xf8,0xf2,0xff,0xc6,0x96,0x38,0xfc,0xc8,0x99,0x3f,0xfb,0xc8,0x99,0x3f, + 0xfb,0xd5,0xb1,0x6d,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe7,0xd3,0xad, + 0xfd,0xc7,0x96,0x3b,0xf7,0xc5,0x96,0x3e,0xeb,0xbf,0x90,0x3c,0xd6,0xb7,0x87,0x39, + 0xbc,0xac,0x7b,0x34,0x9e,0x9e,0x6b,0x2e,0x86,0x92,0x5c,0x28,0x75,0x89,0x53,0x25, + 0x6d,0x85,0x4e,0x23,0x69,0x84,0x4d,0x23,0x67,0x84,0x4d,0x23,0x68,0x7c,0x47,0x20, + 0x68,0x7c,0x46,0x20,0x68,0x7b,0x46,0x20,0x67,0x83,0x4e,0x22,0x6f,0x8d,0x59,0x27, + 0x79,0x99,0x67,0x2c,0x88,0xa5,0x73,0x31,0x9b,0xae,0x7e,0x35,0xaf,0xb6,0x86,0x38, + 0xc2,0xbb,0x8d,0x3a,0xd4,0xc0,0x92,0x3c,0xe5,0xc3,0x94,0x3d,0xf1,0xc5,0x97,0x3e, + 0xf9,0xc6,0x97,0x3f,0xfd,0xc6,0x98,0x3f,0xfe,0xc6,0x98,0x3f,0xff,0xc5,0x96,0x3b, + 0xff,0xce,0xa7,0x5a,0xff,0xfc,0xfa,0xf6,0xff,0xff,0xff,0xff,0xfe,0xf3,0xe9,0xd5, + 0xfe,0xc5,0x96,0x3b,0xfe,0xc6,0x98,0x3f,0xfe,0xc6,0x98,0x3f,0xfe,0xc8,0x9a,0x44, + 0xfe,0xff,0xff,0xff,0xff,0xfd,0xfc,0xf9,0xff,0xc5,0x96,0x3b,0xfe,0xc6,0x98,0x3f, + 0xfe,0xc6,0x98,0x3f,0xfc,0xc5,0x97,0x3e,0xf9,0xc3,0x94,0x37,0xf8,0xcb,0xa3,0x54, + 0xf9,0xe0,0xc8,0x9a,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf3,0xea,0xd9, + 0xfd,0xc8,0x9d,0x4c,0xf4,0xc2,0x93,0x3b,0xed,0xc1,0x92,0x3c,0xe6,0xc1,0x92,0x3c, + 0xe5,0xc2,0x94,0x3d,0xea,0xc4,0x95,0x3e,0xf2,0xc3,0x93,0x35,0xfa,0xf3,0xe8,0xd6, + 0xfe,0xff,0xff,0xff,0xff,0xda,0xbd,0x83,0xfe,0xc5,0x96,0x3b,0xfe,0xec,0xdd,0xbf, + 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdd,0xc2,0x8d,0xfe,0xc6,0x97,0x3d, + 0xfb,0xc5,0x96,0x3e,0xf4,0xc1,0x92,0x3c,0xe4,0xba,0x8a,0x3a,0xcc,0xb0,0x80,0x35, + 0xaf,0xa3,0x70,0x30,0x93,0x94,0x60,0x29,0x7e,0x88,0x54,0x25,0x71,0x82,0x4d,0x22, + 0x6b,0x80,0x4a,0x21,0x69,0x7f,0x49,0x21,0x67,0x7f,0x49,0x21,0x68,0x76,0x42,0x1d, + 0x68,0x77,0x42,0x1d,0x68,0x76,0x42,0x1e,0x67,0x79,0x46,0x1f,0x6b,0x81,0x4d,0x22, + 0x71,0x8d,0x5a,0x26,0x7e,0x9a,0x69,0x2d,0x8f,0xa7,0x77,0x31,0xa5,0xb1,0x82,0x36, + 0xbe,0xb9,0x8a,0x39,0xd4,0xbe,0x8f,0x3b,0xe6,0xc1,0x93,0x3d,0xf2,0xc2,0x95,0x3d, + 0xfa,0xc3,0x95,0x3b,0xfd,0xc3,0x94,0x3c,0xfe,0xc7,0x9c,0x47,0xff,0xca,0xa1,0x52, + 0xff,0xcb,0xa4,0x56,0xff,0xf9,0xf4,0xeb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xc2,0x92,0x36,0xfd,0xc4,0x96,0x3d,0xfd,0xc4,0x96,0x3d,0xfd,0xc2,0x92,0x35, + 0xfd,0xf1,0xe8,0xd5,0xfe,0xff,0xff,0xff,0xff,0xd6,0xb6,0x79,0xfe,0xc4,0x96,0x3d, + 0xfc,0xc2,0x95,0x3d,0xf8,0xc2,0x94,0x3d,0xf3,0xc1,0x92,0x3d,0xef,0xc1,0x92,0x3c, + 0xee,0xc0,0x91,0x3a,0xf2,0xc7,0x9c,0x4a,0xf6,0xf2,0xe9,0xd7,0xfd,0xff,0xff,0xff, + 0xff,0xff,0xff,0xfe,0xff,0xcc,0xa6,0x5c,0xf8,0xc2,0x93,0x3c,0xf4,0xc2,0x94,0x3c, + 0xf1,0xc2,0x94,0x3d,0xf3,0xc2,0x94,0x3e,0xf7,0xc2,0x94,0x3a,0xfb,0xd6,0xb7,0x7b, + 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xfe,0xfe,0xfe,0xfe,0xff,0xd6,0xb6,0x78,0xff,0xc4,0x96,0x3c,0xfe,0xc4,0x96,0x3e, + 0xfb,0xc2,0x94,0x3d,0xf4,0xbf,0x90,0x3c,0xe4,0xb8,0x88,0x39,0xcc,0xad,0x7d,0x34, + 0xb0,0xa0,0x6f,0x2f,0x96,0x93,0x60,0x29,0x82,0x87,0x53,0x24,0x74,0x7f,0x4b,0x20, + 0x6d,0x7b,0x46,0x1f,0x69,0x7a,0x45,0x1f,0x67,0x7a,0x45,0x1f,0x68,0x71,0x3d,0x1c, + 0x68,0x71,0x3d,0x1c,0x68,0x71,0x3e,0x1c,0x67,0x74,0x40,0x1d,0x6a,0x7b,0x48,0x20, + 0x70,0x88,0x56,0x25,0x7d,0x98,0x68,0x2c,0x92,0xa8,0x78,0x32,0xad,0xb2,0x84,0x37, + 0xc8,0xb9,0x8c,0x3a,0xde,0xbe,0x90,0x3c,0xed,0xbe,0x8e,0x35,0xf7,0xc3,0x98,0x45, + 0xfc,0xe1,0xca,0xa0,0xfe,0xf5,0xec,0xde,0xff,0xf9,0xf4,0xeb,0xfe,0xfc,0xf9,0xf5, + 0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xed,0xdf,0xc6, + 0xfe,0xc0,0x92,0x3a,0xfa,0xc1,0x93,0x3d,0xf9,0xc1,0x93,0x3d,0xf9,0xc1,0x93,0x3b, + 0xfb,0xda,0xc0,0x8d,0xfe,0xff,0xff,0xff,0xff,0xeb,0xdc,0xc0,0xfe,0xc1,0x93,0x3c, + 0xfb,0xc0,0x92,0x3c,0xf4,0xbe,0x90,0x3b,0xea,0xbb,0x8d,0x3a,0xe1,0xba,0x8c,0x3a, + 0xde,0xbb,0x8d,0x3b,0xe3,0xbd,0x8f,0x3a,0xeb,0xc0,0x92,0x3c,0xf4,0xdc,0xc3,0x92, + 0xfb,0xff,0xff,0xff,0xff,0xfc,0xfa,0xf7,0xfe,0xc4,0x9a,0x48,0xfb,0xc1,0x93,0x3c, + 0xf9,0xc1,0x94,0x3d,0xf9,0xc1,0x94,0x3d,0xfb,0xc2,0x94,0x3d,0xfd,0xc4,0x97,0x41, + 0xfe,0xfc,0xf9,0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfd,0xfd,0xfb,0xff,0xea,0xda,0xbc,0xff,0xc5,0x9a,0x48,0xfd,0xc0,0x91,0x36, + 0xfc,0xc1,0x93,0x3d,0xf6,0xbe,0x90,0x3b,0xeb,0xb9,0x8a,0x39,0xd8,0xb1,0x82,0x36, + 0xc0,0xa7,0x77,0x31,0xa8,0x9a,0x69,0x2c,0x92,0x8c,0x5b,0x27,0x7f,0x82,0x4e,0x22, + 0x73,0x79,0x45,0x1f,0x6b,0x74,0x40,0x1d,0x67,0x74,0x41,0x1d,0x68,0x6b,0x39,0x1a, + 0x68,0x6b,0x38,0x19,0x68,0x6b,0x39,0x1a,0x67,0x70,0x3e,0x1b,0x6b,0x7b,0x48,0x1f, + 0x74,0x8a,0x5a,0x26,0x85,0x9d,0x6d,0x2e,0x9f,0xab,0x7d,0x34,0xbd,0xb5,0x87,0x38, + 0xd8,0xba,0x8b,0x37,0xeb,0xc9,0xa4,0x5e,0xf7,0xe9,0xd9,0xbd,0xfd,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfb,0xf9,0xf4,0xfe,0xf5,0xee,0xe1,0xfe,0xea,0xdc,0xc1,0xfe,0xc3,0x98,0x49, + 0xfa,0xbd,0x91,0x3b,0xf4,0xbc,0x8f,0x3b,0xf0,0xbc,0x8f,0x3b,0xf1,0xbd,0x90,0x3b, + 0xf5,0xc9,0xa4,0x5c,0xfa,0xfd,0xfc,0xfb,0xfe,0xfe,0xfe,0xfd,0xff,0xc1,0x96,0x43, + 0xfb,0xbd,0x8f,0x3a,0xf2,0xb9,0x8c,0x3a,0xe4,0xb6,0x87,0x38,0xd6,0xb3,0x85,0x37, + 0xcf,0xb4,0x86,0x37,0xd2,0xb8,0x8a,0x38,0xde,0xbb,0x8e,0x3a,0xec,0xbb,0x8b,0x31, + 0xf6,0xdf,0xc9,0x9e,0xfd,0xff,0xff,0xff,0xff,0xf2,0xe9,0xd9,0xfe,0xc0,0x94,0x3e, + 0xfd,0xbf,0x93,0x3c,0xfd,0xc0,0x93,0x3c,0xfd,0xc0,0x93,0x3c,0xfe,0xc0,0x93,0x3d, + 0xfe,0xec,0xdf,0xc6,0xff,0xff,0xff,0xff,0xff,0xfa,0xf7,0xf0,0xff,0xf3,0xec,0xdd, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xe6,0xd4,0xb3, + 0xfe,0xca,0xa5,0x5d,0xfb,0xbd,0x8e,0x37,0xf3,0xbb,0x8d,0x3a,0xe8,0xb6,0x88,0x38, + 0xd6,0xaf,0x80,0x35,0xc1,0xa4,0x75,0x31,0xab,0x97,0x67,0x2b,0x93,0x88,0x56,0x25, + 0x7f,0x79,0x46,0x1f,0x70,0x6f,0x3b,0x1b,0x67,0x70,0x3c,0x1b,0x68,0x67,0x35,0x18, + 0x68,0x67,0x35,0x18,0x68,0x66,0x34,0x17,0x67,0x6c,0x3b,0x1a,0x6c,0x7a,0x49,0x1f, + 0x78,0x8e,0x5e,0x27,0x8e,0xa1,0x73,0x2f,0xae,0xaf,0x81,0x35,0xce,0xb6,0x89,0x37, + 0xe6,0xd1,0xb3,0x7a,0xf7,0xfd,0xfc,0xfa,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xfe,0xf2,0xe9,0xd9,0xff,0xd9,0xc0,0x90,0xff,0xcc,0xa8,0x66,0xff,0xc1,0x97,0x46, + 0xff,0xc0,0x95,0x44,0xff,0xbf,0x93,0x40,0xfe,0xbd,0x91,0x3b,0xfb,0xbb,0x8e,0x3b, + 0xf5,0xb9,0x8c,0x39,0xeb,0xb7,0x89,0x39,0xe4,0xb7,0x89,0x39,0xe4,0xb9,0x8b,0x39, + 0xec,0xba,0x8d,0x38,0xf6,0xfa,0xf6,0xf0,0xfe,0xff,0xff,0xff,0xff,0xe5,0xd5,0xb5, + 0xfd,0xb9,0x8a,0x33,0xf3,0xb7,0x8a,0x38,0xe5,0xb2,0x85,0x37,0xd5,0xae,0x80,0x35, + 0xc9,0xae,0x80,0x35,0xca,0xb3,0x85,0x37,0xd5,0xb8,0x8b,0x39,0xe6,0xbb,0x8e,0x3b, + 0xf3,0xbe,0x92,0x40,0xfb,0xf3,0xeb,0xdc,0xfe,0xff,0xff,0xff,0xff,0xcb,0xa6,0x62, + 0xff,0xbe,0x90,0x3b,0xfd,0xbe,0x91,0x3c,0xfe,0xbe,0x91,0x3c,0xfe,0xbf,0x92,0x3b, + 0xff,0xd7,0xbc,0x87,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc1,0x95,0x42, + 0xff,0xc6,0x9f,0x54,0xff,0xed,0xe1,0xca,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfd,0xfc,0xfb,0xfe,0xeb,0xdd,0xc5,0xfc,0xbd,0x90,0x3c,0xf5,0xb8,0x8b,0x39, + 0xe9,0xb5,0x87,0x38,0xda,0xad,0x7f,0x35,0xc5,0xa1,0x73,0x2f,0xaa,0x92,0x62,0x29, + 0x90,0x7c,0x4b,0x20,0x77,0x69,0x37,0x18,0x67,0x6a,0x38,0x19,0x68,0x63,0x32,0x16, + 0x68,0x63,0x32,0x16,0x68,0x62,0x31,0x16,0x67,0x6b,0x3a,0x19,0x6e,0x7b,0x4a,0x20, + 0x7c,0x91,0x62,0x29,0x95,0xa4,0x77,0x31,0xb7,0xb0,0x83,0x36,0xd8,0xba,0x8f,0x40, + 0xef,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf5,0xef,0xe4,0xff,0xca,0xa7,0x64, + 0xff,0xb8,0x89,0x30,0xff,0xba,0x8d,0x35,0xff,0xbb,0x8e,0x38,0xff,0xbc,0x90,0x3a, + 0xff,0xbb,0x90,0x3a,0xff,0xbb,0x8f,0x3a,0xfd,0xbb,0x8e,0x3a,0xfa,0xb9,0x8c,0x39, + 0xf1,0xb4,0x88,0x38,0xe4,0xb0,0x84,0x36,0xd8,0xb1,0x84,0x36,0xd7,0xb4,0x87,0x38, + 0xe2,0xb7,0x89,0x34,0xef,0xda,0xc1,0x94,0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xfe,0xc0,0x97,0x4b,0xf7,0xb7,0x8b,0x39,0xeb,0xb3,0x86,0x37,0xdd,0xaf,0x82,0x36, + 0xd2,0xaf,0x81,0x35,0xd0,0xb1,0x84,0x36,0xd9,0xb6,0x89,0x38,0xe7,0xb9,0x8d,0x39, + 0xf3,0xbb,0x8e,0x3a,0xfb,0xe2,0xcf,0xac,0xfe,0xff,0xff,0xff,0xff,0xea,0xdd,0xc3, + 0xfe,0xb9,0x8b,0x32,0xff,0xbc,0x8f,0x3a,0xff,0xbc,0x8f,0x3b,0xff,0xbc,0x90,0x3a, + 0xff,0xbe,0x92,0x3e,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe3,0xd0,0xac, + 0xff,0xbc,0x8f,0x38,0xff,0xb9,0x8a,0x31,0xff,0xc6,0xa0,0x57,0xff,0xe2,0xd1,0xad, + 0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xfd,0xfc,0xfb,0xff,0xd6,0xbb,0x89, + 0xf9,0xb5,0x87,0x32,0xec,0xb2,0x84,0x37,0xda,0xa8,0x7b,0x32,0xc0,0x99,0x69,0x2c, + 0xa1,0x80,0x50,0x22,0x7f,0x63,0x32,0x17,0x67,0x65,0x33,0x17,0x68,0x61,0x30,0x15, + 0x68,0x61,0x30,0x15,0x68,0x61,0x30,0x15,0x67,0x6b,0x3a,0x19,0x6f,0x7b,0x4c,0x20, + 0x7d,0x91,0x63,0x29,0x98,0xa4,0x77,0x31,0xbc,0xb1,0x83,0x34,0xdb,0xd2,0xb7,0x85, + 0xf5,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xce,0xae,0x72,0xff,0xbb,0x8e,0x3a, + 0xff,0xbb,0x8e,0x3b,0xff,0xbb,0x8f,0x3a,0xff,0xbb,0x8f,0x3a,0xff,0xbb,0x8e,0x3a, + 0xff,0xbc,0x8e,0x3a,0xff,0xbb,0x90,0x3c,0xfd,0xbb,0x8e,0x3a,0xfa,0xb8,0x8a,0x39, + 0xef,0xb2,0x86,0x37,0xdf,0xad,0x80,0x35,0xcf,0xad,0x80,0x34,0xcd,0xb1,0x84,0x36, + 0xd9,0xb6,0x8a,0x38,0xeb,0xb7,0x8b,0x36,0xf7,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe, + 0xff,0xd9,0xbf,0x91,0xfc,0xb8,0x8c,0x38,0xf4,0xb6,0x89,0x39,0xea,0xb3,0x86,0x37, + 0xe3,0xb4,0x87,0x38,0xe1,0xb4,0x88,0x37,0xe6,0xb6,0x8a,0x38,0xed,0xb9,0x8d,0x39, + 0xf6,0xba,0x8e,0x3a,0xfc,0xe5,0xd4,0xb4,0xfe,0xff,0xff,0xff,0xfe,0xef,0xe6,0xd3, + 0xff,0xb8,0x8a,0x31,0xfe,0xbb,0x8e,0x3b,0xfe,0xbb,0x8f,0x3b,0xfe,0xbc,0x8e,0x3b, + 0xff,0xb9,0x8c,0x34,0xfe,0xe1,0xce,0xaa,0xff,0xff,0xff,0xff,0xff,0xf8,0xf4,0xec, + 0xff,0xbf,0x95,0x45,0xff,0xbb,0x8e,0x3a,0xff,0xbb,0x8f,0x3b,0xff,0xbb,0x8f,0x39, + 0xff,0xc0,0x96,0x48,0xff,0xf6,0xf1,0xe6,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, + 0xff,0xe2,0xcf,0xae,0xf9,0xb5,0x89,0x38,0xe7,0xad,0x80,0x34,0xce,0x9e,0x71,0x2e, + 0xae,0x84,0x54,0x23,0x86,0x61,0x30,0x15,0x66,0x62,0x31,0x16,0x68,0x60,0x2f,0x15, + 0x68,0x60,0x2f,0x15,0x68,0x5f,0x2e,0x15,0x67,0x69,0x38,0x18,0x6e,0x78,0x49,0x1e, + 0x7c,0x8f,0x60,0x28,0x96,0xa2,0x75,0x30,0xb8,0xaf,0x83,0x35,0xd9,0xba,0x90,0x43, + 0xee,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf2,0xe9,0xda,0xff,0xc1,0x9a,0x4f, + 0xff,0xb7,0x88,0x2f,0xff,0xba,0x8d,0x38,0xff,0xbb,0x8e,0x3a,0xff,0xba,0x8e,0x39, + 0xff,0xb8,0x8a,0x33,0xfe,0xe3,0xd2,0xb1,0xfe,0xed,0xe1,0xcb,0xfd,0xb6,0x8b,0x39, + 0xf0,0xb2,0x85,0x36,0xdd,0xab,0x7e,0x34,0xcc,0xa9,0x7b,0x33,0xc7,0xad,0x80,0x35, + 0xd3,0xb3,0x87,0x37,0xe5,0xb8,0x8c,0x39,0xf4,0xf7,0xf3,0xea,0xfe,0xff,0xff,0xff, + 0xff,0xfa,0xf7,0xf2,0xfe,0xb7,0x89,0x33,0xfa,0xb4,0x86,0x2f,0xf6,0xb5,0x86,0x32, + 0xf1,0xb4,0x86,0x31,0xf0,0xb5,0x87,0x32,0xf2,0xb6,0x87,0x32,0xf6,0xba,0x8d,0x39, + 0xfb,0xdb,0xc4,0x98,0xfe,0xfd,0xfc,0xfa,0xff,0xff,0xff,0xff,0xff,0xcf,0xb0,0x76, + 0xfd,0xba,0x8d,0x38,0xfc,0xba,0x8e,0x3a,0xfc,0xbb,0x8e,0x3b,0xfd,0xb9,0x8a,0x33, + 0xfe,0xc2,0x9b,0x50,0xff,0xc7,0xa2,0x5c,0xff,0xfd,0xfc,0xfa,0xff,0xff,0xff,0xff, + 0xff,0xd4,0xb9,0x84,0xff,0xb9,0x8b,0x35,0xff,0xbb,0x8f,0x3b,0xff,0xbb,0x8f,0x3a, + 0xff,0xba,0x8d,0x37,0xff,0xb8,0x8b,0x34,0xff,0xf1,0xe9,0xd8,0xff,0xff,0xff,0xff, + 0xfe,0xfe,0xfd,0xfc,0xff,0xb9,0x8f,0x43,0xee,0xaf,0x82,0x35,0xd6,0xa1,0x74,0x2f, + 0xb5,0x86,0x57,0x24,0x89,0x5f,0x2e,0x15,0x66,0x61,0x30,0x15,0x68,0x5e,0x2d,0x14, + 0x68,0x5e,0x2d,0x14,0x68,0x5e,0x2d,0x14,0x67,0x66,0x36,0x17,0x6d,0x73,0x43,0x1c, + 0x78,0x88,0x59,0x25,0x8e,0x9c,0x6e,0x2d,0xad,0xaa,0x7d,0x34,0xcc,0xb2,0x86,0x36, + 0xe5,0xc9,0xa8,0x6b,0xf5,0xfb,0xf8,0xf4,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xfe,0xe9,0xdc,0xc4,0xff,0xca,0xa8,0x69,0xff,0xc0,0x98,0x4c,0xff,0xc1,0x9a,0x4f, + 0xff,0xd1,0xb3,0x7b,0xff,0xfa,0xf6,0xf0,0xfe,0xff,0xff,0xff,0xff,0xbd,0x96,0x4e, + 0xef,0xb0,0x83,0x35,0xdb,0xa8,0x7b,0x33,0xc7,0xa5,0x78,0x31,0xc0,0xaa,0x7d,0x33, + 0xcb,0xb1,0x84,0x35,0xdf,0xbf,0x99,0x51,0xf2,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xfe,0xfe,0xfe,0xfe,0xff,0xff,0xff,0xff,0xf0,0xe7,0xd6,0xfe,0xe1,0xcf,0xac, + 0xfc,0xe1,0xd0,0xae,0xfc,0xe1,0xd0,0xad,0xfc,0xe5,0xd5,0xb6,0xfd,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfe,0xe9,0xdc,0xc3,0xfd,0xb9,0x8d,0x3a, + 0xf8,0xb8,0x8c,0x39,0xf7,0xb8,0x8c,0x39,0xf8,0xb7,0x89,0x33,0xfa,0xdf,0xca,0xa5, + 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xf4,0xed,0xe1,0xff,0xc7,0xa1,0x5c,0xff,0xc2,0x9a,0x4f,0xff,0xc1,0x99,0x4e, + 0xff,0xce,0xad,0x71,0xff,0xe6,0xd6,0xb9,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, + 0xff,0xfd,0xfc,0xfb,0xff,0xb9,0x8f,0x42,0xed,0xae,0x81,0x35,0xd6,0xa1,0x73,0x2f, + 0xb4,0x84,0x56,0x24,0x89,0x5e,0x2d,0x14,0x66,0x5f,0x2e,0x14,0x68,0x5d,0x2c,0x14, + 0x68,0x5d,0x2c,0x14,0x68,0x5d,0x2c,0x13,0x67,0x61,0x31,0x15,0x6b,0x6c,0x3c,0x1a, + 0x73,0x7e,0x4f,0x21,0x84,0x91,0x63,0x29,0x9d,0xa2,0x75,0x2f,0xba,0xac,0x80,0x34, + 0xd4,0xb2,0x84,0x34,0xe6,0xbe,0x97,0x4e,0xf3,0xe1,0xcf,0xad,0xfb,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xf1,0xe9,0xdc,0xfd,0xb0,0x82,0x2f, + 0xe9,0xad,0x80,0x34,0xd4,0xa4,0x77,0x31,0xbe,0x9f,0x72,0x2f,0xb4,0xa4,0x77,0x31, + 0xbe,0xad,0x80,0x34,0xd3,0xb2,0x85,0x35,0xe7,0xcb,0xac,0x73,0xf6,0xf9,0xf5,0xee, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xe2,0xd2,0xb1,0xfb,0xc5,0xa2,0x62,0xf5,0xb5,0x88,0x37,0xf0,0xb4,0x88,0x38, + 0xea,0xb4,0x87,0x37,0xe9,0xb4,0x88,0x38,0xeb,0xb4,0x87,0x34,0xf1,0xd0,0xb4,0x7f, + 0xf9,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfe, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xce,0xb1,0x7c,0xf5,0xb3,0x86,0x37,0xe5,0xaa,0x7d,0x33,0xcd,0x9c,0x6d,0x2d, + 0xac,0x80,0x51,0x22,0x85,0x5c,0x2b,0x13,0x67,0x5e,0x2d,0x14,0x68,0x5b,0x2b,0x13, + 0x68,0x5b,0x2b,0x12,0x68,0x5b,0x2b,0x12,0x67,0x5d,0x2d,0x13,0x69,0x64,0x34,0x16, + 0x6e,0x71,0x42,0x1c,0x79,0x83,0x54,0x23,0x8b,0x94,0x67,0x2a,0xa3,0xa2,0x74,0x30, + 0xbb,0xaa,0x7d,0x33,0xd1,0xb0,0x83,0x36,0xe0,0xb1,0x83,0x30,0xea,0xb3,0x87,0x33, + 0xf1,0xcd,0xb0,0x79,0xf7,0xe3,0xd3,0xb5,0xfb,0xf0,0xe8,0xd8,0xfd,0xf5,0xf0,0xe5, + 0xfd,0xf7,0xf3,0xea,0xfd,0xea,0xdf,0xc9,0xfb,0xb7,0x8c,0x3f,0xee,0xaf,0x82,0x35, + 0xdd,0xa6,0x79,0x32,0xc6,0x9a,0x6e,0x2d,0xae,0x95,0x67,0x2a,0xa4,0x99,0x6d,0x2c, + 0xac,0xa4,0x77,0x31,0xc1,0xad,0x80,0x35,0xd7,0xb1,0x84,0x33,0xe7,0xba,0x91,0x46, + 0xf1,0xe6,0xd8,0xbe,0xfa,0xb8,0x8e,0x40,0xf5,0xc7,0xa6,0x69,0xf7,0xcf,0xb4,0x80, + 0xf7,0xcf,0xb3,0x7f,0xf7,0xcc,0xad,0x76,0xf6,0xbf,0x98,0x51,0xf3,0xb1,0x82,0x2d, + 0xef,0xb1,0x83,0x30,0xeb,0xb0,0x84,0x36,0xe3,0xae,0x81,0x34,0xdb,0xab,0x7f,0x34, + 0xd3,0xaa,0x7d,0x34,0xd0,0xac,0x80,0x34,0xd5,0xb0,0x83,0x36,0xdf,0xb2,0x84,0x33, + 0xea,0xba,0x92,0x48,0xf2,0xda,0xc4,0x9b,0xf9,0xee,0xe3,0xd1,0xfc,0xf3,0xec,0xe0, + 0xfd,0xf6,0xf1,0xe7,0xfd,0xf7,0xf2,0xea,0xfe,0xf6,0xf1,0xe8,0xfd,0xf4,0xee,0xe2, + 0xfd,0xf1,0xe8,0xd9,0xfd,0xe6,0xd7,0xbc,0xfb,0xce,0xb0,0x7b,0xf7,0xb2,0x85,0x32, + 0xef,0xb1,0x84,0x34,0xe5,0xac,0x80,0x34,0xd4,0xa2,0x75,0x30,0xbb,0x91,0x63,0x29, + 0x9e,0x77,0x48,0x1f,0x7e,0x5b,0x2a,0x12,0x67,0x5c,0x2c,0x13,0x68,0x59,0x2a,0x12, + 0x68,0x59,0x2a,0x12,0x68,0x5a,0x2a,0x13,0x67,0x5a,0x2b,0x13,0x68,0x5d,0x2e,0x14, + 0x6b,0x65,0x35,0x17,0x71,0x72,0x44,0x1c,0x7b,0x82,0x54,0x22,0x8b,0x91,0x63,0x29, + 0x9f,0x9c,0x6f,0x2d,0xb3,0xa5,0x78,0x31,0xc5,0xaa,0x7d,0x34,0xd2,0xad,0x82,0x35, + 0xdc,0xb0,0x83,0x34,0xe3,0xb1,0x84,0x34,0xe8,0xb3,0x87,0x38,0xeb,0xb6,0x8c,0x3f, + 0xed,0xb6,0x8d,0x41,0xec,0xb2,0x86,0x37,0xe7,0xad,0x81,0x35,0xdc,0xa7,0x7b,0x32, + 0xca,0x9b,0x6e,0x2e,0xb1,0x8d,0x60,0x27,0x9a,0x86,0x58,0x24,0x90,0x8b,0x5c,0x26, + 0x96,0x96,0x69,0x2b,0xa8,0xa1,0x75,0x30,0xbd,0xaa,0x7d,0x33,0xd0,0xae,0x81,0x35, + 0xdc,0xaf,0x82,0x34,0xe2,0xb0,0x84,0x36,0xe4,0xb0,0x83,0x35,0xe2,0xb0,0x83,0x35, + 0xe2,0xaf,0x83,0x35,0xe0,0xae,0x82,0x34,0xdf,0xad,0x81,0x35,0xdc,0xac,0x80,0x34, + 0xd9,0xaa,0x7e,0x33,0xd1,0xa6,0x79,0x31,0xc7,0xa1,0x74,0x30,0xbb,0x9c,0x6f,0x2d, + 0xb2,0x9a,0x6e,0x2d,0xaf,0x9e,0x71,0x2e,0xb6,0xa5,0x78,0x31,0xc4,0xaa,0x7e,0x34, + 0xd3,0xaf,0x82,0x35,0xde,0xb1,0x84,0x34,0xe5,0xb2,0x86,0x36,0xea,0xb5,0x8a,0x3d, + 0xec,0xb6,0x8c,0x41,0xee,0xb7,0x8e,0x41,0xef,0xb7,0x8d,0x41,0xee,0xb6,0x8b,0x3e, + 0xed,0xb4,0x88,0x3a,0xeb,0xb1,0x84,0x35,0xe8,0xb0,0x83,0x35,0xe3,0xad,0x81,0x34, + 0xdb,0xa8,0x7c,0x33,0xce,0xa1,0x74,0x2f,0xbb,0x94,0x67,0x2a,0xa3,0x83,0x55,0x23, + 0x8c,0x6c,0x3e,0x1a,0x76,0x5a,0x2a,0x12,0x67,0x5a,0x2a,0x13,0x68,0x57,0x28,0x11, + 0x68,0x58,0x28,0x11,0x68,0x58,0x28,0x11,0x67,0x58,0x28,0x11,0x68,0x59,0x29,0x11, + 0x69,0x5c,0x2d,0x13,0x6b,0x64,0x35,0x16,0x70,0x6f,0x41,0x1b,0x79,0x7c,0x4e,0x20, + 0x86,0x89,0x5b,0x25,0x95,0x93,0x66,0x2a,0xa4,0x9a,0x6e,0x2d,0xb1,0xa1,0x73,0x30, + 0xbd,0xa4,0x78,0x31,0xc6,0xa7,0x7a,0x32,0xcd,0xa8,0x7c,0x33,0xd1,0xaa,0x7d,0x33, + 0xd4,0xa9,0x7d,0x33,0xd2,0xa7,0x7a,0x32,0xcc,0xa2,0x76,0x30,0xc1,0x99,0x6c,0x2d, + 0xaf,0x8c,0x5e,0x26,0x99,0x7d,0x4f,0x21,0x87,0x74,0x45,0x1d,0x7e,0x77,0x49,0x1f, + 0x81,0x84,0x55,0x24,0x8e,0x91,0x63,0x29,0xa0,0x9a,0x6d,0x2d,0xb1,0xa0,0x74,0x30, + 0xbe,0xa3,0x77,0x31,0xc4,0xa4,0x77,0x31,0xc5,0xa4,0x78,0x30,0xc4,0xa2,0x76,0x31, + 0xc2,0xa2,0x75,0x30,0xc0,0xa1,0x75,0x30,0xbf,0xa0,0x74,0x2f,0xbc,0x9d,0x71,0x2e, + 0xb7,0x99,0x6c,0x2d,0xaf,0x93,0x66,0x2a,0xa5,0x8d,0x5f,0x27,0x9a,0x86,0x59,0x25, + 0x91,0x85,0x57,0x24,0x90,0x8a,0x5c,0x26,0x97,0x93,0x66,0x2a,0xa4,0x9b,0x6e,0x2d, + 0xb3,0xa1,0x75,0x30,0xbf,0xa6,0x79,0x31,0xc9,0xa9,0x7c,0x33,0xcf,0xaa,0x7d,0x33, + 0xd3,0xab,0x7e,0x33,0xd5,0xab,0x7f,0x33,0xd6,0xab,0x7f,0x33,0xd5,0xaa,0x7e,0x33, + 0xd4,0xa9,0x7d,0x33,0xd1,0xa7,0x7b,0x32,0xcc,0xa4,0x78,0x31,0xc5,0xa0,0x73,0x2f, + 0xbb,0x99,0x6c,0x2c,0xae,0x8f,0x62,0x28,0x9d,0x82,0x53,0x23,0x8c,0x73,0x44,0x1c, + 0x7c,0x63,0x33,0x16,0x6f,0x58,0x29,0x11,0x67,0x59,0x29,0x12,0x68,0x56,0x27,0x11, + 0x68,0x56,0x27,0x11,0x68,0x56,0x27,0x11,0x68,0x57,0x27,0x12,0x67,0x57,0x27,0x12, + 0x68,0x57,0x28,0x11,0x69,0x5a,0x2b,0x12,0x6b,0x61,0x32,0x15,0x6f,0x68,0x39,0x18, + 0x75,0x72,0x44,0x1c,0x7e,0x7b,0x4d,0x20,0x87,0x84,0x56,0x24,0x91,0x8b,0x5e,0x27, + 0x9a,0x91,0x64,0x29,0xa3,0x95,0x68,0x2b,0xaa,0x98,0x6b,0x2d,0xae,0x99,0x6c,0x2c, + 0xb0,0x99,0x6c,0x2c,0xaf,0x96,0x69,0x2b,0xaa,0x8f,0x62,0x28,0xa0,0x85,0x58,0x24, + 0x93,0x78,0x4a,0x1e,0x83,0x6b,0x3d,0x19,0x78,0x64,0x35,0x16,0x71,0x67,0x38,0x17, + 0x74,0x6f,0x41,0x1b,0x7b,0x7b,0x4d,0x1f,0x87,0x85,0x58,0x24,0x92,0x8c,0x5e,0x27, + 0x9b,0x90,0x62,0x28,0xa1,0x90,0x63,0x29,0xa1,0x8f,0x62,0x29,0x9f,0x8e,0x61,0x28, + 0x9f,0x8d,0x60,0x28,0x9d,0x8d,0x5f,0x27,0x9c,0x8a,0x5d,0x27,0x99,0x86,0x59,0x25, + 0x94,0x83,0x55,0x23,0x8f,0x7b,0x4e,0x20,0x87,0x74,0x46,0x1d,0x80,0x6e,0x40,0x1b, + 0x7a,0x6e,0x3f,0x1b,0x79,0x73,0x44,0x1c,0x7e,0x7c,0x4e,0x21,0x87,0x86,0x58,0x25, + 0x92,0x8d,0x60,0x28,0x9d,0x93,0x66,0x2a,0xa6,0x96,0x69,0x2b,0xab,0x99,0x6c,0x2d, + 0xb0,0x9a,0x6d,0x2d,0xb2,0x9a,0x6e,0x2d,0xb3,0x9a,0x6d,0x2d,0xb2,0x99,0x6c,0x2d, + 0xb1,0x98,0x6b,0x2c,0xae,0x95,0x68,0x2b,0xa9,0x90,0x63,0x28,0xa2,0x8b,0x5d,0x26, + 0x9a,0x83,0x55,0x23,0x8f,0x79,0x4b,0x1f,0x84,0x6e,0x3f,0x1a,0x79,0x63,0x35,0x16, + 0x71,0x5c,0x2c,0x13,0x6b,0x57,0x27,0x11,0x67,0x57,0x28,0x12,0x68,0x54,0x25,0x10, + 0x68,0x54,0x25,0x10,0x68,0x54,0x25,0x10,0x68,0x54,0x25,0x10,0x68,0x54,0x25,0x10, + 0x67,0x55,0x25,0x11,0x68,0x55,0x26,0x10,0x69,0x57,0x29,0x11,0x69,0x5b,0x2c,0x12, + 0x6c,0x60,0x31,0x15,0x6f,0x67,0x39,0x17,0x75,0x6e,0x40,0x1b,0x7b,0x75,0x47,0x1e, + 0x81,0x7b,0x4d,0x20,0x87,0x7f,0x52,0x22,0x8d,0x83,0x55,0x23,0x91,0x84,0x56,0x24, + 0x92,0x83,0x56,0x24,0x91,0x80,0x53,0x22,0x8d,0x79,0x4c,0x20,0x86,0x71,0x43,0x1b, + 0x7e,0x67,0x39,0x18,0x75,0x5f,0x31,0x14,0x6f,0x5b,0x2c,0x13,0x6d,0x5d,0x2d,0x14, + 0x6d,0x61,0x33,0x16,0x71,0x68,0x3a,0x18,0x76,0x6f,0x42,0x1b,0x7c,0x75,0x47,0x1d, + 0x81,0x77,0x4a,0x1f,0x84,0x77,0x4a,0x1f,0x84,0x77,0x4a,0x1e,0x83,0x76,0x48,0x1e, + 0x83,0x75,0x48,0x1e,0x81,0x74,0x46,0x1e,0x81,0x72,0x44,0x1c,0x7f,0x6f,0x41,0x1b, + 0x7c,0x6a,0x3c,0x1a,0x78,0x66,0x37,0x17,0x73,0x60,0x32,0x15,0x70,0x5e,0x2f,0x14, + 0x6e,0x5d,0x2f,0x14,0x6e,0x61,0x32,0x15,0x70,0x67,0x39,0x18,0x75,0x6e,0x40,0x1a, + 0x7b,0x74,0x47,0x1d,0x81,0x7a,0x4c,0x1f,0x87,0x7e,0x51,0x21,0x8b,0x81,0x53,0x22, + 0x8e,0x83,0x54,0x23,0x90,0x83,0x56,0x23,0x90,0x83,0x55,0x23,0x90,0x81,0x54,0x22, + 0x8e,0x7f,0x52,0x22,0x8c,0x7c,0x4f,0x20,0x89,0x78,0x4a,0x1f,0x84,0x73,0x44,0x1c, + 0x7f,0x6c,0x3e,0x1a,0x79,0x65,0x36,0x17,0x73,0x5e,0x2f,0x14,0x6e,0x5a,0x2b,0x12, + 0x6b,0x57,0x28,0x11,0x69,0x56,0x26,0x10,0x67,0x55,0x26,0x10,0x68,0x52,0x24,0xf, + 0x68,0x52,0x24,0xf,0x68,0x53,0x23,0xf,0x68,0x53,0x23,0x10,0x68,0x53,0x24,0x10, + 0x68,0x52,0x23,0xf,0x68,0x52,0x23,0xf,0x67,0x53,0x24,0xf,0x68,0x54,0x25,0x10, + 0x69,0x58,0x29,0x11,0x6b,0x5d,0x2e,0x13,0x6e,0x63,0x35,0x16,0x73,0x6b,0x3d,0x1a, + 0x7a,0x71,0x43,0x1c,0x80,0x76,0x48,0x1e,0x84,0x78,0x4a,0x1f,0x86,0x79,0x4b,0x1f, + 0x86,0x77,0x4a,0x1e,0x85,0x74,0x45,0x1d,0x81,0x6e,0x3f,0x1a,0x7c,0x67,0x38,0x18, + 0x76,0x60,0x32,0x14,0x71,0x5c,0x2e,0x14,0x6e,0x5c,0x2d,0x14,0x6e,0x5e,0x30,0x14, + 0x70,0x61,0x32,0x15,0x71,0x65,0x36,0x16,0x74,0x66,0x38,0x18,0x76,0x67,0x38,0x17, + 0x76,0x67,0x39,0x18,0x76,0x67,0x39,0x18,0x76,0x69,0x3b,0x18,0x78,0x6a,0x3c,0x19, + 0x78,0x6b,0x3d,0x19,0x79,0x68,0x3b,0x18,0x78,0x65,0x37,0x17,0x74,0x60,0x32,0x15, + 0x71,0x5d,0x2e,0x13,0x6e,0x59,0x2b,0x12,0x6c,0x57,0x28,0x11,0x6a,0x55,0x26,0x10, + 0x69,0x55,0x26,0x10,0x69,0x57,0x28,0x11,0x6a,0x59,0x2a,0x12,0x6c,0x5d,0x2e,0x13, + 0x6e,0x60,0x31,0x15,0x71,0x63,0x35,0x16,0x73,0x66,0x38,0x18,0x75,0x67,0x3a,0x18, + 0x77,0x69,0x3b,0x19,0x77,0x69,0x3a,0x19,0x77,0x69,0x3b,0x19,0x77,0x69,0x3b,0x19, + 0x78,0x67,0x39,0x18,0x75,0x65,0x37,0x17,0x74,0x62,0x33,0x16,0x71,0x5f,0x30,0x14, + 0x6f,0x5b,0x2c,0x13,0x6d,0x59,0x2a,0x11,0x6b,0x57,0x27,0x10,0x69,0x54,0x25,0xf, + 0x68,0x54,0x25,0x10,0x68,0x53,0x24,0x11,0x68,0x53,0x25,0x10,0x68,0x51,0x23,0xf, + 0x68,0x51,0x22,0xf,0x68,0x51,0x23,0xf,0x68,0x51,0x22,0xf,0x68,0x51,0x23,0xf, + 0x68,0x51,0x23,0xf,0x68,0x51,0x23,0xf,0x68,0x51,0x23,0xf,0x68,0x53,0x24,0xf, + 0x69,0x56,0x28,0x11,0x6b,0x5f,0x30,0x14,0x71,0x69,0x3c,0x19,0x7a,0x75,0x47,0x1d, + 0x84,0x7c,0x4f,0x21,0x8c,0x82,0x55,0x23,0x93,0x84,0x57,0x24,0x95,0x84,0x57,0x24, + 0x95,0x82,0x54,0x23,0x92,0x7d,0x50,0x21,0x8c,0x77,0x49,0x1f,0x86,0x6f,0x42,0x1b, + 0x7f,0x6a,0x3c,0x19,0x7a,0x67,0x39,0x18,0x78,0x69,0x3b,0x19,0x79,0x6d,0x3f,0x1a, + 0x7c,0x70,0x42,0x1b,0x7f,0x71,0x43,0x1c,0x80,0x70,0x42,0x1b,0x7f,0x6d,0x3f,0x1a, + 0x7d,0x6b,0x3d,0x19,0x7b,0x6c,0x3f,0x1a,0x7b,0x70,0x43,0x1c,0x80,0x74,0x46,0x1d, + 0x82,0x75,0x47,0x1e,0x84,0x72,0x44,0x1c,0x81,0x6b,0x3d,0x19,0x7b,0x62,0x34,0x16, + 0x73,0x5a,0x2b,0x13,0x6d,0x54,0x26,0x10,0x6a,0x53,0x24,0xf,0x68,0x52,0x23,0xf, + 0x68,0x52,0x24,0xf,0x68,0x52,0x24,0xf,0x68,0x53,0x24,0xf,0x69,0x54,0x25,0x10, + 0x69,0x55,0x26,0x10,0x6a,0x56,0x28,0x10,0x6b,0x57,0x29,0x11,0x6b,0x59,0x2a,0x11, + 0x6c,0x59,0x2a,0x11,0x6c,0x59,0x2a,0x12,0x6d,0x59,0x2a,0x12,0x6d,0x59,0x2a,0x11, + 0x6c,0x57,0x29,0x11,0x6c,0x57,0x28,0x11,0x6b,0x56,0x27,0x11,0x6a,0x55,0x26,0x10, + 0x69,0x53,0x25,0x10,0x69,0x53,0x24,0x10,0x69,0x52,0x24,0x10,0x68,0x52,0x23,0x10, + 0x67,0x52,0x24,0xf,0x67,0x52,0x23,0x10,0x68,0x52,0x24,0x10,0x68,0x4f,0x21,0xe, + 0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe, + 0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x67,0x51,0x23,0xf,0x69,0x53,0x25,0xf, + 0x6a,0x5b,0x2d,0x13,0x70,0x68,0x3b,0x19,0x7a,0x79,0x4d,0x1f,0x8a,0x87,0x5b,0x25, + 0x9c,0x91,0x64,0x29,0xa9,0x96,0x6a,0x2b,0xb3,0x98,0x6c,0x2c,0xb5,0x97,0x6b,0x2b, + 0xb5,0x95,0x69,0x2b,0xb1,0x91,0x65,0x29,0xaa,0x8c,0x5f,0x27,0xa1,0x84,0x58,0x24, + 0x97,0x7e,0x52,0x22,0x8f,0x7d,0x50,0x21,0x8d,0x80,0x53,0x22,0x90,0x83,0x57,0x24, + 0x96,0x87,0x5b,0x25,0x9b,0x87,0x5b,0x26,0x9b,0x86,0x59,0x24,0x98,0x82,0x55,0x23, + 0x93,0x7e,0x52,0x22,0x90,0x80,0x53,0x22,0x92,0x85,0x58,0x24,0x97,0x89,0x5c,0x26, + 0x9e,0x8b,0x5e,0x27,0x9f,0x86,0x5a,0x25,0x99,0x7c,0x4f,0x21,0x8d,0x6e,0x40,0x1a, + 0x7e,0x5f,0x31,0x15,0x72,0x56,0x27,0x10,0x6c,0x51,0x23,0xe,0x69,0x50,0x21,0xe, + 0x68,0x50,0x22,0xf,0x68,0x50,0x21,0xe,0x67,0x50,0x21,0xf,0x67,0x50,0x22,0xe, + 0x67,0x50,0x22,0xe,0x68,0x51,0x23,0xe,0x68,0x51,0x22,0xe,0x68,0x51,0x23,0xf, + 0x69,0x52,0x24,0xf,0x69,0x52,0x23,0xf,0x69,0x52,0x24,0xf,0x69,0x51,0x22,0xf, + 0x69,0x51,0x22,0xe,0x68,0x51,0x23,0xe,0x68,0x51,0x22,0xe,0x68,0x50,0x22,0xe, + 0x68,0x50,0x21,0xf,0x67,0x50,0x22,0xe,0x67,0x50,0x22,0xe,0x68,0x50,0x21,0xe, + 0x68,0x50,0x22,0xf,0x68,0x50,0x22,0xe,0x68,0x50,0x22,0xf,0x68,0x4e,0x20,0xe, + 0x68,0x4e,0x20,0xd,0x68,0x4e,0x20,0xe,0x68,0x4e,0x20,0xd,0x68,0x4e,0x20,0xe, + 0x68,0x4f,0x20,0xe,0x68,0x4e,0x20,0xe,0x67,0x4f,0x21,0xe,0x69,0x54,0x28,0x11, + 0x6c,0x62,0x34,0x15,0x76,0x76,0x48,0x1e,0x87,0x89,0x5d,0x26,0xa0,0x98,0x6c,0x2c, + 0xb8,0xa1,0x75,0x30,0xca,0xa5,0x79,0x31,0xd4,0xa6,0x7b,0x32,0xd7,0xa6,0x7b,0x32, + 0xd7,0xa5,0x79,0x31,0xd3,0xa2,0x77,0x30,0xcc,0x9e,0x72,0x2f,0xc3,0x99,0x6d,0x2c, + 0xb9,0x94,0x69,0x2a,0xb0,0x93,0x67,0x2a,0xae,0x95,0x69,0x2b,0xb2,0x99,0x6d,0x2c, + 0xba,0x9b,0x70,0x2e,0xbe,0x9b,0x70,0x2d,0xbf,0x9a,0x6e,0x2d,0xbb,0x96,0x6b,0x2b, + 0xb5,0x94,0x68,0x2a,0xb0,0x95,0x69,0x2b,0xb1,0x99,0x6d,0x2c,0xb8,0x9c,0x71,0x2e, + 0xc0,0x9d,0x72,0x2e,0xc1,0x99,0x6d,0x2c,0xb8,0x8e,0x62,0x28,0xa5,0x7c,0x50,0x21, + 0x8f,0x68,0x3b,0x18,0x7b,0x59,0x2b,0x12,0x6f,0x51,0x23,0xf,0x6a,0x4f,0x21,0xe, + 0x68,0x4f,0x20,0xe,0x67,0x4e,0x21,0xd,0x68,0x4e,0x21,0xe,0x68,0x4f,0x21,0xe, + 0x67,0x4f,0x21,0xe,0x67,0x4f,0x20,0xe,0x67,0x4e,0x21,0xe,0x68,0x4f,0x21,0xe, + 0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xf,0x68,0x4f,0x21,0xe, + 0x68,0x4f,0x21,0xe,0x68,0x4f,0x20,0xe,0x67,0x4f,0x21,0xe,0x67,0x4f,0x21,0xe, + 0x67,0x4f,0x20,0xe,0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe, + 0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x68,0x4f,0x21,0xe,0x68,0x4c,0x1e,0xd, + 0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd, + 0x68,0x4c,0x1f,0xd,0x67,0x4c,0x1f,0xc,0x68,0x4f,0x21,0xe,0x69,0x56,0x29,0x11, + 0x6f,0x68,0x3b,0x18,0x7c,0x80,0x53,0x22,0x94,0x94,0x69,0x2b,0xb3,0xa2,0x76,0x30, + 0xce,0xa9,0x7d,0x31,0xe2,0xad,0x85,0x40,0xed,0xae,0x87,0x43,0xf0,0xae,0x85,0x3e, + 0xef,0xad,0x81,0x33,0xeb,0xab,0x80,0x31,0xe7,0xa9,0x7e,0x33,0xe1,0xa7,0x7b,0x32, + 0xd9,0xa3,0x78,0x31,0xd2,0xa3,0x78,0x31,0xd0,0xa4,0x79,0x31,0xd4,0xa7,0x7c,0x32, + 0xda,0xa8,0x7c,0x31,0xde,0xa9,0x7d,0x31,0xdf,0xa7,0x7b,0x32,0xdb,0xa5,0x79,0x32, + 0xd6,0xa4,0x78,0x31,0xd2,0xa3,0x78,0x31,0xd3,0xa6,0x7a,0x32,0xd8,0xa8,0x7d,0x32, + 0xde,0xa7,0x7c,0x30,0xdd,0xa4,0x79,0x31,0xd3,0x9a,0x6e,0x2d,0xbc,0x88,0x5c,0x25, + 0x9f,0x71,0x44,0x1c,0x84,0x5d,0x2f,0x13,0x73,0x51,0x23,0xf,0x6a,0x4e,0x20,0xd, + 0x69,0x4d,0x1f,0xe,0x67,0x4d,0x1f,0xe,0x68,0x4c,0x1f,0xd,0x68,0x4c,0x1f,0xd, + 0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xd, + 0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xe,0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xd, + 0x68,0x4d,0x1f,0xe,0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xe,0x68,0x4d,0x1f,0xd, + 0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xe,0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xd, + 0x68,0x4d,0x1f,0xd,0x68,0x4d,0x1f,0xe,0x68,0x4d,0x1f,0xd,0x68,0x4b,0x1d,0xd, + 0x68,0x4b,0x1d,0xc,0x68,0x4b,0x1d,0xd,0x68,0x4b,0x1d,0xd,0x68,0x4b,0x1d,0xd, + 0x68,0x4b,0x1d,0xd,0x67,0x4b,0x1d,0xd,0x68,0x4c,0x20,0xd,0x6a,0x57,0x2a,0x11, + 0x70,0x6b,0x3f,0x1a,0x80,0x85,0x59,0x25,0x9c,0x99,0x6e,0x2d,0xbe,0xa7,0x7b,0x31, + 0xdb,0xb0,0x8f,0x61,0xf4,0xb4,0xa2,0x9a,0xfe,0xb4,0xa2,0x99,0xfe,0xb4,0xa2,0x99, + 0xfe,0xb4,0xa1,0x95,0xfe,0xb2,0x94,0x6d,0xfa,0xae,0x84,0x37,0xf4,0xad,0x82,0x33, + 0xee,0xac,0x81,0x34,0xeb,0xab,0x80,0x34,0xea,0xac,0x81,0x34,0xec,0xad,0x81,0x32, + 0xef,0xaf,0x8c,0x53,0xf5,0xb0,0x8f,0x60,0xf6,0xae,0x83,0x38,0xf1,0xac,0x81,0x34, + 0xed,0xac,0x80,0x34,0xea,0xac,0x81,0x34,0xeb,0xad,0x82,0x34,0xee,0xaf,0x87,0x41, + 0xf2,0xb2,0x9a,0x81,0xfa,0xa9,0x7d,0x2d,0xe2,0xa0,0x75,0x2f,0xca,0x8e,0x62,0x28, + 0xa9,0x76,0x4a,0x1e,0x8b,0x5e,0x32,0x14,0x75,0x51,0x23,0xf,0x6c,0x4c,0x1f,0xd, + 0x69,0x4b,0x1d,0xd,0x67,0x4c,0x1e,0xd,0x68,0x4b,0x1e,0xd,0x68,0x4c,0x1e,0xc, + 0x68,0x4b,0x1e,0xd,0x68,0x4c,0x1e,0xc,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd, + 0x68,0x4c,0x1e,0xd,0x68,0x4b,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4b,0x1e,0xd, + 0x68,0x4c,0x1e,0xd,0x68,0x4b,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd, + 0x68,0x4b,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xc, + 0x68,0x4b,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x4c,0x1e,0xd,0x68,0x49,0x1b,0xc, + 0x68,0x49,0x1c,0xc,0x68,0x49,0x1b,0xb,0x68,0x49,0x1c,0xb,0x68,0x49,0x1c,0xb, + 0x68,0x48,0x1b,0xc,0x67,0x4a,0x1c,0xc,0x68,0x4c,0x1f,0xd,0x6a,0x56,0x29,0x11, + 0x71,0x6c,0x3f,0x1a,0x81,0x85,0x5a,0x25,0x9e,0x9a,0x6f,0x2d,0xc2,0xa7,0x7c,0x33, + 0xe0,0xb1,0x95,0x73,0xf9,0xb4,0xa2,0x9b,0xfe,0xb4,0x9e,0x90,0xff,0xb2,0x90,0x5b, + 0xfe,0xb2,0x92,0x63,0xfe,0xb3,0x98,0x78,0xfe,0xb3,0xa0,0x95,0xff,0xb2,0x97,0x76, + 0xfc,0xaf,0x85,0x3a,0xf9,0xaf,0x85,0x35,0xf8,0xaf,0x85,0x36,0xf8,0xb2,0x98,0x79, + 0xfd,0xb4,0xa3,0xa1,0xff,0xb4,0xa3,0xa1,0xff,0xb3,0xa0,0x95,0xfe,0xb1,0x8c,0x4f, + 0xfa,0xaf,0x84,0x33,0xf8,0xaf,0x84,0x36,0xf8,0xaf,0x84,0x32,0xf9,0xb2,0x96,0x71, + 0xfd,0xb5,0xa4,0xa3,0xff,0xab,0x7e,0x2c,0xea,0xa2,0x77,0x31,0xd3,0x91,0x65,0x29, + 0xb0,0x79,0x4c,0x1f,0x8e,0x60,0x33,0x15,0x77,0x51,0x23,0xe,0x6d,0x4b,0x1d,0xc, + 0x69,0x49,0x1c,0xb,0x67,0x49,0x1c,0xb,0x68,0x49,0x1c,0xc,0x68,0x49,0x1c,0xc, + 0x68,0x49,0x1d,0xc,0x68,0x49,0x1c,0xc,0x68,0x49,0x1c,0xc,0x68,0x49,0x1c,0xc, + 0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc, + 0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc,0x68,0x49,0x1c,0xc,0x68,0x4a,0x1c,0xc, + 0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xd,0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1d,0xc, + 0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc,0x68,0x4a,0x1c,0xc,0x68,0x47,0x1a,0xb, + 0x68,0x47,0x1a,0xb,0x68,0x47,0x1b,0xb,0x68,0x46,0x19,0xb,0x68,0x47,0x1b,0xb, + 0x68,0x47,0x1a,0xa,0x67,0x47,0x1b,0xa,0x68,0x4a,0x1d,0xc,0x6a,0x54,0x27,0x11, + 0x70,0x68,0x3c,0x18,0x80,0x82,0x56,0x23,0x9a,0x97,0x6c,0x2c,0xbd,0xa5,0x7a,0x32, + 0xdc,0xac,0x87,0x47,0xf1,0xb4,0xa2,0x9e,0xff,0xb3,0x9e,0x8e,0xff,0xb0,0x84,0x32, + 0xfe,0xb0,0x85,0x37,0xff,0xb0,0x85,0x35,0xff,0xb0,0x85,0x35,0xfe,0xb2,0x94,0x6a, + 0xfe,0xb2,0x9d,0x8d,0xfe,0xb0,0x85,0x32,0xfe,0xb0,0x87,0x3d,0xfe,0xb3,0x9f,0x93, + 0xfe,0xb4,0xa2,0x9b,0xff,0xb2,0x96,0x70,0xff,0xb3,0x9e,0x8c,0xfe,0xb3,0xa1,0x9b, + 0xff,0xb0,0x8d,0x50,0xfe,0xb0,0x85,0x35,0xfe,0xb0,0x84,0x33,0xfe,0xb2,0x98,0x78, + 0xfe,0xb4,0xa3,0xa0,0xff,0xab,0x7f,0x2c,0xed,0xa3,0x78,0x31,0xd5,0x91,0x67,0x2a, + 0xb3,0x79,0x4d,0x1f,0x91,0x5f,0x33,0x15,0x78,0x50,0x22,0xe,0x6d,0x49,0x1c,0xc, + 0x69,0x47,0x1a,0xb,0x67,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x47,0x1b,0xb, + 0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x48,0x1a,0xb,0x68,0x48,0x1a,0xb, + 0x68,0x48,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x48,0x1a,0xb,0x68,0x48,0x1a,0xb, + 0x68,0x47,0x1c,0xb,0x68,0x48,0x1b,0xc,0x68,0x48,0x1b,0xb,0x68,0x49,0x1c,0xc, + 0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x48,0x1c,0xb,0x68,0x47,0x1b,0xb, + 0x68,0x48,0x1a,0xb,0x68,0x49,0x1c,0xb,0x68,0x48,0x1b,0xb,0x68,0x46,0x19,0xa, + 0x68,0x46,0x19,0xa,0x68,0x45,0x19,0xb,0x68,0x46,0x19,0xa,0x68,0x46,0x19,0xb, + 0x68,0x46,0x19,0xb,0x67,0x46,0x19,0xa,0x68,0x48,0x1b,0xb,0x69,0x4f,0x23,0xe, + 0x6e,0x60,0x34,0x15,0x7a,0x79,0x4d,0x1f,0x92,0x8f,0x64,0x29,0xb2,0xa0,0x75,0x30, + 0xd0,0xa9,0x7c,0x30,0xe8,0xae,0x8b,0x52,0xf7,0xb3,0xa1,0x9d,0xff,0xb2,0x98,0x7c, + 0xfe,0xaf,0x85,0x34,0xfe,0xaf,0x85,0x36,0xff,0xaf,0x85,0x35,0xff,0xaf,0x84,0x33, + 0xff,0xaf,0x84,0x31,0xff,0xaf,0x85,0x36,0xff,0xb0,0x87,0x3c,0xff,0xb2,0x9e,0x92, + 0xff,0xb2,0x9e,0x90,0xff,0xb0,0x85,0x36,0xff,0xb0,0x86,0x3a,0xff,0xb2,0x9c,0x8d, + 0xff,0xb3,0xa0,0x9a,0xff,0xb0,0x8f,0x58,0xfe,0xaf,0x83,0x2f,0xfe,0xb1,0x97,0x78, + 0xff,0xb3,0xa2,0xa0,0xff,0xaa,0x7e,0x2c,0xef,0xa2,0x78,0x31,0xd7,0x92,0x66,0x2a, + 0xb5,0x7a,0x4d,0x1f,0x92,0x60,0x34,0x14,0x79,0x4e,0x22,0xe,0x6d,0x48,0x1a,0xb, + 0x69,0x46,0x19,0xb,0x67,0x46,0x19,0xa,0x68,0x46,0x1a,0xa,0x68,0x46,0x1a,0xb, + 0x68,0x46,0x19,0xb,0x68,0x46,0x19,0xb,0x68,0x46,0x19,0xb,0x68,0x46,0x1a,0xb, + 0x68,0x46,0x19,0xb,0x68,0x46,0x1a,0xb,0x68,0x46,0x1a,0xa,0x68,0x46,0x19,0xa, + 0x68,0x46,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x46,0x19,0xa,0x68,0x46,0x1a,0xa, + 0x68,0x47,0x1a,0xb,0x68,0x46,0x1a,0xb,0x68,0x47,0x19,0xa,0x68,0x47,0x1a,0xb, + 0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x47,0x1a,0xb,0x68,0x44,0x17,0x9, + 0x68,0x43,0x17,0x9,0x68,0x43,0x17,0xa,0x68,0x44,0x17,0xa,0x68,0x43,0x17,0x9, + 0x68,0x43,0x17,0x9,0x68,0x44,0x17,0x9,0x67,0x45,0x19,0xa,0x69,0x4a,0x1e,0xc, + 0x6c,0x57,0x2b,0x11,0x74,0x6c,0x41,0x1a,0x86,0x83,0x58,0x24,0xa0,0x96,0x6c,0x2b, + 0xbf,0xa2,0x77,0x31,0xd8,0xa8,0x7e,0x33,0xec,0xaf,0x8e,0x61,0xf9,0xb3,0xa0,0x9c, + 0xff,0xb1,0x9a,0x87,0xff,0xaf,0x86,0x3b,0xfe,0xaf,0x84,0x35,0xff,0xaf,0x84,0x35, + 0xff,0xaf,0x85,0x36,0xff,0xaf,0x85,0x36,0xff,0xaf,0x85,0x36,0xff,0xb1,0x9b,0x8a, + 0xff,0xb2,0xa0,0x9c,0xff,0xb0,0x87,0x3f,0xfe,0xaf,0x84,0x35,0xff,0xaf,0x86,0x38, + 0xff,0xb2,0x9e,0x93,0xff,0xb2,0xa0,0x9b,0xfe,0xb0,0x8c,0x51,0xff,0xb1,0x97,0x77, + 0xff,0xb3,0xa1,0xa0,0xff,0xaa,0x7e,0x2d,0xef,0xa3,0x78,0x31,0xd9,0x92,0x67,0x2a, + 0xb8,0x7a,0x4f,0x20,0x94,0x5f,0x34,0x15,0x7a,0x4d,0x21,0xe,0x6d,0x46,0x19,0xb, + 0x69,0x45,0x18,0x9,0x68,0x44,0x18,0xa,0x67,0x44,0x18,0xa,0x68,0x45,0x17,0x9, + 0x68,0x44,0x18,0xb,0x68,0x44,0x18,0xa,0x68,0x44,0x17,0xa,0x68,0x44,0x18,0xa, + 0x68,0x44,0x18,0xa,0x68,0x44,0x18,0xa,0x68,0x44,0x18,0xa,0x68,0x44,0x18,0xa, + 0x68,0x44,0x17,0x9,0x68,0x44,0x18,0xa,0x68,0x45,0x18,0xa,0x68,0x44,0x18,0xa, + 0x68,0x44,0x18,0xa,0x68,0x44,0x18,0xa,0x68,0x45,0x18,0xa,0x68,0x44,0x17,0x9, + 0x68,0x45,0x18,0xa,0x68,0x45,0x18,0xa,0x68,0x45,0x18,0xa,0x68,0x42,0x16,0xa, + 0x68,0x42,0x16,0x9,0x68,0x42,0x16,0x9,0x68,0x42,0x16,0xa,0x68,0x42,0x16,0x8, + 0x68,0x42,0x16,0xa,0x68,0x42,0x16,0x9,0x67,0x42,0x16,0x9,0x68,0x45,0x19,0xa, + 0x6a,0x4e,0x21,0xd,0x6f,0x5e,0x32,0x14,0x7a,0x73,0x48,0x1d,0x8e,0x88,0x5d,0x26, + 0xa8,0x97,0x6c,0x2c,0xc3,0xa2,0x77,0x30,0xda,0xa8,0x7d,0x30,0xea,0xad,0x88,0x4d, + 0xf7,0xb2,0x9f,0x9b,0xff,0xb1,0x9d,0x94,0xff,0xb0,0x8f,0x61,0xff,0xad,0x83,0x32, + 0xfe,0xaf,0x83,0x32,0xff,0xaf,0x84,0x35,0xff,0xae,0x84,0x35,0xff,0xaf,0x8e,0x5c, + 0xff,0xb2,0xa1,0xa0,0xfe,0xb0,0x9a,0x84,0xff,0xae,0x82,0x30,0xfe,0xaf,0x84,0x35, + 0xfe,0xaf,0x87,0x43,0xfe,0xb1,0x9f,0x9b,0xff,0xb1,0x9f,0x99,0xfe,0xb1,0x9e,0x93, + 0xff,0xb2,0xa1,0x9f,0xff,0xaa,0x81,0x38,0xf1,0xa2,0x78,0x31,0xdb,0x92,0x68,0x2a, + 0xb9,0x7a,0x4f,0x20,0x96,0x5f,0x33,0x14,0x7b,0x4d,0x21,0xd,0x6e,0x44,0x18,0xa, + 0x69,0x43,0x17,0xa,0x68,0x43,0x17,0xa,0x67,0x43,0x17,0xa,0x68,0x43,0x17,0xa, + 0x68,0x43,0x17,0x9,0x68,0x43,0x17,0x9,0x68,0x43,0x17,0x9,0x68,0x43,0x17,0x9, + 0x68,0x43,0x17,0xa,0x68,0x43,0x17,0xa,0x68,0x43,0x17,0xa,0x68,0x43,0x17,0xa, + 0x68,0x43,0x17,0xa,0x68,0x43,0x17,0xa,0x68,0x43,0x17,0x9,0x68,0x43,0x18,0xa, + 0x68,0x43,0x17,0x9,0x68,0x43,0x17,0xa,0x68,0x43,0x17,0xa,0x68,0x43,0x17,0xa, + 0x68,0x43,0x17,0x9,0x68,0x43,0x18,0xa,0x68,0x43,0x17,0xa,0x68,0x40,0x15,0x8, + 0x68,0x40,0x15,0x8,0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8, + 0x68,0x40,0x15,0x8,0x68,0x40,0x15,0x8,0x68,0x40,0x15,0x8,0x68,0x42,0x16,0x8, + 0x68,0x46,0x1a,0xb,0x6b,0x50,0x24,0xe,0x71,0x60,0x35,0x15,0x7e,0x74,0x4a,0x1d, + 0x91,0x88,0x5d,0x26,0xaa,0x96,0x6b,0x2c,0xc2,0xa0,0x76,0x2f,0xd8,0xa6,0x7c,0x31, + 0xe9,0xaa,0x82,0x3c,0xf4,0xaf,0x99,0x86,0xfd,0xb1,0xa0,0x9e,0xff,0xb0,0x9e,0x98, + 0xff,0xaf,0x95,0x77,0xff,0xae,0x88,0x44,0xfd,0xad,0x83,0x34,0xfd,0xad,0x82,0x2f, + 0xfd,0xb0,0x9b,0x8f,0xfe,0xb1,0x9f,0x9d,0xff,0xae,0x8b,0x52,0xfd,0xad,0x83,0x35, + 0xfb,0xad,0x83,0x34,0xfb,0xad,0x86,0x3f,0xfc,0xb0,0x9c,0x91,0xfe,0xb1,0x9f,0x9a, + 0xff,0xb1,0xa0,0x9d,0xff,0xaa,0x87,0x4e,0xf2,0xa1,0x76,0x30,0xd9,0x91,0x67,0x29, + 0xb8,0x78,0x4f,0x20,0x95,0x5e,0x33,0x14,0x7b,0x4b,0x1f,0xd,0x6e,0x43,0x17,0x9, + 0x69,0x41,0x16,0x8,0x68,0x41,0x15,0x8,0x67,0x41,0x15,0x8,0x68,0x41,0x15,0x8, + 0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x9, + 0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x8, + 0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x8, + 0x68,0x41,0x15,0x9,0x68,0x41,0x15,0x8,0x68,0x42,0x16,0x8,0x68,0x42,0x15,0x9, + 0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x8,0x68,0x41,0x15,0x8,0x68,0x3f,0x14,0x8, + 0x68,0x3f,0x14,0x8,0x68,0x3f,0x13,0x8,0x68,0x3f,0x13,0x8,0x68,0x3f,0x14,0x8, + 0x68,0x3f,0x14,0x8,0x68,0x3f,0x13,0x8,0x68,0x3f,0x14,0x8,0x67,0x40,0x14,0x8, + 0x68,0x40,0x15,0x8,0x69,0x46,0x1a,0xa,0x6c,0x50,0x25,0xe,0x72,0x60,0x35,0x16, + 0x7e,0x73,0x48,0x1d,0x91,0x85,0x5b,0x25,0xa8,0x94,0x6a,0x2a,0xbf,0x9d,0x73,0x2f, + 0xd4,0xa4,0x79,0x30,0xe3,0xa8,0x7e,0x34,0xee,0xab,0x84,0x44,0xf4,0xae,0x93,0x75, + 0xfb,0xaf,0x9a,0x8b,0xfe,0xac,0x89,0x52,0xf9,0xab,0x81,0x33,0xf6,0xab,0x81,0x33, + 0xf7,0xac,0x86,0x45,0xf8,0xae,0x98,0x85,0xfd,0xab,0x85,0x43,0xf6,0xa9,0x7f,0x34, + 0xf3,0xa9,0x7f,0x34,0xf2,0xa9,0x7f,0x33,0xf3,0xaa,0x82,0x3a,0xf5,0xaf,0x9a,0x8c, + 0xfe,0xaf,0x9a,0x8d,0xfd,0xa6,0x7c,0x34,0xe9,0x9d,0x73,0x2f,0xd3,0x8d,0x62,0x27, + 0xb3,0x75,0x4a,0x1e,0x91,0x5a,0x2f,0x13,0x79,0x48,0x1d,0xb,0x6e,0x40,0x15,0x9, + 0x69,0x40,0x14,0x8,0x68,0x40,0x14,0x8,0x67,0x40,0x14,0x9,0x68,0x40,0x14,0x9, + 0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8, + 0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8, + 0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x8, + 0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x8,0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x9, + 0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x9,0x68,0x40,0x14,0x9,0x68,0x3d,0x12,0x7, + 0x68,0x3d,0x11,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x8,0x68,0x3d,0x12,0x7, + 0x68,0x3d,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x7, + 0x67,0x3e,0x13,0x7,0x68,0x3f,0x14,0x8,0x69,0x44,0x19,0xa,0x6c,0x4e,0x23,0xd, + 0x72,0x5e,0x32,0x14,0x7e,0x70,0x44,0x1c,0x8e,0x80,0x56,0x23,0xa2,0x8e,0x64,0x29, + 0xb7,0x98,0x6e,0x2c,0xc9,0x9f,0x74,0x2f,0xd8,0xa2,0x78,0x30,0xe1,0xa4,0x79,0x2d, + 0xe6,0xa4,0x7a,0x2b,0xe8,0xa4,0x7a,0x2f,0xe8,0xa4,0x7a,0x31,0xe7,0xa4,0x7a,0x31, + 0xe6,0xa4,0x7a,0x31,0xe6,0xa4,0x78,0x2c,0xe5,0xa3,0x79,0x30,0xe3,0xa2,0x78,0x30, + 0xdf,0xa1,0x77,0x30,0xde,0xa2,0x78,0x30,0xe0,0xa3,0x79,0x31,0xe4,0xa4,0x79,0x2b, + 0xe7,0xa3,0x78,0x2a,0xe4,0xa0,0x75,0x2f,0xd9,0x95,0x6b,0x2c,0xc4,0x84,0x5a,0x24, + 0xa7,0x6b,0x41,0x1a,0x8a,0x54,0x28,0x10,0x76,0x45,0x19,0x9,0x6c,0x3f,0x14,0x7, + 0x69,0x3d,0x12,0x7,0x67,0x3e,0x12,0x7,0x68,0x3d,0x12,0x8,0x68,0x3e,0x13,0x7, + 0x68,0x3e,0x12,0x7,0x68,0x3d,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3e,0x13,0x8, + 0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x8,0x68,0x3e,0x12,0x7, + 0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x8,0x68,0x3e,0x12,0x7,0x68,0x3e,0x12,0x8, + 0x68,0x3e,0x13,0x7,0x68,0x3e,0x13,0x8,0x68,0x3e,0x13,0x7,0x68,0x3e,0x12,0x7, + 0x68,0x3e,0x13,0x7,0x68,0x3e,0x13,0x8,0x68,0x3e,0x13,0x7,0x68,0x3c,0x11,0x7, + 0x68,0x3c,0x11,0x7,0x68,0x3c,0x11,0x7,0x68,0x3c,0x11,0x7,0x68,0x3c,0x11,0x7, + 0x68,0x3c,0x11,0x6,0x68,0x3c,0x11,0x7,0x68,0x3c,0x11,0x7,0x68,0x3c,0x11,0x7, + 0x68,0x3b,0x10,0x7,0x67,0x3c,0x11,0x7,0x68,0x3d,0x12,0x7,0x69,0x43,0x17,0x9, + 0x6c,0x4b,0x20,0xc,0x71,0x58,0x2e,0x12,0x7b,0x68,0x3e,0x19,0x88,0x78,0x4e,0x1f, + 0x99,0x86,0x5b,0x24,0xab,0x8f,0x64,0x28,0xb9,0x95,0x6b,0x2b,0xc4,0x98,0x6e,0x2c, + 0xcb,0x99,0x6f,0x2d,0xcd,0x99,0x6f,0x2d,0xcc,0x98,0x6e,0x2c,0xca,0x98,0x6e,0x2c, + 0xca,0x98,0x6e,0x2c,0xca,0x97,0x6d,0x2c,0xc9,0x95,0x6b,0x2b,0xc6,0x93,0x69,0x2b, + 0xc1,0x92,0x68,0x2a,0xbf,0x93,0x69,0x2b,0xc2,0x97,0x6c,0x2b,0xc8,0x99,0x6f,0x2d, + 0xcc,0x98,0x6e,0x2d,0xcb,0x93,0x69,0x2a,0xbf,0x87,0x5c,0x25,0xac,0x75,0x4a,0x1e, + 0x95,0x5f,0x33,0x15,0x80,0x4b,0x20,0xd,0x71,0x41,0x16,0x8,0x6a,0x3d,0x12,0x7, + 0x69,0x3d,0x12,0x6,0x67,0x3d,0x11,0x6,0x68,0x3c,0x11,0x7,0x68,0x3d,0x11,0x6, + 0x68,0x3c,0x11,0x6,0x68,0x3c,0x11,0x6,0x68,0x3d,0x11,0x6,0x68,0x3c,0x11,0x7, + 0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x10,0x7, + 0x68,0x3c,0x12,0x6,0x68,0x3d,0x11,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x7, + 0x68,0x3d,0x10,0x7,0x68,0x3d,0x11,0x7,0x68,0x3d,0x12,0x7,0x68,0x3d,0x12,0x7, + 0x68,0x3d,0x12,0x7,0x68,0x3d,0x11,0x7,0x68,0x3d,0x12,0x7,0x68,0x3a,0xf,0x5, + 0x68,0x3a,0xf,0x5,0x68,0x3a,0xf,0x6,0x68,0x3a,0xf,0x6,0x68,0x3a,0xf,0x6, + 0x68,0x3a,0xf,0x6,0x68,0x3a,0xf,0x5,0x68,0x3a,0xf,0x6,0x68,0x3a,0xf,0x6, + 0x68,0x3a,0xf,0x5,0x68,0x3a,0xf,0x6,0x67,0x3a,0x10,0x5,0x68,0x3b,0x11,0x6, + 0x69,0x40,0x14,0x8,0x6b,0x46,0x1c,0xa,0x6f,0x51,0x26,0xf,0x76,0x5e,0x34,0x14, + 0x81,0x6b,0x40,0x1a,0x8c,0x77,0x4c,0x1e,0x98,0x7e,0x54,0x22,0xa1,0x82,0x58,0x24, + 0xa7,0x84,0x59,0x24,0xa9,0x83,0x59,0x24,0xa8,0x82,0x58,0x23,0xa7,0x81,0x58,0x23, + 0xa6,0x82,0x57,0x23,0xa6,0x82,0x57,0x23,0xa6,0x7f,0x55,0x22,0xa3,0x7c,0x51,0x20, + 0x9e,0x7a,0x50,0x20,0x9c,0x7c,0x52,0x21,0xa0,0x81,0x57,0x23,0xa6,0x84,0x5a,0x24, + 0xa9,0x83,0x59,0x24,0xa9,0x7d,0x53,0x21,0xa0,0x72,0x46,0x1d,0x92,0x61,0x36,0x16, + 0x82,0x4f,0x25,0xe,0x75,0x43,0x18,0x9,0x6d,0x3c,0x11,0x7,0x69,0x3b,0x10,0x6, + 0x68,0x3b,0x10,0x6,0x67,0x3a,0x10,0x6,0x68,0x3b,0xf,0x6,0x68,0x3a,0x10,0x7, + 0x68,0x3b,0x10,0x6,0x68,0x3a,0x10,0x6,0x68,0x3b,0x10,0x6,0x68,0x3a,0x10,0x6, + 0x68,0x3b,0x10,0x7,0x68,0x3a,0x10,0x6,0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x6, + 0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x7,0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x6, + 0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x6,0x68,0x3b,0x10,0x7, + 0x68,0x3b,0x10,0x7,0x68,0x3a,0x10,0x6,0x68,0x3b,0x10,0x7,0x68,0x38,0xd,0x5, + 0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x6, + 0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x5, + 0x68,0x38,0xd,0x6,0x68,0x38,0xd,0x4,0x68,0x38,0xd,0x6,0x67,0x38,0xe,0x5, + 0x67,0x39,0xf,0x5,0x68,0x3d,0x11,0x6,0x6a,0x42,0x17,0x8,0x6d,0x48,0x1e,0xc, + 0x71,0x51,0x27,0x10,0x77,0x5a,0x30,0x13,0x7e,0x61,0x37,0x16,0x84,0x65,0x3b,0x17, + 0x87,0x67,0x3d,0x19,0x8a,0x66,0x3c,0x18,0x88,0x64,0x3a,0x17,0x87,0x64,0x3a,0x17, + 0x87,0x64,0x3a,0x17,0x87,0x64,0x3a,0x16,0x86,0x62,0x37,0x16,0x84,0x5f,0x35,0x15, + 0x81,0x5e,0x33,0x14,0x81,0x5f,0x35,0x15,0x82,0x64,0x3a,0x17,0x86,0x67,0x3d,0x18, + 0x89,0x67,0x3c,0x18,0x89,0x61,0x37,0x16,0x84,0x58,0x2e,0x12,0x7d,0x4d,0x22,0xd, + 0x74,0x42,0x17,0x9,0x6e,0x3c,0x11,0x7,0x6a,0x39,0xf,0x5,0x68,0x39,0xe,0x5, + 0x67,0x38,0xe,0x5,0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x5, + 0x68,0x38,0xe,0x5,0x68,0x38,0xd,0x5,0x68,0x38,0xe,0x5,0x68,0x39,0xe,0x5, + 0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x6, + 0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x6,0x68,0x39,0xe,0x5, + 0x68,0x39,0xe,0x6,0x68,0x39,0xe,0x6,0x68,0x39,0xe,0x5,0x68,0x39,0xe,0x5, + 0x68,0x39,0xe,0x5,0x68,0x39,0xf,0x5,0x68,0x39,0xf,0x5,0x68,0x36,0xc,0x4, + 0x68,0x36,0xd,0x4,0x68,0x37,0xc,0x5,0x68,0x37,0xd,0x5,0x68,0x36,0xd,0x5, + 0x68,0x37,0xd,0x5,0x68,0x36,0xc,0x5,0x68,0x37,0xd,0x4,0x68,0x37,0xd,0x5, + 0x68,0x37,0xc,0x5,0x68,0x37,0xd,0x4,0x68,0x37,0xd,0x4,0x68,0x36,0xc,0x5, + 0x67,0x37,0xc,0x4,0x68,0x37,0xd,0x5,0x69,0x38,0xe,0x5,0x69,0x3b,0x11,0x6, + 0x6b,0x3f,0x15,0x7,0x6d,0x43,0x19,0x9,0x6f,0x48,0x1d,0xb,0x72,0x4a,0x20,0xc, + 0x74,0x4c,0x22,0xd,0x74,0x4b,0x21,0xc,0x74,0x4a,0x20,0xc,0x73,0x4a,0x1f,0xc, + 0x73,0x4a,0x20,0xc,0x73,0x4a,0x20,0xc,0x73,0x48,0x1e,0xb,0x72,0x46,0x1c,0xb, + 0x71,0x45,0x1b,0xa,0x71,0x47,0x1d,0xb,0x71,0x4a,0x20,0xc,0x73,0x4c,0x22,0xe, + 0x75,0x4c,0x22,0xe,0x75,0x49,0x1f,0xc,0x73,0x44,0x1a,0xa,0x6f,0x3f,0x14,0x7, + 0x6c,0x3a,0xf,0x6,0x6a,0x38,0xe,0x5,0x69,0x37,0xd,0x5,0x68,0x37,0xd,0x5, + 0x67,0x37,0xd,0x5,0x68,0x37,0xd,0x4,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x4, + 0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5, + 0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x37,0xd,0x4,0x68,0x37,0xd,0x5, + 0x68,0x37,0xd,0x4,0x68,0x38,0xd,0x4,0x68,0x38,0xd,0x5,0x68,0x37,0xd,0x5, + 0x68,0x37,0xd,0x5,0x68,0x38,0xd,0x5,0x68,0x37,0xd,0x5,0x68,0x38,0xd,0x5, + 0x68,0x38,0xd,0x5,0x68,0x38,0xd,0x6,0x68,0x38,0xd,0x5,0x68,0x35,0xb,0x4, + 0x68,0x34,0xa,0x4,0x68,0x35,0xb,0x3,0x68,0x35,0xb,0x3,0x68,0x35,0xb,0x4, + 0x68,0x35,0xa,0x3,0x68,0x35,0xb,0x3,0x68,0x34,0xb,0x4,0x68,0x35,0xb,0x3, + 0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x3, + 0x68,0x35,0xa,0x4,0x68,0x34,0xb,0x3,0x67,0x35,0xb,0x4,0x68,0x36,0xc,0x4, + 0x68,0x37,0xd,0x4,0x69,0x38,0xe,0x4,0x69,0x39,0xf,0x5,0x6a,0x3a,0x11,0x6, + 0x6b,0x3b,0x11,0x6,0x6b,0x3a,0x11,0x6,0x6b,0x3a,0x11,0x6,0x6b,0x3a,0x11,0x6, + 0x6b,0x3a,0x11,0x6,0x6b,0x3a,0x10,0x6,0x6b,0x3a,0x10,0x6,0x6a,0x39,0xf,0x5, + 0x6a,0x39,0xf,0x5,0x6a,0x39,0xf,0x5,0x6a,0x3b,0x11,0x6,0x6b,0x3b,0x12,0x6, + 0x6b,0x3b,0x11,0x6,0x6b,0x3a,0x10,0x6,0x6a,0x39,0xe,0x5,0x6a,0x37,0xc,0x4, + 0x69,0x36,0xc,0x3,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4, + 0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4, + 0x68,0x36,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xc,0x4,0x68,0x35,0xb,0x4, + 0x68,0x35,0xc,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4, + 0x68,0x36,0xb,0x4,0x68,0x36,0xb,0x5,0x68,0x35,0xb,0x4,0x68,0x35,0xb,0x4, + 0x68,0x36,0xc,0x5,0x68,0x35,0xc,0x4,0x68,0x36,0xc,0x4,0x68,0x35,0xb,0x4, + 0x68,0x36,0xb,0x4,0x68,0x36,0xc,0x4,0x68,0x36,0xb,0x4,0x68,0x33,0xa,0x4, + 0x68,0x34,0xa,0x4,0x68,0x33,0xa,0x3,0x68,0x34,0xa,0x4,0x68,0x33,0xa,0x3, + 0x68,0x34,0xa,0x4,0x68,0x33,0xa,0x3,0x68,0x33,0x9,0x3,0x68,0x34,0xa,0x4, + 0x68,0x34,0xa,0x3,0x68,0x34,0xa,0x3,0x68,0x34,0xa,0x4,0x68,0x34,0xa,0x4, + 0x68,0x34,0xa,0x3,0x68,0x34,0xa,0x3,0x68,0x34,0xa,0x4,0x67,0x33,0xa,0x3, + 0x68,0x34,0xa,0x3,0x68,0x34,0xa,0x4,0x68,0x34,0xb,0x4,0x69,0x35,0xa,0x4, + 0x69,0x34,0xb,0x4,0x69,0x34,0xb,0x4,0x69,0x34,0xb,0x4,0x69,0x34,0xb,0x4, + 0x69,0x34,0xb,0x4,0x69,0x35,0xb,0x4,0x69,0x34,0xb,0x3,0x69,0x34,0xa,0x4, + 0x68,0x34,0xa,0x4,0x68,0x34,0xa,0x3,0x68,0x35,0xb,0x3,0x69,0x35,0xc,0x4, + 0x69,0x35,0xb,0x4,0x69,0x34,0xb,0x3,0x69,0x34,0xa,0x3,0x68,0x34,0xa,0x4, + 0x68,0x34,0xa,0x4,0x67,0x34,0xa,0x3,0x67,0x34,0xa,0x4,0x68,0x34,0xa,0x3, + 0x68,0x34,0xa,0x4,0x68,0x34,0xb,0x4,0x68,0x34,0xa,0x4,0x68,0x34,0xa,0x3, + 0x68,0x34,0xa,0x4,0x68,0x34,0xa,0x4,0x68,0x34,0xa,0x4,0x68,0x34,0xb,0x3, + 0x68,0x34,0xb,0x3,0x68,0x34,0xa,0x4,0x68,0x34,0xa,0x3,0x68,0x34,0xa,0x4, + 0x68,0x34,0xa,0x4,0x68,0x34,0xb,0x4,0x68,0x34,0xb,0x4,0x68,0x34,0xb,0x4, + 0x68,0x35,0xb,0x4,0x68,0x34,0xb,0x4,0x68,0x34,0xb,0x4,0x68,0x35,0xb,0x4, + 0x68,0x34,0xb,0x3,0x68,0x35,0xa,0x4,0x68,0x34,0xb,0x4,0x68,0x31,0x8,0x2, + 0x68,0x31,0x8,0x2,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x2,0x68,0x32,0x8,0x3, + 0x68,0x31,0x8,0x2,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x32,0x8,0x2, + 0x68,0x32,0x8,0x3,0x68,0x32,0x8,0x3,0x68,0x31,0x8,0x2,0x68,0x32,0x8,0x2, + 0x68,0x31,0x8,0x3,0x68,0x32,0x8,0x3,0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x2, + 0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x2,0x67,0x32,0x8,0x2, + 0x67,0x32,0x8,0x2,0x67,0x32,0x9,0x2,0x67,0x31,0x8,0x2,0x67,0x32,0x8,0x2, + 0x67,0x32,0x8,0x3,0x67,0x32,0x8,0x3,0x67,0x32,0x8,0x2,0x67,0x32,0x8,0x2, + 0x68,0x32,0x8,0x2,0x68,0x32,0x9,0x2,0x67,0x32,0x8,0x2,0x67,0x32,0x9,0x2, + 0x67,0x32,0x8,0x2,0x67,0x32,0x8,0x2,0x67,0x32,0x8,0x3,0x67,0x32,0x8,0x3, + 0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x3, + 0x68,0x32,0x8,0x2,0x68,0x32,0x8,0x2,0x68,0x32,0x9,0x3,0x68,0x32,0x8,0x3, + 0x68,0x32,0x9,0x3,0x68,0x32,0x9,0x2,0x68,0x32,0x9,0x3,0x68,0x32,0x9,0x3, + 0x68,0x32,0x8,0x3,0x68,0x32,0x9,0x2,0x68,0x32,0x9,0x3,0x68,0x32,0x9,0x3, + 0x68,0x32,0x9,0x2,0x68,0x33,0x9,0x3,0x68,0x33,0x9,0x3,0x68,0x33,0x8,0x3, + 0x68,0x32,0x9,0x3,0x68,0x32,0x9,0x2,0x68,0x33,0x9,0x2,0x68,0x32,0x9,0x3, + 0x68,0x32,0x9,0x3,0x68,0x32,0x9,0x3,0x68,0x33,0x9,0x3,0x68,0x30,0x7,0x2, + 0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2, + 0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2, + 0x68,0x30,0x7,0x2,0x68,0x31,0x7,0x2,0x68,0x31,0x7,0x2,0x68,0x30,0x7,0x3, + 0x68,0x30,0x7,0x2,0x68,0x31,0x7,0x2,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x2, + 0x68,0x30,0x7,0x1,0x68,0x30,0x7,0x3,0x68,0x30,0x7,0x2,0x68,0x30,0x7,0x1, + 0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x30,0x7,0x2,0x68,0x31,0x7,0x2, + 0x68,0x31,0x7,0x3,0x68,0x31,0x7,0x2,0x68,0x31,0x8,0x3,0x68,0x30,0x8,0x3, + 0x68,0x31,0x7,0x1,0x68,0x31,0x7,0x3,0x68,0x31,0x8,0x2,0x68,0x31,0x7,0x3, + 0x68,0x31,0x6,0x2,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3, + 0x68,0x31,0x8,0x3,0x68,0x31,0x7,0x3,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x2, + 0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x2,0x68,0x31,0x8,0x2,0x68,0x31,0x8,0x3, + 0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x31,0x7,0x1, + 0x68,0x31,0x8,0x2,0x68,0x31,0x7,0x2,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3, + 0x68,0x32,0x8,0x3,0x68,0x31,0x8,0x2,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x2, + 0x68,0x31,0x8,0x3,0x68,0x32,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3, + 0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x31,0x8,0x3,0x68,0x2e,0x5,0x1, + 0x68,0x2e,0x5,0x1,0x68,0x2e,0x5,0x1,0x68,0x2e,0x5,0x2,0x68,0x2e,0x5,0x2, + 0x68,0x2e,0x5,0x1,0x68,0x2e,0x5,0x1,0x68,0x2e,0x5,0x1,0x68,0x2f,0x6,0x1, + 0x68,0x2e,0x5,0x2,0x68,0x2e,0x6,0x2,0x68,0x2e,0x5,0x1,0x68,0x2e,0x6,0x1, + 0x68,0x2e,0x6,0x1,0x68,0x2e,0x5,0x1,0x68,0x2e,0x5,0x2,0x68,0x2f,0x6,0x1, + 0x68,0x2e,0x6,0x2,0x68,0x2f,0x5,0x1,0x68,0x2f,0x5,0x2,0x68,0x2e,0x5,0x1, + 0x68,0x2f,0x5,0x2,0x68,0x2f,0x5,0x1,0x68,0x2e,0x5,0x2,0x68,0x2e,0x6,0x2, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2,0x68,0x2e,0x6,0x1,0x68,0x2f,0x6,0x1, + 0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x1, + 0x68,0x2e,0x6,0x2,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x1, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x2, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x2, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1, + 0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2f,0x6,0x1,0x68,0x2c,0x4,0x0, + 0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x0, + 0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x1,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0, + 0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x1,0x68,0x2c,0x4,0x0, + 0x68,0x2c,0x5,0x0,0x68,0x2c,0x4,0x0,0x68,0x2d,0x5,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2c,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2d,0x4,0x1, + 0x68,0x2c,0x4,0x2,0x68,0x2c,0x4,0x1,0x68,0x2e,0x4,0x0,0x68,0x2d,0x4,0x1, + 0x68,0x2e,0x4,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x4,0x1,0x68,0x2e,0x4,0x1, + 0x68,0x2e,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x1, + 0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2e,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2e,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x1,0x68,0x2d,0x4,0x1, + 0x68,0x2d,0x4,0x1,0x68,0x2d,0x4,0x1,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2d,0x4,0x1,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0, + 0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x0,0x68,0x2d,0x4,0x2,0x68,0x2d,0x4,0x0, + 0x68,0x2d,0x4,0x1,0x68,0x2d,0x5,0x1,0x68,0x2d,0x4,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2b,0x2,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x1, + 0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2b,0x3,0x1,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x1, + 0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x1,0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2b,0x3,0x0,0x68,0x2b,0x3,0x1,0x68,0x2b,0x3,0x0,0x68,0x2c,0x3,0x0, + 0x68,0x2b,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x1,0x68,0x2b,0x3,0x1, + 0x68,0x2c,0x4,0x0,0x68,0x2c,0x3,0x1,0x68,0x2b,0x4,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2c,0x3,0x0,0x68,0x2b,0x3,0x1,0x68,0x2c,0x3,0x0,0x68,0x2b,0x4,0x1, + 0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0, + 0x68,0x2c,0x3,0x1,0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x1,0x68,0x2c,0x3,0x0, + 0x68,0x2c,0x4,0x1,0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x0,0x68,0x2c,0x3,0x0, + 0x68,0x2c,0x3,0x1,0x68,0x2c,0x3,0x0,0x68,0x2c,0x4,0x1,0x68,0x2c,0x3,0x0, + 0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x0,0x68,0x2c,0x3,0x1,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x3,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x29,0x2,0x0,0x68,0x2b,0x1,0x0,0x68,0x2b,0x1,0x0, + 0x68,0x29,0x1,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x1,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2b,0x2,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2b,0x1,0x0,0x68,0x2b,0x2,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x1,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x1,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x3,0x0, + 0x68,0x2a,0x1,0x0,0x68,0x2a,0x3,0x0,0x68,0x2a,0x1,0x0,0x68,0x2b,0x1,0x0, + 0x68,0x29,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x1,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x3,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x3,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x3,0x0,0x68,0x2b,0x1,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2a,0x3,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x1,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x3,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x29,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2b,0x1,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x29,0x2,0x0,0x68,0x2b,0x1,0x0,0x68,0x2a,0x1,0x0,0x68,0x2a,0x1,0x0, + 0x68,0x2b,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2b,0x1,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0,0x68,0x2b,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0, + 0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0x2a,0x2,0x0,0x68,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xfe,0x7,0xff,0x3f,0xff,0x83,0xf8,0x3f,0xf8,0x0,0xfc, + 0x3,0xff,0x0,0xf0,0x1f,0xf0,0x0,0x10,0x0,0x7f,0x0,0x40,0xf,0xf0,0x0,0x0, + 0x0,0x1e,0x0,0x0,0xf,0xf0,0x0,0x0,0x0,0x6,0x0,0x0,0xf,0xe0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xf,0xe0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x1f,0xf0,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xf8,0x0,0x0, + 0x0,0x0,0x0,0x0,0x3f,0xfc,0x0,0x0,0x0,0x0,0x0,0x0,0x1f,0xfc,0x0,0x0, + 0x0,0x0,0x0,0x0,0x1f,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0xf8,0x0,0x0, + 0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xf8,0x0,0x0, + 0x0,0x0,0x0,0x0,0x3,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xf8,0x0,0x0, + 0x0,0x0,0x0,0x0,0x3,0xf8,0x0,0x0,0x0,0x0,0x0,0x0,0x3,0xfc,0x0,0x0, + 0x0,0x0,0x0,0x0,0x7,0xfe,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0xff,0x0,0x1, + 0x0,0x0,0x0,0x0,0xf,0xff,0xc0,0x3,0xc0,0x0,0xe0,0x0,0x1f,0xff,0xf0,0xf, + 0xf0,0x1f,0xf8,0x0,0xff,0xff,0xf8,0x1f,0xff,0xff,0xff,0xff,0xff,0xff,0xf0,0xf, + 0xde,0x1f,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0xf,0xff,0xff,0xff,0xff,0xc0,0x0, + 0x0,0x7,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0x80,0x0, + 0x0,0x3,0xff,0xff,0xff,0xff,0x80,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0x80,0x0, + 0x0,0x3,0xff,0xff,0xff,0xff,0xc0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xc0,0x0, + 0x0,0x3,0xff,0xff,0xff,0xff,0xe0,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xf0,0x0, + 0x0,0x3,0xff,0xff,0xff,0xff,0xf8,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xfc,0x0, + 0x0,0x3,0xff,0xff,0xff,0xff,0xfe,0x0,0x0,0x3,0xff,0xff,0xff,0xff,0xff,0x0, + 0x0,0x7,0xff,0xff,0xff,0xff,0xff,0xe0,0x0,0x1f,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/down_arrow.png + 0x0,0x0,0x0,0x85, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x2,0x0,0x0,0x0,0xb4,0xb4,0x2,0x1d, + 0x0,0x0,0x0,0x4c,0x49,0x44,0x41,0x54,0x78,0x9c,0xd5,0xd0,0xb9,0x11,0x80,0x0, + 0x8,0x44,0xd1,0xfd,0x43,0x63,0x94,0x46,0x69,0x74,0x86,0x81,0x8e,0xf7,0x81,0x91, + 0xe3,0xc6,0xef,0x13,0x20,0xfd,0x73,0x54,0x55,0x5f,0x1b,0xe0,0xee,0xad,0xc3,0x60, + 0x99,0xd9,0x9,0x0,0x49,0x26,0xe9,0x31,0x18,0xe9,0xa4,0xef,0x83,0x99,0x2e,0xfa, + 0x2a,0x58,0xd3,0x8d,0x3e,0x6,0x3b,0x7a,0xbe,0x88,0x78,0xf5,0xd6,0x4f,0x36,0x0, + 0xa9,0xcf,0x17,0x72,0x33,0x67,0xb2,0xe,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44, + 0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/cusdrLogo.png + 0x0,0x2,0x10,0x6e, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x1,0xf4,0x0,0x0,0x1,0x2c,0x8,0x6,0x0,0x0,0x0,0x35,0xbb,0x41,0xc8, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0, + 0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1, + 0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0x8,0x1d, + 0x11,0x18,0x20,0x82,0xbf,0xf3,0x19,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x78, + 0xda,0x94,0xbd,0x5d,0xaf,0x6e,0x5d,0x76,0x14,0x36,0x6a,0xb1,0x85,0x72,0xc1,0x2f, + 0x89,0x88,0xb2,0x13,0x23,0x1b,0x84,0xed,0xc6,0xbe,0x23,0x88,0x3b,0x2e,0xa3,0x28, + 0x96,0x83,0x8c,0xe3,0xf0,0x61,0xc7,0x49,0x24,0x64,0x84,0xc2,0x47,0x42,0x1a,0x6c, + 0xec,0x10,0x1c,0x22,0x4,0x52,0x24,0xee,0x72,0x15,0x21,0xe4,0xbb,0xa4,0x3b,0xb4, + 0x90,0x4d,0x2,0xbd,0x7f,0xd1,0xae,0x5c,0xec,0xb5,0xe6,0xac,0xaa,0x31,0xe6,0x73, + 0x5e,0xda,0x6a,0xf7,0xfb,0x9e,0xf3,0x7c,0xac,0x67,0xad,0x39,0xe7,0x18,0xa3,0x46, + 0x8d,0x2a,0xd4,0x1f,0xfa,0xf7,0x7f,0x5c,0x55,0x55,0x44,0x15,0xaa,0x8a,0x25,0xff, + 0x61,0xad,0x3f,0x5c,0x7f,0x87,0x2a,0x70,0xff,0xb3,0xbd,0x1,0xfe,0x9e,0xf1,0x25, + 0xf7,0x1f,0x10,0xf2,0x1d,0xf9,0x5e,0xf9,0x73,0x40,0xde,0x3f,0xbc,0x56,0x3f,0x1f, + 0xf7,0x3f,0xd8,0x6f,0xe1,0xe1,0xf2,0x20,0x7f,0x7e,0xff,0x9e,0xf5,0x5d,0xf9,0x7b, + 0xab,0x8a,0x72,0x3d,0x25,0xff,0xfe,0x5c,0xef,0xcb,0x7b,0xa7,0xef,0x99,0x7e,0x77, + 0xbe,0x2f,0xff,0xf3,0xea,0xf7,0x3c,0xcf,0x3,0xfd,0xfe,0xe8,0xef,0xa9,0xfc,0x2d, + 0xfa,0x3e,0x7d,0x1b,0x87,0x7b,0x9e,0xcf,0xa6,0xe2,0xf9,0xca,0x9a,0xb0,0x7b,0x2b, + 0x9f,0x85,0xef,0xf0,0xcc,0xed,0x37,0xc6,0xf5,0x21,0xde,0xd3,0x3e,0x6b,0x78,0xae, + 0xd3,0x77,0xd9,0x3d,0xc1,0xe1,0x75,0xc3,0xfd,0xa8,0x58,0x67,0xf9,0x3d,0xf9,0xfb, + 0xd6,0xb5,0xe8,0xbd,0xe7,0xf0,0x78,0x87,0xcf,0x19,0x7f,0xe3,0xfd,0xec,0x9e,0xf, + 0x68,0x4b,0x69,0xb8,0x1f,0xdf,0xba,0xbf,0x35,0xdd,0x87,0x1a,0xf6,0x77,0xfc,0x2e, + 0xfb,0xce,0x57,0xf7,0xb4,0x6a,0xbe,0xd8,0x5c,0x87,0xb9,0xee,0xf2,0xdc,0x99,0xd6, + 0x6d,0x9e,0x3,0xf7,0xff,0x52,0xd6,0x5d,0xf1,0x70,0x6f,0xa6,0x6b,0xac,0xbe,0xcf, + 0x99,0xfb,0xfa,0x70,0xe6,0xe8,0xf5,0xd,0x47,0xe0,0xfe,0x3c,0x9e,0xbf,0x7b,0xdd, + 0xc7,0xbc,0xf6,0xe1,0xc,0xc8,0xb3,0x60,0xfd,0xbc,0xdc,0x33,0x7a,0x4d,0x98,0x7f, + 0x6b,0xae,0x6d,0x3d,0xaf,0xaa,0xfc,0x7e,0xca,0xb3,0xf9,0xfa,0xd7,0xf8,0xa1,0x79, + 0xee,0xca,0x3d,0xfc,0x7a,0x64,0x3c,0x3f,0x33,0xc,0x47,0x4,0xe,0xff,0x5b,0x2f, + 0x96,0xef,0xf8,0xe8,0xb9,0xef,0x8d,0xbe,0x99,0xba,0xdf,0x5e,0x1c,0x1b,0xcf,0x6f, + 0x1e,0x8e,0xf0,0xe3,0xad,0xad,0xf3,0xf6,0x6a,0xcb,0x2d,0x8e,0x70,0x7f,0x24,0xfd, + 0xc7,0x9f,0x3e,0x1f,0x55,0x75,0xd9,0x62,0x99,0x36,0xe1,0xba,0xe9,0xf0,0x7f,0x7, + 0xe6,0xa0,0x83,0x6f,0x1c,0x58,0xe4,0xbe,0x91,0x78,0xb5,0xc0,0x25,0x8,0x42,0xff, + 0xec,0xb9,0x56,0xdd,0xd8,0xec,0x8b,0xd2,0x9e,0x2e,0xea,0x9c,0xb4,0x4c,0xd7,0x29, + 0x9b,0xb9,0x24,0x50,0xd5,0xb3,0x29,0x39,0xdc,0x2b,0xca,0x81,0x4c,0xbf,0x87,0xa4, + 0x27,0x43,0xf6,0x14,0x38,0x7,0x26,0x7b,0x2e,0xc3,0x77,0x2,0xfb,0xf7,0x64,0xe2, + 0xd0,0x72,0x3,0x59,0x81,0x19,0x4b,0xf5,0xb3,0x29,0xbf,0x11,0xf1,0x9b,0xe2,0xf6, + 0x7c,0xfd,0x17,0xbe,0x39,0x2a,0x12,0xa2,0xb5,0x62,0x75,0x43,0xb1,0xdf,0x6b,0xfb, + 0x7e,0xfa,0x7d,0x2f,0xbd,0xf7,0xf7,0xe7,0x13,0x1e,0x5c,0xa,0x43,0x2e,0xf4,0x2a, + 0x40,0x4f,0x87,0xa9,0x5e,0xcb,0xf4,0xfc,0xee,0x3f,0xb7,0xe7,0x25,0x7f,0xa6,0x6b, + 0xfa,0x79,0x36,0xcf,0x73,0x42,0x4,0x49,0xbd,0x6f,0x79,0x28,0xaf,0x7b,0x28,0xcf, + 0xde,0xe,0x58,0xd9,0x8b,0x9c,0x12,0x18,0xb9,0x5f,0x9a,0x40,0xeb,0xb3,0x40,0xec, + 0x55,0xf0,0x74,0xdc,0xec,0xef,0xd6,0xc3,0x97,0xba,0xff,0x31,0xec,0x27,0xce,0x27, + 0x6c,0xee,0xeb,0xca,0xc0,0x25,0x67,0x2,0xe2,0xb3,0x9f,0xe0,0x93,0xc1,0x3c,0xaf, + 0x3,0x7a,0xce,0xa0,0x47,0x1,0xa0,0x9f,0x11,0x76,0x7f,0xf6,0x1e,0x40,0xae,0x41, + 0xc0,0x6f,0xab,0x5,0x51,0xfa,0x3d,0x27,0xbe,0x42,0x0,0xca,0xaf,0xb1,0x86,0x7d, + 0x74,0xff,0xe,0x70,0xba,0x57,0xe8,0xdb,0xc5,0xce,0xe7,0xfb,0x7b,0x34,0x9,0xb4, + 0x67,0xb,0x3b,0xf1,0x91,0x5,0x8c,0xbc,0xc,0x38,0xd5,0x14,0xfa,0x7e,0xec,0x63, + 0xf0,0xfe,0x66,0xbb,0xce,0x75,0xe4,0xfa,0x6f,0x25,0x7c,0xed,0x3,0xf2,0xfe,0xe7, + 0xad,0xf1,0x9e,0xfd,0x31,0x28,0xe8,0xdf,0x1,0x85,0x7b,0xdd,0xeb,0x73,0xc0,0xfd, + 0x7,0xeb,0x94,0x41,0x5e,0x5b,0x4,0x28,0xb9,0x37,0xc8,0x9b,0xfc,0x5c,0xe7,0x3e, + 0xec,0xfc,0xfb,0xec,0xf9,0xe9,0x1f,0x21,0xb6,0x33,0xf6,0xa7,0x40,0xff,0x1e,0x45, + 0x7d,0x7e,0xeb,0x77,0x96,0x5c,0x3f,0xda,0x11,0x7,0xdc,0xef,0x8b,0x25,0xf9,0xbc, + 0xee,0xf2,0x43,0x6c,0xd8,0xd8,0x96,0xd9,0x50,0xe,0xd5,0xc,0x3a,0xba,0x21,0xb8, + 0x7f,0x2d,0xa7,0x85,0x25,0x87,0xb3,0x1e,0xe0,0x80,0x1f,0x2e,0xcf,0x7b,0xc8,0x8, + 0x12,0x1a,0x68,0xe9,0x8b,0x97,0x18,0xe,0x82,0xf2,0x80,0x96,0x41,0x92,0x99,0xb1, + 0x4d,0xc5,0xc9,0x84,0x46,0x20,0xaa,0xd4,0xf2,0xec,0xb8,0xe2,0xde,0xe9,0x2,0x6b, + 0x49,0xc8,0x21,0x48,0xd9,0x7d,0xe4,0x39,0x41,0x1a,0x77,0x62,0x6,0x2f,0xf8,0xfb, + 0x5a,0x1e,0x43,0x7f,0x76,0xfa,0xdf,0x15,0x44,0xb9,0xf,0x75,0xb,0x74,0xe5,0xc1, + 0xe2,0x50,0x84,0xf8,0x1,0x7b,0x48,0x14,0x58,0xfd,0x99,0x25,0xa,0x83,0x3c,0x94, + 0x23,0x20,0x23,0x6e,0xa1,0xde,0x1b,0x66,0x22,0x26,0x1,0x38,0x2b,0xe1,0x4c,0x60, + 0x29,0xf7,0x64,0xfa,0x33,0xc6,0x3e,0x58,0xf7,0x2a,0x7e,0x4f,0xe9,0xe7,0xd2,0x7f, + 0xf3,0xa,0x10,0xfd,0x76,0xed,0xfb,0xc4,0x58,0x67,0xf5,0x15,0x80,0x80,0xe1,0xb0, + 0x91,0x24,0xa1,0xe0,0xb9,0x8,0xf4,0x50,0xcd,0x84,0xb,0xc3,0x3e,0x47,0xdc,0x1b, + 0xfd,0xdf,0x29,0xb1,0xf4,0xc4,0x6,0xa8,0x1e,0xb4,0x57,0xad,0x80,0x7d,0x30,0xaf, + 0xbd,0x8d,0x82,0x24,0x13,0xa0,0x7c,0x96,0xee,0x3f,0xbb,0x34,0xd,0xa6,0x71,0xea, + 0xb1,0xe2,0x7b,0xf5,0xb0,0x86,0x7d,0x36,0xd7,0x3f,0x1f,0x70,0x34,0xf4,0x0,0xa0, + 0x67,0x2,0xf5,0x0,0x67,0x5c,0x87,0x6,0xd3,0xc2,0x5d,0xa1,0x45,0x10,0x59,0x7b, + 0xe9,0xb2,0x24,0xed,0xeb,0xed,0x97,0xc5,0xfe,0x27,0x98,0x1,0x53,0x78,0xd9,0x1f, + 0x45,0x9,0xca,0x90,0xbf,0xdf,0xc7,0x74,0x6,0xcf,0x5a,0xff,0x8e,0x8,0xea,0x99, + 0xcb,0xc1,0x92,0x8f,0x1d,0x48,0x81,0x48,0xa6,0xa6,0x1c,0xb0,0x45,0x46,0xdc,0xd7, + 0xf5,0xf5,0x23,0x9,0xde,0xbf,0xdb,0x13,0x4c,0xca,0xd9,0xe5,0xb9,0x17,0x64,0xed, + 0xf4,0xa0,0x98,0x99,0xc,0xed,0xee,0xde,0xdf,0x7c,0x79,0xf8,0x62,0xed,0x60,0x5a, + 0x99,0x30,0xe8,0xe9,0x73,0x7,0x5d,0xe0,0xb9,0xf6,0x48,0x2c,0x9e,0xef,0xb3,0xa3, + 0x12,0x52,0xa3,0xed,0x67,0xc0,0xaf,0x4f,0x5a,0x7b,0x95,0xba,0x7e,0xe5,0xbf,0xbc, + 0xd7,0xeb,0x5b,0x83,0xf6,0xac,0x92,0x90,0x4c,0x17,0x87,0x6a,0xa0,0x55,0x56,0xa, + 0x2f,0xc5,0x29,0xdd,0xe0,0x58,0x9,0xc,0x25,0xef,0x81,0x1e,0xe2,0x53,0x10,0x92, + 0x0,0xc3,0xac,0x3e,0x27,0x98,0x31,0x70,0x8c,0x6,0x35,0xc5,0xe1,0x58,0x13,0x14, + 0x7d,0x80,0x7b,0xad,0x52,0x3e,0xc1,0xd0,0x7,0xb4,0x1,0x99,0x4,0x55,0x7c,0xd6, + 0x0,0xa3,0x9f,0xa0,0xe4,0xf1,0x8f,0xd0,0x21,0x3a,0x43,0x1a,0x70,0xa8,0x94,0xca, + 0xa1,0x3f,0xbd,0xa7,0xad,0xbd,0x11,0xc9,0xb,0xb3,0xe5,0x12,0xd5,0x25,0xa2,0x92, + 0xe7,0x80,0xc6,0x20,0xd0,0x94,0xfb,0x7e,0x7c,0xdd,0x4e,0x9c,0x93,0x14,0xc5,0xec, + 0x24,0x20,0x68,0x62,0xf5,0x75,0x50,0x33,0x4a,0x7,0x46,0x79,0xe2,0x6b,0xe8,0x81, + 0x17,0x81,0xe7,0x0,0x19,0xd0,0x90,0x96,0xa7,0x33,0x2a,0xe,0xc8,0xa7,0x7e,0x5d, + 0x27,0x2b,0xda,0x3a,0xb9,0xb9,0xed,0x7a,0xe3,0xfa,0x88,0x86,0xf2,0x2a,0x12,0x85, + 0x40,0x9f,0xc9,0xa1,0x73,0x3,0x8,0xc,0xfa,0x54,0x3e,0xfd,0xb6,0x30,0x72,0x74, + 0x4d,0x7e,0x9e,0x43,0x8d,0x51,0x11,0x42,0xe0,0xcd,0xe7,0xa8,0x85,0xec,0x5,0xc4, + 0xf6,0x86,0x7e,0x46,0x7b,0xb6,0xd7,0x7a,0x7e,0xab,0x3a,0x21,0x64,0x89,0x3c,0xc7, + 0x3e,0xe4,0xa0,0xe7,0x50,0x39,0x7d,0x3d,0x13,0xdc,0xfb,0x80,0xe5,0x49,0xb7,0x1d, + 0xea,0xe0,0xfd,0x14,0x6b,0x5,0x93,0xcc,0xf4,0xb1,0xe,0xeb,0xe7,0xb6,0x70,0xb8, + 0xf6,0xfb,0xb3,0x1,0x9,0x4f,0x12,0x58,0xee,0x7d,0xb6,0xe,0x6e,0x5f,0x41,0xf2, + 0xbf,0x2,0x59,0xdf,0xfb,0x81,0xb6,0x25,0xb1,0xc2,0x1b,0xf2,0x37,0xd1,0xef,0xd2, + 0x73,0x6d,0xb4,0x5a,0x2f,0x61,0xff,0x5a,0x55,0x30,0x25,0x26,0x30,0x7e,0xdf,0xfe, + 0xdd,0xb8,0x7f,0xa,0x6,0x98,0x1e,0xfa,0xb1,0x2b,0xa0,0x95,0xc0,0xcc,0xfb,0xb7, + 0x42,0xc2,0x7,0xd6,0x75,0x2c,0x60,0xa8,0xf8,0x75,0x5d,0x80,0xff,0x6a,0x5b,0xdf, + 0x90,0x30,0x82,0x7e,0x8c,0xf1,0xa9,0x9c,0x9f,0xfb,0xe8,0xb0,0xb,0xee,0xd,0xb0, + 0xbb,0x40,0x88,0xe3,0x10,0x9e,0xe7,0xca,0x42,0x5e,0xfb,0x16,0x91,0x52,0xe1,0x80, + 0x1b,0xc2,0x1,0x4c,0xdc,0x51,0x3e,0x9f,0xc,0xac,0x42,0xaf,0x2,0x68,0x61,0xac, + 0x57,0xe8,0x18,0x2,0x6e,0x2b,0x8,0x29,0x50,0x79,0xd,0x95,0xf4,0xd0,0x5f,0x46, + 0x54,0xf6,0x60,0xeb,0xaf,0x78,0x25,0x54,0xe7,0x1e,0x72,0xf6,0xaf,0x31,0x54,0x5f, + 0x5a,0xb9,0x0,0xbd,0x2a,0x69,0x3d,0x94,0x44,0x10,0xe2,0xb3,0x18,0x48,0x0,0x10, + 0x95,0x1d,0x7,0xb8,0x1c,0x56,0xb5,0x40,0xab,0x68,0xa2,0x37,0x79,0x40,0xcf,0xee, + 0x33,0xb1,0xd1,0xdf,0x6f,0x88,0x1,0xa4,0x8a,0x49,0x48,0x51,0x36,0x38,0x87,0x7b, + 0x1,0xf8,0xcf,0x46,0xc0,0x61,0x79,0x2b,0x30,0x5,0xd2,0xbc,0xb7,0x88,0xa,0x71, + 0xff,0x1e,0x64,0xa5,0xac,0x95,0x25,0x12,0x56,0xc7,0xb0,0x14,0xee,0x8a,0x89,0x43, + 0xfb,0x5,0x9,0x33,0x3b,0xbc,0xa5,0xaf,0xb7,0x6c,0x99,0x30,0x78,0x10,0x4c,0xa8, + 0x7a,0x1f,0x62,0x18,0x70,0x4f,0xcd,0xa4,0x75,0x1d,0x1,0x18,0xe0,0x43,0x48,0xa1, + 0xfd,0xf5,0xf7,0x40,0x56,0x9b,0x68,0xb9,0xd9,0xfe,0xee,0xe7,0xa,0x2e,0xc9,0x69, + 0xbd,0x7c,0x24,0x2,0x1d,0xba,0xaf,0x8f,0x52,0xd,0x5b,0x25,0x26,0x9,0xde,0xe, + 0xb0,0xfa,0xdb,0x64,0x8b,0x5c,0xfe,0x5b,0xbd,0x6d,0xa9,0x6b,0xe,0xf6,0x67,0x5c, + 0xbf,0x20,0x2,0x36,0xf6,0xf5,0xc1,0xa1,0x94,0xfb,0xbd,0xf0,0xf7,0xdd,0xf7,0x6b, + 0x2f,0x7f,0x2e,0x44,0xe1,0x39,0xc4,0x1,0xca,0x6b,0xbc,0xda,0x65,0x4,0xfc,0x7d, + 0x0,0xd3,0xe1,0xd5,0xe7,0xb0,0x5e,0xff,0xeb,0xeb,0x1a,0x82,0x44,0xb0,0xb2,0x2a, + 0x7f,0xee,0x11,0x1a,0xda,0x1,0xab,0x8c,0xf7,0x81,0xcc,0xfc,0xed,0xab,0x12,0x94, + 0xbb,0xa1,0xf7,0xea,0xe9,0x5d,0x13,0x52,0x85,0xc6,0x7d,0xb3,0xea,0x15,0x92,0xb8, + 0xc4,0xef,0xc2,0xe,0xa0,0x9a,0x68,0x3f,0x48,0x1,0x9f,0x7b,0xcf,0x6b,0x57,0xe9, + 0xc3,0x96,0x53,0x48,0x99,0x59,0xd5,0x3f,0xeb,0x4f,0x8e,0x7c,0xb2,0x1c,0x82,0x5e, + 0xaf,0x87,0x3c,0xcb,0xb2,0x24,0xd1,0xea,0xe0,0x1,0x98,0x51,0x70,0x17,0xa5,0x9f, + 0xab,0xf8,0x3b,0xbc,0x8b,0xa1,0x49,0x43,0xec,0xb5,0xe7,0xbd,0x9a,0x84,0xe8,0xde, + 0x2,0x3b,0x4a,0x4b,0x85,0xef,0x5b,0xbb,0xb0,0x56,0xca,0x86,0x44,0xf7,0x4,0x25, + 0xdb,0xbf,0x52,0xce,0x4c,0x79,0xbe,0x5c,0xff,0x3f,0x90,0x86,0xfb,0x1d,0x97,0x55, + 0x99,0x46,0x58,0x88,0xa,0x96,0x1d,0xd1,0x5c,0xff,0x42,0x81,0x1,0x9,0xf,0x8e, + 0x3c,0x54,0x78,0x1c,0xfa,0xc1,0xeb,0x23,0x31,0x43,0xa5,0xad,0xd9,0x73,0xf7,0xba, + 0x10,0xd0,0x77,0x42,0xee,0xad,0xf7,0xb9,0xab,0x55,0xb4,0x2a,0x17,0x91,0x63,0xa0, + 0x41,0xee,0xc0,0x1c,0xb8,0x40,0x39,0x78,0xa5,0x5f,0xb3,0xf,0x5e,0x58,0x45,0xe2, + 0xc1,0x59,0xcf,0xb9,0x1,0xc2,0xcb,0xe0,0xaa,0x8b,0x4b,0x36,0x81,0x17,0xfb,0x68, + 0x68,0x72,0xe7,0x29,0xf5,0x4c,0x90,0x52,0xe5,0xe9,0x93,0x46,0xc0,0x61,0xbb,0x4a, + 0xcb,0x3e,0x1f,0xac,0xfb,0x34,0xf2,0x13,0x2a,0xa1,0x23,0xef,0xcd,0xef,0xdf,0xa4, + 0x3d,0xae,0x80,0x5a,0x23,0x14,0xc0,0x72,0x35,0x48,0xcd,0xe3,0xaf,0xca,0xdf,0xba, + 0xb6,0x10,0xfc,0x5a,0x1d,0xf4,0xcb,0xbf,0xdf,0x15,0x5f,0x5d,0xde,0x87,0xdb,0x21, + 0x4c,0xe1,0x53,0x46,0x55,0x2b,0x15,0x47,0xc1,0x10,0x71,0x64,0xdf,0x55,0x2,0xf6, + 0x57,0xd0,0xf2,0xdf,0xc6,0xe8,0xcd,0x69,0xf0,0x64,0xd0,0x5d,0x30,0xc0,0xcd,0x18, + 0x8,0x38,0xda,0xc7,0x7b,0xe,0x30,0x92,0x12,0xb2,0xb1,0xd6,0x29,0x2c,0x1,0xa0, + 0x7c,0xb4,0x6,0x1b,0xf,0x2e,0x4c,0x80,0x2a,0x2,0x1b,0x6a,0xe8,0x1e,0xd0,0x7b, + 0xc6,0xc4,0xfe,0xef,0xb3,0xf7,0x29,0xbf,0x1d,0x79,0x64,0xc8,0x7d,0x22,0x34,0x51, + 0xc2,0x8,0xb8,0x34,0x9a,0x80,0x42,0xf0,0xc8,0x9a,0x1d,0x76,0xdc,0x71,0x25,0x76, + 0xb5,0xaa,0xd7,0xf5,0xcf,0x12,0xa0,0xb3,0xbf,0xee,0xdd,0x43,0x49,0xc,0x57,0x55, + 0xbb,0x13,0x5e,0xea,0x77,0x1b,0x88,0xa,0x43,0x6c,0x10,0xad,0x3,0x18,0xdd,0x23, + 0x12,0x56,0x39,0x53,0x0,0xb6,0x1d,0x46,0xf6,0x56,0xc5,0xa,0x3f,0xf4,0x5f,0x81, + 0x95,0x98,0x50,0x60,0x66,0x3f,0x57,0x1e,0xe4,0xad,0x15,0x6d,0x6d,0x47,0x25,0xcc, + 0x9c,0xc4,0xb1,0x84,0xe9,0xe5,0xf5,0x97,0x20,0xc4,0xfa,0x1a,0x3d,0x5b,0xac,0x5d, + 0xc1,0xf1,0xde,0x65,0xf2,0x56,0x96,0x4,0x63,0xe8,0x34,0xc9,0xde,0xbf,0xf6,0xde, + 0xf3,0xc4,0x3e,0x8,0xbf,0xc3,0xbd,0xd5,0x73,0x3,0x96,0xa8,0x46,0x82,0x83,0xaa, + 0xb7,0x8a,0xec,0xa9,0x73,0xc6,0xd0,0xfb,0xba,0xab,0x5f,0x81,0x11,0x22,0x43,0x64, + 0x2c,0xd,0x6e,0x3d,0xf6,0x4d,0x36,0x94,0xf6,0x54,0xf4,0x50,0x68,0x8c,0x1,0x8, + 0xe8,0x1,0x8a,0x7b,0xb1,0x9,0xf4,0x6f,0xd9,0x9e,0x1c,0x66,0x94,0x9e,0x26,0x23, + 0x12,0x7c,0xbd,0xf6,0xd2,0xee,0xc5,0x82,0xcb,0x56,0xc5,0xb0,0x98,0x9e,0x6c,0x7, + 0xeb,0xdc,0xbb,0x4e,0x18,0xcd,0x39,0x53,0x23,0x8c,0x35,0x31,0x9b,0xf5,0xe8,0x45, + 0x7,0xdf,0x57,0x68,0xc8,0x40,0xa5,0xdf,0x10,0x30,0xab,0xc1,0x95,0xfa,0x54,0x31, + 0xac,0x83,0x5,0x3b,0xb,0xeb,0x33,0xae,0xff,0xeb,0x6f,0xbd,0xbf,0x85,0xcb,0xa1, + 0x7c,0x85,0x93,0x8d,0x28,0x2d,0x89,0x4d,0x83,0x53,0x49,0x83,0x66,0x41,0x9f,0xbe, + 0x78,0xa0,0xd4,0x5,0x97,0x45,0x7d,0xbb,0xef,0xd5,0x5e,0x54,0x9,0xd0,0x90,0xde, + 0x67,0xa4,0xb4,0x29,0xa0,0xd5,0x14,0x76,0x86,0xe,0x96,0x41,0xcb,0xf,0x44,0x4e, + 0x62,0x20,0x19,0x79,0x6b,0x3,0x72,0x30,0x5b,0x2,0x49,0xa9,0x72,0xe8,0x70,0x21, + 0xa3,0xa9,0x8b,0x8d,0x45,0x1a,0x18,0xd6,0xe0,0xbc,0x42,0x4b,0x28,0xb4,0x4b,0xb1, + 0xf6,0x9d,0x2d,0x9e,0x80,0x16,0x83,0x5c,0xaa,0xeb,0x6,0xd1,0x9f,0x64,0xd,0x40, + 0x4d,0xae,0x49,0x8,0x14,0xce,0xcd,0x3,0x70,0x6,0x6f,0xe7,0x18,0x28,0xad,0x67, + 0xad,0xf9,0x5,0xa3,0xd2,0xde,0x56,0x70,0x88,0x7c,0x27,0x9c,0x6c,0xbc,0x57,0x3f, + 0xab,0x5,0xbc,0x95,0x36,0x18,0xd,0x83,0xd8,0xd5,0x30,0x6c,0x85,0xc5,0x77,0x36, + 0xb4,0x26,0x76,0x2c,0x22,0x10,0x82,0x16,0xe,0x3d,0x46,0xcc,0x69,0xaa,0xb6,0x9, + 0xfc,0xbb,0xf7,0xa2,0xa0,0x75,0xb3,0xfc,0x4c,0x58,0x7b,0x8,0xf5,0x85,0x28,0xe6, + 0xa4,0x92,0x77,0x3e,0xe4,0xd6,0xee,0x27,0xda,0x10,0x44,0x70,0xaf,0x71,0xfa,0x1a, + 0x6c,0x49,0x44,0xe,0x46,0x3d,0x7b,0xcc,0x2,0x13,0x5b,0x40,0x5,0xf3,0xc0,0x1a, + 0x20,0xf6,0x86,0x79,0x4b,0x45,0x6c,0x44,0xe9,0x3c,0x94,0x31,0x9c,0xcb,0x35,0x12, + 0xf5,0xa3,0x7f,0x54,0xc5,0xeb,0x38,0x5c,0x91,0xa0,0x9e,0xa1,0xb6,0x13,0x55,0x4a, + 0xd7,0x36,0xe2,0x2,0x48,0x79,0x30,0xb8,0x3,0x3a,0x6,0x36,0x22,0x39,0x4c,0x64, + 0x41,0xb7,0x50,0x64,0xa7,0xdc,0x30,0x45,0x84,0x8,0x4c,0x4,0xf3,0xfc,0xf7,0xeb, + 0x39,0x54,0x3c,0xe0,0xd9,0xd2,0xc6,0x90,0x97,0x49,0x45,0xb6,0xfa,0x5e,0x31,0xba, + 0xc1,0x9a,0x89,0x6e,0x9a,0x41,0xb2,0xe6,0xfe,0x3f,0xef,0x5,0xce,0xb5,0xe8,0x9f, + 0x2a,0x9e,0x1,0x2b,0xd6,0x14,0x16,0x25,0x28,0xdd,0xef,0x80,0xb2,0x68,0x9f,0xca, + 0x8c,0x2,0xcb,0x70,0x57,0x76,0xda,0x87,0xe4,0xbe,0xd7,0xc9,0xd5,0xdb,0x13,0x63, + 0x7b,0x95,0x41,0xc6,0xbd,0xc,0x4a,0xa6,0x1f,0x1c,0x24,0x56,0x8f,0xc,0xc1,0x5e, + 0x45,0xb4,0x5b,0xa8,0xe8,0xc3,0xfa,0x78,0xae,0xe4,0xa,0xd4,0xea,0xda,0x3b,0x33, + 0x59,0x89,0xc5,0xa3,0xdc,0x9f,0x6d,0x44,0x2e,0x39,0xf0,0x34,0xb6,0x71,0x27,0x74, + 0x23,0xf4,0xb,0x39,0xc,0x99,0xc7,0x39,0x2,0x0,0xdf,0xcf,0x74,0x77,0x50,0x20, + 0xfd,0xeb,0x24,0x7d,0x7b,0xd2,0xc8,0x3c,0x54,0xaa,0xbe,0x80,0x2f,0x4,0x27,0xa0, + 0x60,0xd0,0xdd,0x94,0xd6,0xee,0x9c,0x17,0xd2,0x67,0x67,0x1,0x97,0x40,0xaf,0x1a, + 0x88,0xd0,0x47,0x35,0xe3,0xb0,0x76,0x14,0xac,0x5d,0xb0,0xe5,0xd9,0x18,0x98,0xd4, + 0x2d,0x7,0xbf,0xd7,0x17,0x15,0x81,0x41,0xef,0x19,0xa3,0xf5,0xb1,0x25,0xc0,0xb0, + 0x4f,0x20,0x0,0xfe,0x5e,0x47,0xe8,0x86,0x56,0x1c,0x7c,0x97,0x31,0xc6,0x8b,0xa, + 0xde,0x23,0xa6,0x62,0x11,0x43,0x7f,0x13,0x36,0x66,0x28,0x21,0x1b,0x3a,0xd1,0xa, + 0xa7,0xb7,0x44,0xff,0x99,0x8a,0x0,0x4d,0x63,0x6a,0xb8,0x51,0xe,0x20,0x26,0x49, + 0xb3,0x9a,0x42,0x8c,0x3d,0xe,0xd9,0x7f,0x4e,0x8b,0xb1,0x57,0x73,0xd9,0x5a,0x84, + 0xd1,0x68,0xd0,0x2,0x7,0x30,0x40,0x13,0x35,0xd,0x23,0x5d,0x92,0x1c,0x65,0x12, + 0x38,0xa1,0x6f,0x7b,0xed,0x76,0xa,0xa,0xe2,0x1c,0x9,0x40,0xd5,0xce,0x6d,0x9c, + 0xd7,0xb5,0x71,0x68,0x78,0x1c,0xa8,0x6e,0xd,0x6c,0xb0,0xb5,0x48,0xed,0x60,0x6a, + 0xe0,0x72,0x70,0xba,0x90,0xc4,0xf1,0x32,0x2,0x39,0x84,0xb7,0xc1,0xa9,0x40,0xe3, + 0xbc,0xbf,0xf6,0x9,0x45,0x69,0xf1,0x64,0xc,0x66,0x2c,0x9,0xd6,0x5b,0xd4,0x16, + 0xbd,0x2a,0x5d,0xcc,0x3a,0x8e,0xc,0x1b,0x92,0xc1,0x7b,0x42,0x9f,0x65,0xbe,0x37, + 0x31,0xa3,0xf4,0xcb,0xd1,0xef,0xb6,0xc9,0xee,0xef,0xa1,0xcc,0x31,0xc2,0x4b,0x5a, + 0xef,0xab,0xa2,0x7c,0xe3,0x6a,0xf5,0x9c,0xed,0x5b,0xcb,0xa9,0xd1,0xfb,0x2a,0xb6, + 0x46,0x9e,0x4a,0x4c,0x9,0x2e,0x90,0xf5,0xe3,0x87,0x75,0x3,0x11,0x65,0x3e,0xb4, + 0xf5,0x64,0x94,0xb2,0xd3,0x36,0x37,0xfa,0x28,0x6a,0x3f,0x23,0x6c,0xc1,0x67,0x32, + 0xa1,0x9f,0xd1,0x27,0x90,0xa4,0xc7,0x2a,0x23,0x2f,0xce,0x77,0xdb,0xcf,0x3b,0x89, + 0x19,0x5f,0x90,0xf3,0x25,0x93,0x8d,0x6c,0x77,0x7e,0x11,0xda,0x1e,0xe2,0xf,0x37, + 0xf3,0x13,0x36,0x65,0x3,0xb,0x24,0xda,0x42,0xd8,0xf4,0xa,0x7c,0x55,0xea,0x16, + 0x5c,0x6b,0x80,0xca,0x1c,0xc2,0x72,0x20,0x2e,0xc6,0xb9,0x22,0x70,0x6b,0x75,0xc6, + 0x40,0x55,0x0,0x44,0x95,0xd6,0x5a,0xf7,0xab,0xc7,0xb5,0xa0,0x3e,0x32,0xd9,0x33, + 0x9d,0x80,0xd5,0xe8,0x8e,0x6c,0x41,0x16,0x99,0xde,0x26,0xab,0xe6,0xd2,0xa,0x6, + 0x27,0xae,0x5d,0xfb,0x7e,0xb4,0xd3,0x4e,0xda,0x4a,0x6c,0xd8,0x46,0x63,0x14,0xd0, + 0x50,0x93,0x7e,0xa5,0x95,0x7d,0xc8,0xc6,0x3f,0xd,0x56,0x7d,0x83,0x8,0xd1,0xe, + 0x56,0xe4,0x8f,0x1b,0x3e,0xbf,0x6,0x4,0x48,0x9a,0xd4,0xd5,0xe7,0xba,0xfb,0x94, + 0x4a,0x9e,0xf1,0xe0,0x9,0xb9,0xac,0x2,0xaf,0xfb,0x20,0xd6,0xc0,0x71,0x65,0xd6, + 0xea,0xfd,0xd5,0x72,0xce,0xd2,0x54,0x1,0x2a,0x57,0xa6,0xcb,0x7f,0x40,0x90,0x82, + 0x1d,0x60,0x16,0xba,0x64,0x5,0x8e,0x93,0x2d,0x47,0x62,0xb0,0x20,0x11,0x6d,0x9c, + 0xbd,0x2a,0x26,0x84,0xfc,0x41,0x39,0x3,0x9b,0xd,0xe9,0x49,0x24,0x81,0x39,0x22, + 0x8a,0x8,0xc3,0xd1,0x4f,0xa6,0xa6,0x85,0xa3,0x64,0x81,0x4f,0x4e,0x3c,0x44,0x3d, + 0xc4,0x74,0x27,0xa4,0xa4,0xee,0x89,0xfe,0x94,0x90,0xec,0x64,0x93,0x41,0xf6,0xd5, + 0x76,0x47,0xa3,0x4b,0xae,0x1,0xad,0xa9,0xca,0x97,0x8,0x5,0x4a,0xc,0xf3,0x82, + 0xf9,0x41,0x2d,0x17,0x7a,0x29,0xe7,0x1e,0xd9,0x3f,0xb3,0x50,0xf5,0xb6,0xd7,0x30, + 0x5b,0x6f,0xc6,0x82,0x41,0xed,0xa,0x95,0x88,0x90,0xc9,0x80,0xd7,0x15,0xf,0xe4, + 0xa6,0xdc,0xb7,0xc9,0xa1,0x29,0x3b,0xb4,0xb5,0x7e,0x7,0x8b,0xc6,0xba,0xc4,0xc, + 0x5f,0xcb,0x35,0x7a,0xa6,0x3e,0xb7,0x8f,0xad,0x8a,0x5c,0xe8,0x80,0xdc,0xd4,0xa7, + 0x72,0x65,0xd,0x64,0x33,0x38,0xfb,0x15,0x68,0x63,0xd0,0x1b,0xda,0x82,0x43,0x68, + 0x2,0x2d,0x7a,0xdf,0x95,0xe,0x91,0x46,0xb5,0x45,0xab,0x3e,0x3,0x6a,0x46,0xcf, + 0xdc,0x1a,0xc3,0x37,0x2,0xa7,0x1,0x60,0xca,0xb4,0x8d,0xac,0x81,0xf0,0x4e,0xab, + 0xd7,0x3c,0xc2,0x1c,0xae,0xa8,0x9a,0x93,0x80,0x94,0xa8,0x83,0xcd,0xaa,0x57,0x10, + 0x8d,0x68,0x55,0x52,0x19,0x41,0xa8,0x56,0x0,0x4b,0x6e,0xb0,0x26,0x42,0x4d,0x7b, + 0x62,0xa4,0x6c,0x77,0xa6,0xea,0x9a,0xb,0x5e,0x2d,0x2,0x27,0xe3,0xa1,0xe,0xa9, + 0xbf,0x21,0x23,0xc3,0xeb,0xc7,0x80,0xd6,0x5a,0xec,0xb,0xa6,0x2c,0xd6,0x3c,0xef, + 0x8d,0xfe,0x1d,0x5f,0x7f,0x77,0x79,0x4b,0x66,0xd2,0x31,0xba,0xff,0xf2,0x9a,0x44, + 0x3c,0x4e,0x7,0x1b,0xbf,0x82,0x53,0xab,0xfc,0xd9,0xb8,0x42,0x7e,0x64,0xb1,0x3c, + 0xf9,0x68,0x63,0x8b,0x27,0x5d,0x88,0xc8,0x2a,0x27,0x61,0x1c,0xad,0x8c,0x30,0x40, + 0x93,0xd3,0x7d,0x22,0x87,0xaf,0x1c,0xa2,0x35,0xb4,0x52,0x72,0xdc,0x80,0x49,0x12, + 0xae,0x1c,0x4d,0xe2,0x30,0xa9,0x82,0xc5,0x6,0x57,0x16,0x76,0xad,0xa0,0xbb,0x7b, + 0xf0,0x56,0x8c,0xc7,0x73,0x69,0x83,0x37,0x60,0xfc,0x3b,0x5a,0xa1,0xe4,0xed,0x41, + 0x9,0x4a,0xda,0x8a,0x88,0x11,0x30,0x94,0x9f,0x85,0x8c,0xfb,0xd8,0xa6,0x2a,0xda, + 0xf2,0xc6,0xb0,0x94,0x58,0x99,0x5a,0x67,0xab,0xa2,0x9d,0xa5,0xd1,0x66,0x92,0xa5, + 0xd8,0xb7,0x5f,0x16,0x53,0xcf,0x3c,0x3a,0x5d,0xcb,0x6c,0x5,0x48,0x45,0x5b,0x64, + 0x2a,0x83,0xe5,0xfb,0x6e,0x1f,0x4f,0xc3,0x3c,0xbf,0x8a,0xcd,0xd4,0xe6,0x8,0xa4, + 0x2e,0x52,0x7c,0x64,0xe8,0xdb,0xe4,0xba,0x82,0xd3,0xcc,0xc,0x35,0x65,0xd3,0x5d, + 0xda,0xf5,0xd6,0xd7,0x3f,0x5c,0x5f,0x17,0x77,0x15,0x78,0xad,0x7,0xe7,0x54,0x4, + 0x4,0x3f,0x7,0x6d,0x4,0x56,0x89,0x27,0x28,0x18,0xd3,0xf4,0x21,0x86,0x30,0x99, + 0xcd,0x71,0x10,0x33,0xc7,0x8d,0x57,0x25,0xa2,0xa4,0x37,0x48,0xc6,0x23,0x63,0xe, + 0x89,0xa2,0x4,0x73,0x13,0xc1,0xc,0x6b,0xd5,0x15,0x64,0x1,0xeb,0x98,0x71,0x5, + 0xa9,0x2c,0x72,0x69,0x44,0xb5,0xa7,0x5c,0x44,0xe3,0x89,0xdd,0x9c,0x3,0x22,0xd8, + 0xef,0xa5,0x50,0xa,0x8d,0x64,0xc4,0x60,0x2f,0x96,0x41,0x9c,0xc3,0x81,0x1e,0xc, + 0x65,0x9f,0x51,0xac,0xca,0x3b,0xee,0x7c,0xbb,0x10,0x57,0xc0,0xdc,0x17,0xf5,0xd9, + 0x58,0x38,0x94,0xbc,0x44,0x12,0xd8,0xb3,0xb4,0x81,0x1d,0xf,0xfd,0xa8,0x10,0x56, + 0xd8,0xec,0x57,0x44,0xa5,0x9a,0xf3,0xc4,0x68,0x90,0xf0,0xea,0x6d,0x23,0xe0,0xd4, + 0x69,0xa6,0x1a,0x18,0x49,0xfb,0x8e,0x2e,0x5d,0x4e,0xdc,0xc8,0xd7,0x1a,0xa,0x15, + 0x3d,0x44,0x56,0x17,0xe1,0x41,0x10,0x3b,0x9b,0x8,0xc,0x7a,0xdf,0x94,0x3,0x21, + 0x94,0xfd,0xde,0xb7,0xf9,0xfb,0x3,0xe1,0xd0,0x98,0xb5,0x3,0xfd,0x66,0x9c,0xbc, + 0x26,0x6b,0x18,0x3c,0x36,0xb6,0x2f,0x52,0xd5,0x4a,0x27,0x17,0x84,0xa5,0xbd,0x18, + 0xeb,0x94,0xbd,0x9a,0x82,0x51,0x31,0xbf,0xbe,0x13,0xcf,0x1a,0x7a,0x4,0xce,0x44, + 0x77,0xf2,0xe3,0xa0,0x6b,0xa1,0x67,0x4c,0x26,0xbe,0x39,0x97,0xae,0xbf,0xb,0x74, + 0x32,0x2d,0x90,0x35,0x52,0x67,0xe3,0xc9,0xc2,0x44,0xf9,0x14,0x9,0x64,0xde,0x1d, + 0xad,0x8d,0x70,0x28,0x1a,0x23,0x79,0x52,0xce,0x2,0x1a,0xff,0xc5,0x99,0xe3,0x29, + 0x7b,0xb2,0xcf,0xb7,0xc3,0x24,0x7,0x76,0x92,0x80,0x89,0xc3,0x6b,0x4b,0x18,0x73, + 0x67,0x64,0x5d,0xd5,0xd5,0xce,0x5,0x8,0xc7,0x8f,0x75,0x6d,0x76,0x3d,0xc6,0x7a, + 0xc0,0xda,0xb6,0x1c,0xaa,0x69,0xd8,0x3c,0x8,0x36,0xaa,0xc6,0x98,0x62,0x1d,0x18, + 0xf3,0x8b,0x85,0x4e,0x8f,0x17,0x26,0x1f,0x0,0xda,0xb7,0x7c,0xc9,0x70,0x8,0xa1, + 0x6e,0x38,0x4e,0x7c,0x12,0x25,0x34,0x19,0xca,0x49,0x48,0x30,0xcd,0xf,0x84,0x10, + 0xe,0x9d,0x48,0x19,0x49,0xc4,0x42,0x92,0xf1,0xf6,0x47,0x7f,0xfc,0x82,0x2,0xdd, + 0xd2,0x8c,0xec,0x5b,0x2a,0x1,0x1c,0xa3,0xcc,0x64,0x64,0xc8,0x4d,0x2,0xd2,0xc5, + 0x5d,0x28,0x44,0x8a,0xa,0xc8,0x7d,0x66,0xc,0x44,0xa6,0x9c,0xa4,0x88,0xe2,0x41, + 0xe,0xf4,0x95,0x1e,0xdf,0xd4,0xaf,0x83,0xdc,0x3,0x51,0x5c,0x1a,0xe,0xb9,0xfe, + 0x7e,0x47,0xb8,0x66,0x25,0xa6,0x49,0x2e,0x34,0xfa,0x47,0x83,0xb4,0x64,0x4e,0x1a, + 0x36,0x28,0x36,0xc9,0x45,0x89,0xe8,0x4d,0xdf,0x27,0xf0,0x20,0x53,0xaa,0xb3,0x55, + 0x22,0x7c,0xad,0x24,0x2a,0xdf,0xdd,0x6e,0x57,0x8e,0xed,0xf1,0x86,0xa0,0xb4,0xb, + 0x2b,0x3,0xd1,0x30,0xbe,0x42,0x90,0xcc,0x10,0xbf,0x83,0xfa,0xb9,0x41,0x52,0x8c, + 0x9e,0x57,0xb6,0x9,0xb4,0x1,0xd5,0x3e,0xcb,0x68,0x51,0x4e,0x9a,0xe2,0x20,0x7f, + 0xd0,0x24,0x6b,0x5f,0x11,0x20,0xa7,0x85,0xf3,0x6a,0x79,0x4a,0xc5,0x1a,0xa9,0x94, + 0x71,0x3c,0xa6,0x7f,0x4f,0x45,0x67,0xe5,0xb7,0xf3,0xb8,0x37,0x7c,0x2f,0x8d,0x5b, + 0x5c,0x5b,0x29,0xc1,0xf1,0x61,0x20,0x12,0xac,0xfa,0x4e,0x7b,0xb0,0x9f,0x37,0xcf, + 0xda,0xf8,0xe,0x5b,0xd7,0x5a,0x59,0xe,0xdd,0x4e,0x17,0xc1,0xe9,0xbd,0xdc,0x30, + 0x2e,0x6,0xe1,0xc8,0xfc,0x67,0xb6,0x3d,0x3a,0xa1,0x89,0x4e,0xc6,0x4b,0x4e,0x84, + 0x7f,0x2e,0xa2,0x62,0x8f,0x33,0x72,0xbd,0x86,0x86,0xe,0x3a,0xfd,0x0,0xab,0x3d, + 0x4a,0x42,0xb8,0x35,0x73,0x2b,0xc6,0xc9,0x94,0x8c,0x1a,0x9a,0x83,0x5c,0x3,0x82, + 0xc4,0x2a,0x82,0x40,0x15,0x8a,0xbc,0xb2,0xaf,0xc,0x84,0xa,0xed,0x8b,0x87,0x6f, + 0x40,0x8d,0x1d,0x60,0x9b,0x23,0xb7,0xb3,0x59,0xd1,0x4f,0x8d,0x29,0x86,0x2b,0x6, + 0x57,0x8d,0x3,0xb8,0x52,0x35,0x2f,0xc,0xf8,0x9,0x31,0xb5,0xcc,0x26,0xc5,0xda, + 0x69,0x75,0xbd,0x52,0xb3,0xad,0x57,0xa8,0xf2,0x8b,0x48,0x6,0xbc,0xfd,0x7,0x3f, + 0xfe,0xa6,0x56,0xee,0x69,0xb7,0x1c,0x37,0x63,0xea,0xbf,0x1f,0x36,0xec,0xab,0x20, + 0x30,0x9d,0x18,0xa7,0x83,0x3b,0x21,0xb3,0x97,0x92,0xc9,0x18,0xc6,0xe1,0x7c,0x2e, + 0x7c,0xd2,0x29,0x5e,0x7,0xfc,0x44,0x73,0x6c,0x52,0xa4,0xd3,0x63,0xed,0xac,0x5b, + 0x3b,0x6c,0x39,0x11,0x55,0xe6,0x80,0xd2,0x55,0xd,0x86,0xb9,0x7a,0x9,0xb8,0x90, + 0x76,0x82,0x77,0x8e,0xa4,0x27,0x5d,0x15,0xaf,0x1b,0x8,0x1e,0xa0,0x6f,0xea,0xef, + 0xf4,0x30,0x7b,0x90,0xd1,0x23,0xa2,0x82,0xcf,0xcb,0xc3,0x7b,0x12,0x1b,0xf1,0x20, + 0xe6,0xa3,0x5f,0xd3,0xb4,0xa3,0xea,0x16,0x9d,0x96,0x6d,0x45,0xce,0xb4,0xee,0xdd, + 0x77,0x58,0xee,0xaa,0x55,0x8d,0x43,0x3e,0x35,0xd9,0x4,0x14,0xcf,0x21,0x7c,0x56, + 0xfe,0xf,0x32,0x4c,0x6,0x94,0xe4,0xa4,0x60,0x68,0x69,0xa6,0x4,0x82,0x36,0x6b, + 0x2c,0xc7,0xde,0xb0,0x39,0xcb,0x55,0xb7,0xfc,0x7c,0xbb,0xfb,0xa2,0x2c,0x13,0x78, + 0x49,0x89,0x76,0xa3,0x2b,0x3d,0x87,0xf2,0x13,0x64,0x87,0xad,0x44,0x63,0xc1,0x2b, + 0xfb,0x99,0xdd,0x8a,0xe1,0xd1,0x7b,0xb0,0xe0,0xe9,0xf,0x74,0x4f,0xb9,0x30,0xa4, + 0x46,0xe5,0x78,0xa6,0xac,0xb7,0xb5,0xbd,0x28,0xd0,0xaf,0xee,0x37,0x6e,0xf8,0x96, + 0x1b,0x89,0xc3,0x14,0xf8,0xd6,0xe7,0xef,0x49,0x8b,0x36,0xf,0x30,0x9c,0xda,0x34, + 0x5c,0x70,0x6e,0x25,0xb1,0x8e,0x4e,0x18,0x7b,0x42,0x4,0x51,0x88,0x51,0x66,0x99, + 0xe9,0x4c,0x7c,0x6d,0x4b,0x2b,0x1c,0x8f,0x81,0x20,0x3b,0x5f,0x83,0x4f,0x3,0x9c, + 0x92,0xd3,0x97,0x25,0x56,0xec,0xd7,0x31,0xb8,0x45,0x4e,0x96,0x42,0x80,0x53,0xe1, + 0x34,0xa6,0xab,0xc3,0x6b,0x79,0x68,0x2c,0xb4,0x50,0x85,0x1e,0x7a,0x5a,0xcb,0x8b, + 0xdf,0x4a,0x5c,0x4f,0x1e,0x28,0xe8,0x8,0x13,0x63,0x7e,0x7,0x3e,0xa2,0xf1,0xe6, + 0x30,0x8,0x5b,0x6b,0x6b,0xda,0x18,0x27,0xe5,0x33,0x90,0xc2,0x4d,0x80,0x8d,0x8, + 0xcd,0xa3,0x5c,0x91,0xe2,0x2a,0xf4,0x1c,0xf2,0x3f,0xaa,0xbc,0x65,0x84,0xd,0x1d, + 0xa1,0xa3,0xf7,0x2,0x16,0x73,0xd2,0xe6,0x1c,0x55,0x96,0xb6,0xf7,0x92,0x58,0xd5, + 0xc9,0x1d,0x56,0x15,0xd,0x83,0x7d,0xc1,0xb8,0xe6,0xc,0x92,0x5,0xbb,0x96,0x6, + 0xd2,0xd7,0x28,0xc6,0x87,0xa1,0xe2,0x46,0x1b,0x75,0x53,0x82,0x45,0x9,0x61,0xe2, + 0x9,0xc0,0x5d,0xe9,0x4a,0x47,0xdc,0xe4,0xb,0xaf,0x53,0x0,0xc3,0x8d,0x3c,0x43, + 0x2,0x2,0xc6,0x25,0x3f,0x4d,0x19,0x24,0x44,0x3c,0x12,0xc2,0xa6,0x65,0x82,0x60, + 0xda,0xde,0x3d,0x62,0x65,0xfb,0xd7,0x90,0x79,0x8f,0x67,0x24,0x4b,0xc6,0x22,0x69, + 0xc5,0xfb,0x94,0x3f,0x7f,0xbd,0xf6,0x6a,0xc1,0xb3,0x8c,0x4,0xb9,0xab,0xc4,0x35, + 0xfa,0xb5,0x12,0xbf,0x1d,0x0,0x21,0xfa,0xf3,0xa8,0x1c,0xcf,0x12,0x16,0x30,0x77, + 0xe0,0x64,0x54,0x6b,0x63,0x79,0x4e,0x2f,0x2f,0xa0,0xa4,0x99,0xf5,0x76,0x6e,0xe2, + 0xe6,0x82,0x2e,0x37,0x3,0x77,0x5f,0x9,0x65,0x86,0x79,0x5f,0xcf,0x82,0x96,0xe9, + 0xdc,0x9a,0x45,0x14,0x8a,0xdf,0xb5,0x82,0x0,0x21,0x33,0xf0,0x43,0x7f,0x52,0x67, + 0xeb,0xb3,0x52,0x6d,0x0,0xb0,0x33,0xf2,0x19,0xa2,0x41,0xb4,0x2e,0x4,0x8d,0x78, + 0xb6,0x20,0x69,0x38,0xf,0xc5,0x97,0x26,0x62,0xb9,0x25,0xf9,0xf0,0x49,0x50,0x2, + 0xf5,0x50,0xc9,0x50,0x54,0xab,0xc5,0x90,0xc4,0xb9,0xa,0x7e,0x4f,0xae,0x5d,0x9c, + 0x61,0xf6,0xad,0x9a,0xf6,0xa,0xbf,0x19,0xcf,0xfe,0x5d,0xe5,0xea,0xb1,0x2d,0x1, + 0x9e,0xf,0x3f,0x2,0xf3,0xfe,0x63,0xc0,0x39,0x49,0xa,0xed,0xc5,0xba,0x4f,0x97, + 0x74,0x83,0x2f,0x1f,0xb1,0xd5,0x64,0x6b,0x6f,0xa8,0x43,0xa9,0x80,0x4d,0x32,0x76, + 0xc5,0xe1,0x41,0x81,0x14,0x6c,0x1c,0xc,0xd4,0x94,0xf1,0x96,0x17,0x85,0x44,0x48, + 0xea,0xa3,0x27,0xc8,0xd1,0x7a,0xb1,0x35,0xab,0xd3,0x24,0xaf,0xf8,0x29,0x2d,0xd7, + 0x99,0xd4,0x38,0x93,0x66,0xf,0x97,0x69,0x8e,0x62,0xf2,0xad,0x5,0xa8,0x26,0xaa, + 0x4f,0xbf,0x19,0xa6,0xec,0x7,0xa3,0xcc,0xfb,0x7b,0xbb,0x7a,0x9b,0x6d,0xc2,0x4b, + 0x63,0x37,0x86,0xaa,0x87,0x36,0x33,0xa9,0x1,0x44,0x49,0x79,0x56,0x33,0x5c,0x25, + 0x73,0x91,0xae,0x9c,0x35,0x8a,0xa8,0xa2,0x7,0xb9,0x7d,0xb,0x30,0xc0,0x89,0x30, + 0xb2,0xa0,0x2e,0x5e,0x4c,0x44,0xbf,0x3,0x68,0xa0,0xcc,0x78,0x63,0xc9,0x37,0xf7, + 0xa4,0xa,0xf7,0x20,0x8c,0xb0,0xcb,0xfe,0x7d,0xd7,0xaa,0x52,0xd0,0x31,0x47,0xc9, + 0x77,0x30,0xf2,0x8f,0x8a,0x97,0xcc,0xd5,0xb2,0xa3,0xea,0x8c,0xba,0x38,0xf7,0x90, + 0xac,0x13,0x6a,0x52,0xa7,0x1,0x20,0xba,0x2f,0xa0,0x12,0xc1,0x94,0x64,0x84,0x40, + 0x6,0x7a,0x9b,0x46,0x67,0x98,0xed,0xf3,0xe1,0xdd,0xbb,0xfd,0x98,0x18,0x73,0xf7, + 0xcf,0xc1,0x47,0xa9,0xfc,0x62,0x56,0xdc,0x88,0x33,0x8e,0x49,0x52,0x11,0x90,0x65, + 0xb0,0x51,0x9d,0xb5,0xb,0x84,0xa4,0x8d,0x54,0x75,0x77,0x20,0x7d,0x82,0x28,0x92, + 0xb7,0x12,0x7,0x96,0x56,0xad,0x36,0xa1,0x10,0xad,0x2e,0xa4,0x96,0xb8,0x8d,0x9a, + 0x89,0xbc,0x24,0xd8,0x89,0x99,0xc3,0x4c,0xf9,0xea,0xf7,0x56,0x8c,0x1c,0x21,0xd2, + 0x33,0xe3,0xc9,0x54,0x23,0x4a,0x1e,0x15,0x95,0xf5,0x3f,0x17,0x5a,0x9,0x8a,0xc6, + 0x3a,0xae,0xc1,0xd7,0x46,0x45,0x58,0xf8,0xb2,0x89,0xd1,0x44,0x22,0xd7,0x5a,0xbf, + 0x5a,0x3d,0xfa,0x70,0x29,0x16,0xd0,0x4a,0x5a,0x67,0x5a,0xe1,0x5,0x88,0x6e,0x41, + 0x7,0xff,0x1e,0x14,0xa1,0xc6,0x31,0xef,0x97,0x83,0xce,0x3c,0x9c,0xf,0x72,0xe, + 0x65,0x5b,0x12,0x81,0x8b,0x38,0x2b,0x7e,0x67,0xb4,0x68,0xb2,0xdd,0xb5,0x83,0x6, + 0x43,0x1c,0xb3,0xe0,0xb0,0xf9,0x42,0x27,0x92,0xfa,0x90,0xb0,0x90,0x13,0x10,0xd1, + 0xa4,0xae,0x87,0x5e,0xd0,0xd7,0x0,0xa8,0x24,0x26,0x31,0x11,0x61,0x9,0x97,0x9c, + 0x6d,0x29,0x47,0x3d,0x49,0x79,0x37,0x8b,0xb6,0xea,0xd7,0x8b,0x3,0x54,0x9d,0x23, + 0x81,0x1a,0x7,0xa0,0xbd,0x7e,0x1c,0x6a,0xfe,0x3a,0x70,0x8b,0xf2,0x3c,0xf,0xf2, + 0x40,0xf4,0xff,0x39,0x4c,0x11,0xbc,0x61,0x60,0x1d,0xd2,0x92,0x4,0x67,0xef,0x29, + 0x57,0x88,0xec,0xc,0xcb,0x6a,0x15,0x1c,0x66,0xd4,0xa1,0x69,0x3,0xef,0x83,0xcb, + 0x7,0xce,0xd0,0x21,0x98,0x16,0x48,0x30,0x3b,0xb6,0xae,0xca,0x64,0x68,0x92,0xb0, + 0x69,0x0,0x6e,0xe9,0x7a,0xdd,0xa3,0xca,0x76,0xd7,0x8e,0xe7,0xa9,0xe1,0x71,0x50, + 0x2b,0xb1,0x44,0x40,0x36,0x1e,0x38,0xa8,0xbe,0x49,0x65,0x54,0xb5,0x67,0x57,0xd7, + 0x31,0xd5,0xa,0xe0,0x80,0x7a,0xa5,0x61,0xe0,0x55,0x1,0x6f,0x2,0xc,0x17,0xf1, + 0x3,0x2d,0xcd,0xf6,0x43,0xb1,0xa2,0x8f,0x6e,0x7,0xc3,0x38,0x1b,0xc5,0x78,0x7e, + 0x49,0x33,0x90,0xea,0x56,0x9e,0x1b,0x95,0xdd,0x1d,0x13,0x1,0x3c,0x8,0x74,0x70, + 0x40,0x31,0x22,0x17,0xa,0x9c,0x44,0xc6,0x72,0x34,0x66,0x88,0xdc,0x67,0x8e,0xa2, + 0x98,0xd8,0x7,0xe3,0xbb,0x82,0xe4,0xd9,0x50,0x85,0xf6,0x84,0xe6,0xde,0x2e,0xe6, + 0xc6,0xb8,0xbf,0xe3,0x8a,0xe4,0xe,0xd7,0x42,0xa0,0x5c,0xa5,0x68,0x27,0xb6,0x36, + 0x90,0x73,0x3b,0x54,0xa9,0xe6,0xc0,0x5a,0xd3,0x96,0xe4,0x63,0xe8,0xcb,0x9d,0x6c, + 0x4d,0x65,0xe6,0x5e,0x53,0x6b,0xfa,0xc0,0x91,0xdf,0xd,0x86,0x89,0x4a,0x2d,0x78, + 0xbe,0x5b,0x5c,0x72,0xa8,0x92,0x44,0xc3,0x7a,0xb2,0x74,0x5e,0x9,0x36,0xf6,0xe8, + 0x6b,0x1e,0xcc,0x94,0x24,0x49,0xd0,0x24,0xe5,0xc5,0xac,0x3d,0xa8,0x7,0xb2,0xa0, + 0x8f,0x9e,0x9,0xc,0xcf,0x2d,0x78,0x43,0x50,0xe3,0x23,0x1c,0x90,0xc8,0x74,0x8f, + 0x93,0xc3,0xdc,0x5,0xb6,0xd8,0x25,0xa6,0x83,0xaf,0xb1,0x10,0x4d,0x43,0x54,0xfd, + 0x3c,0xb0,0xfb,0xda,0x8c,0xa9,0x44,0x28,0x26,0x47,0xfb,0x4e,0xcd,0xe6,0xec,0xa9, + 0x73,0xeb,0xbc,0x67,0x31,0x93,0x86,0x7a,0xad,0x20,0x50,0x2e,0x40,0x4b,0x8,0xca, + 0x88,0xc5,0x1c,0xfa,0x56,0xc8,0x39,0xa2,0x54,0x8d,0x26,0xa2,0x85,0xb7,0xdb,0x44, + 0x35,0x81,0xed,0x99,0x61,0x93,0xdd,0x17,0x22,0xc8,0xdf,0x20,0x6d,0xfa,0x29,0x3b, + 0xb3,0x1b,0xd5,0x73,0x9f,0x89,0xdd,0x46,0x48,0x31,0x99,0x40,0xbb,0xd0,0x8f,0x8c, + 0xb7,0x84,0xe1,0xf9,0x40,0xe7,0x32,0xce,0x60,0x87,0xef,0x22,0x2,0x5,0xc,0x4c, + 0x9f,0x27,0x84,0x11,0x99,0x6a,0x43,0x70,0x4f,0xff,0x8b,0xae,0x28,0xb7,0x42,0x25, + 0x10,0x10,0x29,0x77,0x65,0x9c,0x1,0x6b,0xcd,0x36,0xef,0x31,0xb2,0xd2,0xb9,0x71, + 0xba,0x42,0x1,0x74,0xa4,0xed,0x79,0xad,0x11,0x2c,0x4a,0x86,0xfa,0xa7,0x81,0xef, + 0x1a,0x7d,0xb0,0x2d,0xff,0x95,0x51,0x35,0x37,0xf4,0x68,0x9,0xf0,0x8,0x9a,0xbd, + 0x1a,0xc1,0x40,0x28,0x49,0x9d,0xea,0x8e,0x1,0xf8,0x33,0x3b,0x3e,0xe,0x63,0x25, + 0x39,0x86,0xbb,0x92,0x38,0xf4,0xcf,0xb7,0x19,0xe3,0x81,0x54,0x36,0xd5,0x44,0x93, + 0x9c,0x4a,0xca,0x2c,0x3b,0xbc,0x76,0xed,0xc3,0x9e,0x9b,0x12,0xbf,0xfa,0x81,0x3c, + 0x20,0x59,0xf4,0x8d,0x79,0x64,0x49,0x8d,0x55,0x1a,0x4c,0xff,0xc0,0x61,0xb8,0xcb, + 0x36,0x13,0x52,0xc1,0x8c,0xa,0x21,0xf,0x55,0xd8,0xc0,0x89,0x43,0xea,0x9f,0xba, + 0x16,0x6a,0xf7,0x2e,0x28,0x3d,0x88,0x12,0x11,0xa0,0x33,0xd1,0x95,0x99,0x46,0xd8, + 0x8c,0x72,0x22,0x1c,0xfe,0x5d,0x2,0x93,0x13,0x41,0x56,0x42,0x48,0xb4,0xb0,0xb3, + 0xe1,0x2c,0xf9,0x12,0xf2,0xd6,0xb8,0x56,0x79,0x10,0xd,0x19,0x0,0x5d,0x9,0xec, + 0xeb,0x49,0x8,0xcc,0xd3,0xb5,0xe2,0x27,0xc4,0x71,0x54,0x58,0x9,0x68,0x16,0x86, + 0x4e,0xf4,0x8a,0xad,0x46,0xd4,0x2f,0xef,0x61,0xd7,0x52,0xe,0xb5,0x31,0xe,0xec, + 0xe7,0x2e,0x44,0x6d,0xf1,0x76,0x5f,0xfb,0x25,0x90,0xaf,0xb6,0x14,0x5c,0x89,0xad, + 0x5d,0x27,0xb2,0x56,0xaf,0xa6,0x84,0xb9,0xf,0x31,0x57,0xa5,0x74,0x91,0x9d,0x2b, + 0x4c,0x7d,0x26,0x84,0x57,0x2,0x51,0xce,0x63,0x7,0x5a,0x97,0x84,0x43,0x56,0xca, + 0x98,0xa0,0x7,0x32,0x66,0x95,0x1e,0x4a,0x8b,0x92,0x74,0x93,0xa9,0x65,0x79,0x8, + 0xec,0x12,0x98,0xa0,0x45,0x29,0x6,0x7f,0x2b,0xf9,0x5,0xbb,0xd8,0x55,0xb2,0xdf, + 0x89,0x10,0x1,0xb,0xcb,0x29,0x60,0xb5,0xf8,0x20,0x46,0x1a,0x56,0x43,0x27,0x38, + 0x5,0xfc,0x69,0xd5,0xdd,0x5f,0xf5,0x66,0xba,0xca,0x39,0x34,0xcf,0x79,0x8c,0x2d, + 0x9d,0x6d,0x1a,0xd1,0x40,0x7a,0x71,0x65,0xaa,0x67,0x30,0x53,0x90,0xe1,0x58,0xe9, + 0x56,0xe0,0x18,0x82,0x6a,0xa,0x1c,0x62,0x2b,0x77,0x9f,0xfa,0x6c,0xf6,0xbb,0xca, + 0x8d,0x12,0x74,0xf,0xc2,0x16,0xf5,0x10,0x88,0x5a,0x5b,0xfb,0x20,0xc3,0x18,0x55, + 0xaa,0x3b,0xf0,0x74,0x82,0x83,0x1e,0xfa,0x98,0x5,0x78,0x13,0x34,0x13,0x89,0x52, + 0x1d,0xe1,0x53,0x5,0xb4,0x6b,0x5,0x17,0x98,0x8b,0x92,0x9e,0xfb,0xd2,0x8f,0x92, + 0x60,0x94,0xd0,0xf3,0x1e,0x81,0xa3,0x13,0x69,0x8c,0x5b,0x41,0xe3,0x2e,0x94,0xba, + 0x14,0x39,0x7c,0x23,0xd2,0x8d,0xf4,0xbe,0xf4,0x82,0xa7,0xe2,0x73,0x39,0xd4,0xe0, + 0xa,0x27,0xa5,0xb9,0xcf,0xb6,0x2f,0x72,0x97,0x3e,0x79,0x1f,0x12,0xce,0xcc,0xca, + 0xe9,0xc0,0xb8,0x81,0x1a,0xdc,0xc0,0x77,0x79,0xf6,0x7d,0x73,0x6,0xda,0xe1,0xa5, + 0x84,0x83,0x10,0xdf,0x93,0x8e,0xc4,0xb3,0xaf,0xf6,0x6a,0x5b,0x25,0x5f,0x41,0xff, + 0x7c,0x8a,0x76,0xe2,0x64,0xa5,0x44,0xc0,0xc9,0x37,0x5a,0x93,0xe1,0x53,0x7b,0x6e, + 0x32,0xb6,0x29,0x1c,0xb8,0x47,0xd3,0xbe,0x56,0x53,0x99,0xf2,0xea,0x66,0x44,0x5e, + 0xd6,0xdf,0x5f,0xce,0x48,0x80,0x77,0x4,0x1a,0x0,0xad,0x2d,0xaf,0xe7,0xef,0xae, + 0xce,0x54,0xd4,0x60,0x37,0x69,0xbd,0xa8,0x4b,0x97,0x31,0x9e,0xaf,0xec,0xb5,0x9, + 0x5e,0x81,0x13,0x81,0x76,0xae,0xda,0x19,0x21,0x3a,0x95,0x2d,0xd9,0xe,0xcf,0x7d, + 0x76,0xab,0x99,0xe5,0x13,0xd8,0xb2,0x5b,0x92,0xa0,0xfc,0x26,0x41,0xf6,0x22,0x46, + 0xb,0x14,0xc8,0xf5,0xea,0x1c,0xf4,0x22,0xce,0x72,0x22,0x3,0x50,0x66,0xef,0xb3, + 0x1d,0x57,0x71,0x2f,0xcb,0xf5,0xd2,0xf5,0x34,0xe7,0x44,0x32,0x45,0x9b,0x2e,0x50, + 0x65,0x3e,0xaa,0xe7,0x87,0x70,0x41,0x94,0x4,0xc,0x71,0x5e,0x53,0xb5,0x41,0x65, + 0xe3,0x33,0x12,0xc5,0x87,0xd4,0x69,0xfa,0xfe,0xc2,0x4,0xa5,0xb4,0xd1,0x72,0xa, + 0xe6,0x89,0xbd,0x46,0x85,0x11,0x45,0x52,0xa0,0x5c,0xf0,0xd,0x7d,0x86,0xdd,0xc7, + 0xd6,0xaa,0x70,0xfd,0xe1,0xff,0xf0,0xc7,0x27,0x56,0xed,0x79,0x38,0x2c,0x9c,0x68, + 0x62,0xf8,0xe6,0xbb,0xb0,0x17,0x47,0xae,0x37,0x36,0xe3,0xbb,0x13,0x22,0xf0,0x42, + 0xd2,0x52,0x45,0x48,0x64,0xb9,0x91,0x5e,0x49,0x35,0xae,0x28,0x87,0x7e,0x4c,0xd, + 0x92,0xba,0x7,0x96,0xf9,0x44,0xb5,0x6c,0xf0,0x1f,0xdb,0x9f,0x1b,0x84,0xac,0xd5, + 0x54,0x93,0xb9,0xe4,0x50,0x42,0xb3,0x4f,0x12,0x54,0x67,0xaa,0x3a,0xfe,0x39,0xcc, + 0x64,0xa4,0xbf,0x7a,0x6a,0x5a,0x32,0xb5,0xe4,0xb3,0xfa,0x60,0xb2,0x6c,0x24,0x60, + 0xe3,0x88,0x1c,0xb7,0x95,0xc4,0x51,0x6d,0xc1,0xdb,0x5b,0x38,0x8c,0x52,0x4d,0xd7, + 0x72,0xca,0x8c,0x71,0x60,0x13,0x9f,0xd8,0x45,0x29,0xa4,0x75,0xf8,0xfb,0x6f,0x11, + 0x59,0xcf,0x64,0xda,0xb0,0xe1,0x3c,0x7e,0x8e,0xec,0x80,0x64,0xe1,0x67,0xc0,0x1d, + 0xae,0x56,0x3,0x58,0x82,0x89,0x11,0xa6,0x1a,0x4c,0xc9,0xc6,0xf5,0x7d,0xc1,0xc0, + 0x8d,0xd4,0xdf,0x7e,0x59,0x58,0xe6,0x36,0x6d,0x34,0xd5,0xca,0x1f,0x55,0xeb,0x92, + 0x43,0xc0,0xe0,0x83,0x4c,0x7,0x86,0x99,0x4,0x84,0x64,0x73,0x9d,0xd8,0x28,0xf7, + 0xeb,0xe8,0x86,0x47,0xec,0xa,0xed,0xe3,0x59,0x86,0xd3,0x64,0x27,0xcd,0x16,0x74, + 0x1f,0x1b,0xaa,0x12,0x46,0x57,0x5b,0xe3,0xd0,0x9,0xcb,0x9,0x52,0xf4,0xf1,0x20, + 0x52,0x90,0xcb,0x72,0x1,0x15,0x2a,0xfa,0x84,0x3,0xf,0x6b,0x68,0x23,0x32,0xcf, + 0x93,0x10,0x7b,0x62,0x10,0x60,0x3b,0xc9,0x71,0x9e,0x22,0xc6,0x21,0xf0,0x44,0x97, + 0xa0,0x66,0xc5,0xb8,0xf3,0xcc,0xcb,0x8c,0x4f,0x2a,0x39,0x9a,0x23,0x60,0xf3,0x92, + 0xb3,0xc6,0xfa,0x16,0x51,0xbf,0xa5,0x5e,0x59,0x98,0xf1,0x5,0x96,0x5a,0xa1,0x86, + 0x57,0xc5,0xf1,0x3d,0x33,0xbd,0x4e,0xa2,0xe8,0xf5,0x87,0xdf,0x7f,0x1c,0x2e,0x28, + 0xa1,0xd2,0x34,0xc1,0xcd,0xec,0x55,0x88,0xcd,0x3a,0xc,0xc7,0x18,0x7b,0x5,0x3f, + 0x4a,0x9,0x72,0x68,0x86,0x3,0xf3,0x59,0x1d,0x2c,0xdf,0xf1,0xb5,0xaf,0xe,0xf9, + 0xd3,0xa9,0x3b,0x5,0x9c,0x64,0x1d,0x12,0x73,0x30,0x38,0x6c,0x98,0xf1,0x50,0x3f, + 0x64,0x40,0x40,0x7f,0xd,0xcc,0xc0,0x42,0x8e,0x4c,0x6e,0xd6,0xb2,0x6b,0x70,0xe3, + 0x1b,0xc1,0xe6,0xb0,0x82,0xbf,0xb5,0x68,0x59,0x47,0x31,0xb1,0xd3,0x9f,0x7d,0xd7, + 0x80,0x57,0x43,0x78,0xe0,0x8b,0x77,0x4e,0x24,0x13,0xc8,0x61,0xce,0x21,0x74,0xfa, + 0x4c,0x6d,0xf7,0x6e,0xdf,0x63,0x54,0x61,0x5a,0x64,0xe3,0x4c,0x6c,0x85,0xbc,0x2f, + 0x73,0xf7,0x3e,0xa7,0xf6,0x14,0x93,0x4d,0xc,0x45,0x58,0xa2,0x32,0x64,0x3a,0x5d, + 0x73,0x3e,0x35,0x4b,0xdb,0x53,0x65,0x86,0x31,0xa5,0x1a,0xd2,0x79,0x18,0xd3,0x27, + 0x47,0x36,0x54,0xda,0x7f,0xbb,0x55,0x4b,0xa4,0x13,0x64,0x23,0x10,0x50,0x39,0x7, + 0xe5,0x2d,0xb3,0x5d,0xbc,0x44,0x2,0x21,0x9a,0x13,0xde,0x7d,0xa7,0xc9,0x2f,0xb7, + 0xbc,0x79,0x90,0xb3,0x4f,0x83,0xc7,0xdc,0x73,0x7,0xf9,0x6f,0x41,0x98,0x32,0xaf, + 0x55,0x9d,0x84,0xc3,0x61,0x5f,0xd,0x60,0x99,0xf,0x72,0x76,0x5e,0x9,0xea,0xcc, + 0xc7,0x21,0xbe,0x1d,0x8,0x19,0xda,0xe8,0x94,0x2f,0xd2,0xb1,0xbf,0x46,0x9a,0xc, + 0x32,0x29,0x4e,0xc7,0xe6,0x14,0x30,0xc7,0x69,0xd9,0x6f,0xed,0x7a,0xd7,0x24,0xcf, + 0x55,0x3d,0x7f,0x4e,0x68,0x44,0x34,0x79,0x9,0x4e,0xe3,0x41,0x9d,0xec,0x26,0xad, + 0x2b,0x93,0x29,0x86,0x56,0xe5,0xc3,0xdc,0x67,0x9c,0xa3,0x18,0xce,0xc,0x45,0x2b, + 0x19,0xd3,0x48,0x56,0x4c,0x10,0xe3,0xad,0xb1,0x29,0x7f,0xe3,0xaa,0xa9,0xc,0xec, + 0x5c,0x6c,0x59,0x3d,0x58,0xcf,0xd8,0x1a,0x2,0xf2,0x11,0xa9,0xc2,0x93,0xc0,0x4c, + 0xab,0x6,0x51,0xbd,0x4a,0x6c,0x64,0x8a,0xa,0x3b,0xd6,0x25,0x2,0x1e,0xa2,0x15, + 0x87,0x9d,0x31,0x49,0x5b,0x85,0xbb,0x84,0xf6,0xe2,0xa7,0x37,0x8e,0x6c,0xf4,0x3, + 0xc0,0x8d,0xb0,0x62,0xe4,0x60,0x55,0xca,0xb1,0x1f,0x75,0x4c,0xa5,0x3c,0x5c,0x81, + 0x3,0x4b,0x79,0x1e,0x4c,0xde,0x56,0xa2,0x34,0x15,0xa8,0x93,0x6b,0x1b,0xb,0x43, + 0xd6,0xd7,0x96,0x4f,0x93,0x1d,0x9c,0xbc,0xd3,0x2a,0xe5,0x70,0xe3,0xa5,0x5a,0x7d, + 0x8c,0xe4,0x4d,0xba,0x5f,0x40,0xd,0xe4,0xab,0xbd,0xa4,0x28,0x52,0x8b,0x22,0x84, + 0x21,0xff,0x9c,0x63,0x5d,0xb,0x3e,0xd5,0x39,0x64,0x75,0x64,0x9b,0x64,0x80,0x97, + 0x7,0x1,0x17,0x3c,0x69,0x87,0x7,0xbb,0x37,0xc6,0xd6,0xd3,0xf6,0xcd,0xca,0x81, + 0xf1,0xac,0x33,0xd9,0x60,0xf4,0x41,0xa9,0x28,0x92,0x8e,0x76,0xf9,0x38,0xa3,0x92, + 0xae,0xd4,0xf3,0xfb,0x91,0xd7,0xda,0x52,0xa2,0x1b,0xa3,0xeb,0xb3,0xdc,0xa1,0x44, + 0x15,0xa3,0x4b,0xb9,0x6,0x50,0x18,0x82,0x4a,0xb4,0xc5,0x92,0xe3,0x31,0x0,0x49, + 0x6a,0x47,0xdb,0xe6,0x83,0xad,0x1d,0xb5,0xd9,0x7e,0x4c,0x9e,0x8b,0x42,0xa9,0x55, + 0x3d,0x40,0xd,0x1d,0x8,0xc6,0x19,0xdb,0xbb,0x75,0x2,0x95,0x22,0x49,0xcb,0x58, + 0x5c,0x9f,0x32,0xfd,0xfe,0x6a,0xec,0x7e,0x5b,0xc7,0x48,0xea,0x23,0x4f,0xf5,0xd3, + 0x90,0x10,0xc8,0x7e,0xcc,0x63,0xef,0x72,0x12,0x20,0x5a,0xef,0x18,0xd1,0xba,0xa7, + 0x29,0x94,0xad,0x33,0x3c,0x85,0x58,0x20,0x93,0xf,0x78,0xd4,0xd1,0x2,0x4d,0x58, + 0xfc,0x20,0x57,0x89,0x9b,0xb4,0x34,0x36,0xe7,0x62,0x30,0xc1,0x62,0xaf,0x36,0xd3, + 0xfa,0x13,0xf4,0x8a,0x96,0x22,0xf3,0x5d,0x75,0xf0,0x7c,0x21,0x7,0x5e,0x8e,0xac, + 0xa3,0x2a,0x9f,0x87,0xd5,0xf1,0x43,0xa2,0x9d,0xc3,0xe6,0x33,0xac,0xb6,0xd1,0x49, + 0xa4,0x67,0x27,0x7a,0xba,0x2c,0x78,0x23,0x3e,0xf4,0x98,0x16,0x3d,0x56,0xc,0xd9, + 0x60,0x63,0x1e,0x89,0xa6,0xff,0x24,0x21,0xbd,0xd,0xf1,0xd4,0x0,0x2,0x38,0xb0, + 0xfc,0x70,0xec,0x9d,0x35,0x36,0x6c,0xf6,0xe8,0x72,0x13,0x23,0x18,0xc2,0xba,0x51, + 0xc3,0x33,0xfc,0xd8,0x33,0x1c,0x7a,0xda,0xee,0x58,0x5,0x67,0xc9,0x3f,0x32,0xab, + 0x2a,0xad,0x9,0x97,0x46,0x35,0x9,0xca,0xfb,0xef,0x89,0xae,0xf1,0xc3,0x46,0x60, + 0xab,0xc1,0x6c,0xbe,0x5c,0xe6,0x51,0x7b,0x1e,0xc0,0xb1,0x16,0x35,0xdb,0x59,0x95, + 0xc8,0x94,0xfe,0x75,0xf6,0x27,0x77,0xf7,0x7,0xe2,0x43,0x8e,0x25,0x99,0x8b,0x36, + 0xeb,0xed,0xbe,0xd9,0x79,0xff,0xd4,0xc9,0xbb,0x46,0x4d,0x7c,0xb4,0xd7,0x98,0x8a, + 0x95,0xd9,0xd1,0x3f,0x19,0xb1,0x64,0xac,0x40,0x76,0x1,0xef,0xdf,0xf5,0x68,0x0, + 0x20,0xe,0xc,0xc8,0x18,0x61,0x8c,0xb6,0x11,0x41,0xce,0x7b,0x66,0x9f,0x61,0xf7, + 0xb0,0xa0,0x93,0x1b,0xb8,0x93,0x82,0x47,0x46,0xd8,0xe7,0x94,0xb,0x4e,0xae,0x72, + 0x6d,0x67,0x34,0x33,0xa0,0x22,0x96,0x44,0xe8,0xf6,0xff,0x7e,0x24,0x8f,0xd1,0x24, + 0x65,0x81,0x4d,0x36,0x24,0x74,0x44,0xf2,0xb2,0xc9,0x3,0xf3,0x92,0xd7,0x25,0x7b, + 0xb3,0xca,0x9,0x37,0x96,0x0,0x54,0xeb,0x1f,0x5d,0x69,0x56,0xfa,0x75,0x63,0x50, + 0xae,0xc1,0xf3,0xf9,0x40,0xfe,0xda,0x9e,0xe6,0x2a,0x2b,0x8b,0xe2,0x85,0x14,0x56, + 0x9e,0x5c,0x9d,0x25,0xe1,0xcc,0xe0,0x86,0xf9,0xcc,0xa8,0x3e,0x69,0xd4,0xc9,0xa5, + 0xf0,0x7d,0xdf,0x48,0x62,0x92,0x30,0xdb,0x3a,0xdc,0xfe,0x10,0x2a,0x88,0x33,0xb6, + 0x12,0x95,0xdf,0x6,0x55,0xb,0xe4,0xb6,0xbb,0xad,0x2d,0x19,0xdb,0x25,0x7d,0x19, + 0x4a,0xbc,0xfb,0x5a,0x10,0x1a,0x20,0x4a,0xb3,0xd8,0x72,0x9f,0x18,0x1c,0x75,0x38, + 0x9c,0xaf,0xaa,0x1b,0x8e,0x4d,0x6e,0x6d,0x8e,0x3f,0x30,0x59,0xe,0xb4,0xd3,0x15, + 0xdb,0xa4,0x87,0xc2,0x6,0xcf,0x83,0x77,0x55,0xbb,0x71,0x9d,0x56,0x6c,0xb9,0x4c, + 0x31,0x51,0xb3,0xfd,0x66,0x12,0xa0,0x33,0x4,0x51,0xf9,0x2b,0x97,0xff,0x26,0x31, + 0xcd,0xf2,0x9b,0x70,0x2e,0x0,0xdb,0x4d,0xa7,0x4f,0x4,0xb4,0x5d,0xb2,0xf6,0xef, + 0x35,0xc0,0x35,0x91,0x91,0x4d,0xa4,0x47,0xd4,0xe0,0xfb,0x5e,0x7,0x99,0xec,0xbc, + 0x37,0xb4,0x98,0x36,0xed,0xae,0x37,0xb5,0xa2,0xa7,0x9c,0xcc,0x68,0x4e,0xd9,0x9e, + 0x3e,0x3c,0x50,0xaf,0x4a,0x88,0x76,0x7f,0xaa,0x38,0xd8,0xad,0x94,0x4c,0x86,0xa0, + 0x8c,0x8d,0x10,0x6,0xdb,0x25,0x44,0xe3,0x3d,0x64,0xac,0xca,0x6c,0x50,0x59,0x37, + 0x38,0xd,0x4a,0x6e,0x10,0xb2,0xd8,0x73,0xed,0x50,0x42,0x84,0x3c,0x24,0x83,0x19, + 0x2b,0x46,0x31,0xb2,0xfa,0x42,0x90,0x28,0x4a,0x3d,0xc8,0x85,0xf4,0x86,0xac,0xc, + 0x11,0x24,0xa5,0x4d,0xaa,0xd0,0x3,0xca,0x78,0x1,0x5,0x77,0x8a,0xd3,0xdf,0xcb, + 0x20,0x3e,0xa9,0xc7,0x7,0x31,0x33,0xd3,0x87,0xd6,0x37,0xd4,0x6a,0x36,0x5a,0x1, + 0x6a,0x6,0x31,0x8e,0xb0,0xd4,0x25,0x46,0x36,0x87,0xd1,0x94,0xc4,0xe,0x16,0xb9, + 0x6,0x96,0xf0,0x2f,0x74,0xe2,0x71,0xb5,0x12,0x27,0xab,0x3e,0x42,0xda,0x21,0xbb, + 0xec,0x1c,0xf9,0xf3,0x71,0xdb,0xf1,0x9e,0x8c,0xe6,0x58,0xd3,0x86,0x80,0x1,0xce, + 0x55,0x44,0x52,0x49,0x2d,0xeb,0x11,0x56,0x76,0xe0,0xc3,0xb8,0x34,0x59,0xa1,0x8f, + 0x57,0x3d,0xbc,0x90,0xea,0x3a,0xec,0xbe,0x7f,0x14,0x1,0xe1,0xd8,0xe3,0xce,0x8a, + 0x71,0x97,0xc7,0x42,0x5e,0xd5,0xf1,0x36,0x15,0x8b,0x9,0xd7,0x33,0xd7,0xde,0xe6, + 0x82,0x0,0x30,0xa0,0x75,0x4b,0x53,0xfb,0x81,0xe2,0x6d,0x74,0x8e,0x67,0x74,0x8e, + 0x7d,0xbe,0x69,0xb0,0x4a,0x6f,0xbc,0x1a,0xab,0x22,0x39,0xd8,0x89,0x3e,0x8,0xcf, + 0x30,0xb6,0x59,0x13,0x19,0xab,0xa1,0x6c,0x41,0x57,0xa9,0x61,0x21,0x75,0x78,0xa2, + 0xa3,0x9c,0xc0,0x81,0x27,0x37,0x28,0xd3,0x64,0xa0,0x98,0xec,0x3b,0x87,0xae,0xe8, + 0x84,0xab,0xab,0x73,0xa2,0xa1,0x92,0xa,0x71,0xc0,0xc7,0x1f,0xc3,0xff,0xd4,0x91, + 0x46,0x4e,0x53,0x4,0xd5,0xdf,0x33,0x55,0x84,0x74,0xdf,0x81,0xe6,0x26,0xfb,0x8a, + 0x6b,0x13,0xcf,0x3a,0xdb,0x4c,0xad,0xa5,0x8a,0x43,0x47,0x5a,0x99,0xf9,0x2b,0x47, + 0x78,0x50,0xc3,0x9,0x81,0x81,0x7f,0x26,0x61,0xce,0x87,0xe7,0xe6,0x41,0xf7,0x4a, + 0xa1,0xb8,0x5d,0xf6,0x16,0x5b,0xd3,0xcc,0xae,0x34,0xbe,0x62,0x55,0xe1,0xf,0xfd, + 0x7b,0xef,0x3f,0x5e,0x87,0x33,0x1d,0xbe,0xd9,0xf1,0xf5,0x5,0x5b,0x20,0x86,0xfe, + 0x4d,0xe0,0x8d,0x1d,0x4d,0xdf,0xed,0xa8,0x18,0x69,0x79,0x25,0xd1,0x7d,0xe8,0x43, + 0xb5,0xf9,0xc5,0x57,0x1c,0xab,0x98,0x1d,0x33,0xc2,0x4f,0xf0,0xc6,0x12,0x35,0x3a, + 0xc9,0xc1,0x9b,0x2e,0xf2,0x40,0xc4,0x98,0x5b,0xe4,0xdd,0x4d,0x7e,0xfe,0xd1,0x7c, + 0x41,0xa4,0x98,0xb8,0xaf,0xbd,0x47,0x8c,0x80,0xd8,0x27,0xe1,0x48,0xd5,0x98,0x46, + 0x18,0x6,0xbb,0x62,0x31,0x7,0xe2,0x87,0x83,0xf7,0x4d,0xbf,0x5b,0x68,0xda,0x49, + 0xc5,0x4a,0x5,0x1e,0x75,0x14,0xaa,0x14,0x30,0x9,0x2,0x5f,0x3b,0xbf,0x4e,0x8d, + 0xd3,0xe7,0x17,0x24,0xeb,0xbe,0x82,0x83,0x31,0x8a,0xe1,0xe7,0xe7,0x4d,0x7a,0xa9, + 0xa8,0x97,0xb2,0xc9,0x6b,0xbd,0x6a,0x70,0xa3,0x9,0xfd,0xe0,0xbb,0x90,0x18,0x86, + 0x9e,0xdb,0x51,0x65,0xb8,0x62,0x74,0xf3,0x5b,0x2,0xd1,0xa7,0xd6,0xd0,0x91,0xe1, + 0x3a,0xf4,0x56,0x5e,0xe8,0xf7,0x1f,0xbf,0xfb,0xf8,0xfd,0xdf,0xba,0xa1,0x3c,0xd2, + 0x62,0xda,0x4d,0x4b,0x82,0x43,0xd,0xd8,0x7f,0x13,0xfc,0x80,0xb4,0x63,0x6,0x42, + 0xa0,0xed,0x34,0x7e,0x83,0xd5,0x31,0x6b,0x47,0xf2,0xa8,0xd2,0xed,0x4,0xb0,0x4e, + 0x3,0x4b,0xf6,0xc7,0xc4,0xbb,0x38,0xdf,0xf0,0x7e,0xaa,0xcc,0x85,0x50,0x97,0x9b, + 0x9d,0x64,0xb0,0xb3,0x3d,0x3d,0x8d,0x70,0x29,0xec,0x2f,0x30,0x3f,0xd3,0xf0,0xa3, + 0xd4,0x59,0x96,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x20,0xdb,0xa1,0x3,0x49, + 0xf8,0x95,0x6c,0x73,0x93,0x6c,0x1e,0x7c,0x4,0xe,0x4f,0x4,0x43,0x5f,0x3e,0x11, + 0x20,0x72,0x38,0x15,0xd0,0x65,0x94,0x5f,0x5a,0x31,0xc,0xca,0xae,0xae,0x17,0xd4, + 0x7d,0x31,0x10,0xc6,0xe6,0x15,0x84,0xc7,0x2a,0x84,0xe3,0x24,0x6f,0xfc,0xee,0x51, + 0xb2,0xb2,0x8c,0xf7,0x49,0x93,0xae,0x7d,0xc3,0x9,0x43,0x90,0xdc,0x38,0xca,0xa1, + 0x31,0x13,0x61,0xc0,0xa4,0xd,0x0,0x77,0x5,0x12,0x58,0x68,0x55,0x6a,0xc0,0xb8, + 0x5b,0xa1,0x5f,0x3c,0xf4,0xc1,0xd6,0x3f,0x5f,0xf2,0xf9,0x17,0xda,0x34,0x4e,0xba, + 0x2a,0x3d,0x1a,0x19,0x70,0x50,0xcc,0xc5,0x24,0xa,0x93,0x71,0xce,0x77,0xd8,0xe8, + 0xe9,0x76,0xa4,0xd7,0x23,0x16,0x8c,0xea,0x80,0x86,0x84,0xbe,0x37,0xc9,0x88,0xe2, + 0xd8,0x3,0x74,0x6b,0x52,0xa8,0x7f,0xfd,0x91,0xb4,0x92,0xfa,0x14,0x68,0xb5,0xa6, + 0x8e,0x4f,0x50,0x6e,0xb6,0x3b,0xbf,0xa1,0x19,0x8d,0x5,0x6a,0xbe,0x3d,0x8a,0x50, + 0x1d,0x8a,0x5e,0x4e,0x5c,0xda,0x97,0x63,0x4b,0xc2,0xba,0x76,0x4b,0x58,0x6c,0x22, + 0x60,0xaf,0xb8,0xdf,0x86,0x7e,0xd6,0xc,0x41,0xb6,0xef,0x83,0xc3,0x86,0x66,0x11, + 0x85,0x57,0x4c,0xbd,0x6d,0xc4,0x6c,0xf5,0x34,0xe1,0x4a,0x6c,0x18,0xe1,0x90,0xe8, + 0x23,0x1d,0x10,0x5c,0x43,0xdb,0x14,0xd6,0xbb,0x36,0x2c,0xc7,0x58,0xe7,0x49,0xa4, + 0xc3,0x80,0x67,0xf7,0x7c,0x4b,0xf6,0x89,0x43,0xd6,0xed,0xb6,0xb5,0x72,0xb0,0xda, + 0xeb,0xed,0x75,0xe3,0x16,0x1f,0x2a,0xce,0xdc,0x4b,0xad,0xdf,0xe9,0x37,0x27,0xb, + 0x62,0x6f,0x89,0x64,0xc0,0x4a,0x88,0x5c,0xa5,0x85,0xe7,0xc4,0x82,0x35,0xaf,0x2f, + 0x59,0xe9,0x51,0xc9,0xa3,0x8d,0xd4,0xf9,0xfd,0x42,0xe8,0xa9,0xef,0x91,0x2a,0x74, + 0x89,0x9b,0x2a,0xbb,0xbe,0xc9,0xe3,0xcc,0x85,0x7c,0x32,0x98,0x23,0xd6,0x38,0x9b, + 0xa4,0xb4,0x8c,0xd,0xc2,0x7f,0x9b,0x8e,0x70,0x91,0xc2,0xc7,0x50,0x5f,0xd3,0xe7, + 0xf3,0x4c,0x2a,0xd9,0xe7,0xd1,0xa1,0x2d,0xa2,0x4a,0x9e,0x84,0x57,0xaf,0x40,0x2c, + 0x23,0x2b,0x5c,0x5d,0x1a,0xf8,0xb9,0xc0,0xb4,0xc7,0xf0,0x56,0x5c,0x79,0xeb,0xa, + 0x2e,0x45,0xd0,0x92,0x9b,0xb5,0xec,0x94,0x44,0x2a,0xed,0x4b,0x3a,0x9a,0x9e,0x2d, + 0x9f,0x3c,0x4e,0x98,0x2,0x48,0x36,0x6a,0x9,0xb1,0x1f,0xd6,0xbc,0x74,0x22,0x6a, + 0xbb,0xd3,0xdb,0x5b,0x49,0x46,0xd5,0x21,0x46,0x6e,0x22,0x10,0xaa,0x3a,0xc5,0xa5, + 0xf,0xcc,0xb2,0x41,0x33,0x25,0x82,0x1d,0x91,0xae,0xd8,0xf8,0x2d,0xdb,0x28,0x4c, + 0x72,0x22,0xb3,0xda,0x84,0x7b,0x69,0xc6,0xdb,0x23,0x5b,0x65,0x87,0x97,0xed,0x73, + 0x1f,0xa2,0x51,0x3b,0xe7,0x23,0x5c,0xd3,0x85,0x18,0x9e,0x59,0x6e,0xe6,0x56,0x42, + 0xf8,0xd2,0xb5,0xa4,0x58,0x4,0x53,0x84,0x61,0x5d,0x70,0x3f,0xe9,0x60,0x1a,0xed, + 0xcd,0xd1,0xa5,0xe0,0x3a,0x4e,0x35,0x70,0x1e,0xba,0x64,0xe1,0x55,0xa3,0xed,0x96, + 0xf5,0x21,0x79,0x1e,0x39,0x2e,0x47,0x5e,0xa,0xe2,0xca,0xad,0xf6,0x99,0xeb,0xe1, + 0x5f,0x8e,0x50,0xe4,0xdc,0x4f,0x60,0xde,0x36,0x76,0x85,0x1a,0x44,0x2c,0x42,0x93, + 0x9f,0x23,0xb9,0x63,0xc4,0x8,0xc,0x6b,0x8,0xbd,0xeb,0x4a,0xc7,0xb5,0xc8,0xe8, + 0x2b,0xb8,0x23,0xf4,0xc8,0x37,0x20,0x79,0x83,0x6f,0xf6,0xa8,0x27,0xed,0x75,0x99, + 0x7d,0x16,0x3,0xde,0x84,0x92,0x5,0xa7,0x51,0xb4,0xfa,0x92,0x51,0x95,0xcc,0x3e, + 0xd7,0x82,0x53,0x15,0x11,0x88,0x35,0x97,0x2e,0xfc,0x26,0x9,0x63,0xb0,0x7c,0x8b, + 0x5f,0x64,0x63,0x57,0xa3,0x98,0xb9,0x8c,0x9f,0xa1,0x57,0x4a,0xc3,0x3c,0xf0,0x38, + 0x78,0x42,0x74,0x11,0x16,0xe,0xba,0xe2,0x8a,0xb2,0xc6,0xb5,0x37,0x6f,0xc,0x43, + 0x5e,0x60,0xcf,0x57,0x6b,0xe7,0x4a,0x3,0x1b,0x21,0x6f,0x32,0x2f,0x9c,0x3,0xc4, + 0x4e,0xd,0x70,0xe2,0xc7,0xad,0x5a,0x10,0xc6,0xb9,0xc9,0x59,0xb0,0x34,0x5f,0x46, + 0x97,0x66,0x58,0x7f,0x1e,0xc9,0x7e,0xb9,0x7c,0xf7,0x49,0xa9,0x6e,0x4f,0x68,0xd4, + 0x6a,0x81,0x11,0x1c,0xc0,0x15,0x2c,0x2e,0x81,0xb,0x58,0x25,0xd4,0xce,0x86,0xff, + 0x3b,0xf9,0xfa,0x91,0xd6,0xdd,0xad,0x23,0xd2,0x35,0x1a,0xc,0x57,0x8c,0xc1,0x74, + 0x4d,0x5e,0x74,0x9c,0x1,0x70,0x59,0x63,0xca,0x74,0x50,0xce,0x75,0xf7,0xb1,0x4a, + 0x97,0x4d,0xae,0xaa,0x10,0x3a,0x9b,0x11,0x25,0xe,0x84,0x48,0x8f,0x2d,0x34,0x68, + 0xde,0x9e,0x8c,0x78,0x2e,0x40,0xfd,0xd2,0x55,0xc6,0xdb,0xea,0xf7,0x5a,0x7b,0xfd, + 0xed,0xe9,0x55,0x37,0x46,0x70,0x39,0x44,0x9,0xc3,0xd2,0xb1,0x32,0x86,0x3d,0x3a, + 0x80,0x6c,0x93,0xb4,0x11,0x6b,0x34,0x62,0x42,0x9,0xeb,0x10,0x26,0x19,0x58,0x62, + 0x34,0x91,0x6c,0x6a,0x44,0xbf,0x5,0x15,0x92,0xaa,0xa2,0x4b,0x8b,0x20,0x2e,0xec, + 0x16,0x14,0x1c,0x1e,0x44,0xb2,0x57,0x6b,0x86,0xea,0x92,0x81,0xd8,0xce,0x64,0xed, + 0x25,0x4d,0x26,0x36,0x53,0x34,0x3c,0x64,0xda,0xa7,0x1,0xfe,0x5c,0x48,0x18,0x23, + 0xf1,0xd9,0x76,0xac,0x54,0x70,0xc5,0x2d,0x46,0x37,0x93,0x1d,0x75,0xf6,0x85,0x1d, + 0xf4,0xc3,0xe5,0xa9,0x87,0x3f,0x5d,0xd3,0xc6,0xcf,0x24,0x81,0x35,0xdb,0x99,0x9a, + 0x46,0x36,0xd4,0x54,0x64,0x30,0x29,0x5a,0xc1,0x87,0xc7,0xa6,0x3e,0xaa,0x4f,0x15, + 0xf0,0x80,0x3,0x37,0x11,0x14,0x56,0x68,0x63,0x3b,0x23,0x1d,0xa1,0x40,0x97,0x2c, + 0x2a,0x5a,0xa4,0xd4,0x1e,0xba,0x5c,0xfb,0xe2,0xe,0xa0,0xbb,0xc6,0xad,0xb8,0x90, + 0x6a,0x7f,0x10,0x3f,0x8b,0x3c,0xec,0xbd,0x3d,0x69,0x22,0x32,0x5a,0x12,0x4,0xcc, + 0xa8,0xbf,0x92,0xda,0xe3,0xd0,0x40,0xa,0x91,0x60,0x95,0x60,0xa2,0x86,0x35,0x9d, + 0xf7,0x52,0x96,0xd0,0x3c,0x6a,0x80,0x34,0xd1,0x91,0x79,0x32,0x60,0x39,0x20,0x6a, + 0x97,0x3,0xd2,0xa0,0x61,0x19,0x27,0x5,0x70,0x8b,0xdb,0xae,0x47,0xbe,0xdd,0xd5, + 0x76,0xcf,0xd4,0x5d,0xda,0x74,0xaa,0x63,0xb,0x91,0x68,0xc0,0xd0,0xd6,0x2f,0x2c, + 0x1,0xe6,0x12,0x50,0x29,0x33,0x48,0x42,0x1b,0x7c,0x66,0xb4,0xbf,0xd8,0x64,0x5, + 0x91,0x22,0x46,0xd1,0x4e,0xd0,0xeb,0x31,0xb2,0xe1,0xc3,0x7d,0x40,0x35,0x6e,0x93, + 0x8b,0xb4,0xf7,0x3d,0x3f,0xe2,0x7a,0xe8,0xa5,0x55,0x47,0x0,0xb3,0x5f,0x1c,0xed, + 0xbb,0x76,0x56,0xc8,0x6b,0xe0,0xa2,0x65,0xca,0x58,0xdf,0xe7,0x36,0x43,0x77,0x61, + 0x40,0x9e,0x9c,0xc6,0x63,0x7a,0x29,0x2a,0xef,0xbb,0x44,0xc9,0x96,0x40,0x57,0x15, + 0xa6,0x79,0x5,0x38,0x5f,0xaa,0x77,0x97,0x60,0x53,0x23,0xd9,0x20,0xc1,0xd8,0x26, + 0xe,0xd,0x7c,0x4d,0x16,0xb2,0xd8,0xca,0xcf,0x56,0xc3,0xb1,0x48,0x96,0x2f,0x24, + 0x66,0x1d,0x55,0x85,0x31,0x24,0xd,0x17,0xc0,0xc8,0x56,0xb7,0xf7,0xf2,0xaa,0x67, + 0x30,0x5,0x47,0xf6,0xfa,0x75,0x28,0x22,0xd1,0x20,0xc8,0xb,0xc1,0x98,0x68,0x23, + 0xe2,0xf9,0x1e,0x34,0xd8,0xf,0x6,0x89,0x5,0xb3,0xdd,0x18,0xb3,0xd1,0x69,0x1, + 0x6c,0x81,0xda,0x9f,0x4f,0xa6,0x34,0x26,0x9d,0x88,0xf8,0x11,0x6c,0x2c,0x5e,0x73, + 0xef,0xa9,0x1,0x46,0x5c,0x2c,0xe9,0x9,0x6f,0x75,0x6,0xf1,0xbe,0xe,0x3a,0x53, + 0xba,0x42,0xd,0x4f,0x58,0xf0,0x75,0xc1,0x82,0x39,0xe4,0x10,0x80,0xf5,0x34,0xf0, + 0x1a,0x1e,0x1e,0x60,0x56,0x5a,0x55,0xcb,0x1d,0xc0,0xb4,0xd7,0xaf,0x53,0x7,0x83, + 0x64,0x24,0xf3,0xa9,0xc8,0x4,0x7,0x6,0x8,0xb2,0x21,0xb1,0xba,0x31,0x11,0xd3, + 0x7,0xf0,0x43,0x4,0x37,0xeb,0xdc,0xdd,0x99,0xb4,0xc5,0x73,0xf5,0xc3,0x8d,0x7d, + 0x52,0x5,0x75,0x20,0x42,0xc9,0x88,0x16,0xee,0xcf,0x7b,0x5a,0x2c,0xd,0x8f,0xd2, + 0xe9,0x8,0x81,0xd7,0x86,0x9,0x1b,0x5b,0x82,0x2e,0x80,0x22,0x7,0xe6,0x48,0xc0, + 0x82,0x1d,0xcc,0x5b,0xd4,0x31,0xb4,0xd6,0xa3,0xf0,0xd4,0xa0,0x69,0x2c,0xdc,0x85, + 0x2d,0xb2,0xb6,0x68,0xd8,0xd6,0xbc,0x7f,0xe0,0x4a,0x45,0xfe,0x98,0x89,0x2d,0xf6, + 0xbe,0xc1,0x40,0xe9,0x8b,0x1,0xbf,0xfd,0xdc,0xf0,0x30,0xd6,0x7d,0x4f,0x70,0x75, + 0x4a,0x20,0x55,0xe9,0xe0,0xd9,0x51,0x43,0x3b,0x44,0xdb,0x4f,0xc6,0x2c,0xf7,0xb6, + 0x20,0x93,0x1d,0x6e,0xa4,0xd5,0x4d,0xee,0x61,0x1d,0xce,0xcc,0x80,0x23,0xf6,0xfd, + 0xaf,0xc6,0x58,0x99,0x5c,0xdb,0xf2,0x4,0x58,0x70,0x3a,0x22,0x18,0x23,0xa6,0x7a, + 0xd0,0x21,0xf0,0xa6,0xe9,0xf,0x34,0xa2,0x3c,0xaa,0xb7,0xa8,0x46,0x47,0x39,0x48, + 0xf2,0x85,0x98,0xa6,0x0,0x5a,0x97,0x45,0x91,0x15,0x54,0xc2,0xe4,0xd1,0x2e,0x4a, + 0x8e,0x53,0xc6,0xa9,0xe9,0x78,0xe7,0x25,0x7f,0x75,0xd9,0xfa,0x63,0xb9,0x76,0x7e, + 0xf7,0xad,0x87,0xf5,0x9c,0x31,0x1a,0x6,0xa1,0x51,0x63,0xa1,0xf1,0x32,0x20,0x79, + 0xf3,0x52,0x11,0xc5,0x38,0xa4,0xdf,0x33,0x23,0x6e,0x41,0xf6,0xda,0x5d,0xd1,0xbf, + 0xb9,0x2b,0x9a,0x7,0x5c,0x26,0x23,0x76,0x82,0x1b,0x87,0xc9,0x62,0x2e,0xd8,0xa9, + 0x57,0x71,0xee,0x1b,0x4d,0x39,0xc8,0x52,0xa1,0xaa,0x57,0x51,0xfb,0x20,0xef,0xb2, + 0x88,0xa3,0x1e,0xb1,0xf5,0xc8,0xca,0x60,0xf2,0x5d,0xfc,0xa9,0x82,0xd5,0x26,0x99, + 0x31,0xb4,0xad,0x19,0xfd,0xdc,0x49,0x3d,0x88,0xd1,0x5a,0xa0,0x64,0xfe,0xb,0xe, + 0x33,0x34,0xa2,0xc3,0x98,0x54,0x56,0x7a,0x34,0x81,0x80,0x2e,0x13,0xcb,0xc9,0x25, + 0x48,0xe6,0x4e,0x19,0xae,0x78,0x8e,0xbe,0x75,0xd9,0x5e,0xb4,0xf9,0xcb,0x69,0xbc, + 0x82,0xc3,0xd3,0x57,0xa5,0xbe,0xeb,0x76,0x30,0xb,0xf8,0x75,0x70,0x7e,0x2b,0xb5, + 0x77,0x45,0x54,0x64,0x61,0x7c,0xfc,0x8,0x61,0xa4,0xc0,0x3,0x11,0x55,0x73,0x38, + 0xcb,0xa5,0x81,0xc2,0x32,0x29,0x69,0x7,0xf,0xad,0x62,0xc4,0x0,0x83,0x63,0xc0, + 0xdf,0x81,0x9a,0x9,0x43,0x56,0xd5,0xb0,0xa1,0x2a,0x6c,0x24,0xa8,0x92,0x6a,0xe9, + 0x49,0x26,0x28,0x52,0x99,0x4e,0x38,0x4b,0x7,0xb2,0xb9,0x6d,0xe6,0x22,0x2e,0x50, + 0xb2,0xa0,0x24,0x58,0xbd,0x87,0xdc,0x13,0x4e,0x93,0x32,0x86,0xeb,0xba,0x77,0x80, + 0x51,0xd1,0x83,0x3e,0xb3,0xbd,0x26,0xf0,0x38,0xbf,0x77,0x35,0xd4,0xae,0xcd,0xae, + 0x77,0x59,0xe4,0x70,0xae,0x43,0xd5,0xd1,0x51,0xc0,0x8c,0x7f,0x2a,0x5c,0xc3,0x1c, + 0x39,0x42,0x92,0x26,0x5f,0x99,0xd7,0x78,0xe7,0xa3,0xf9,0x70,0xa3,0xc9,0x27,0x6f, + 0xfb,0x5f,0x97,0x5e,0xae,0x3d,0x99,0x82,0xd4,0xe5,0xf0,0x8a,0x1d,0x8c,0x59,0x6a, + 0x70,0x44,0xf0,0xc0,0xf2,0x56,0x23,0x18,0x88,0xbd,0x1b,0xd0,0x6c,0xc0,0x54,0xd5, + 0xfb,0xd4,0xbf,0x63,0x12,0xe5,0x62,0xcd,0x35,0x69,0x20,0x88,0xdc,0x63,0x7d,0x24, + 0x43,0x31,0x39,0x6f,0xa0,0x73,0x8a,0x50,0x2a,0xb5,0x1c,0x28,0x8e,0xc5,0xec,0x2d, + 0x43,0xdb,0x12,0x15,0x4a,0xa6,0x9a,0xba,0xc0,0xbd,0x11,0x31,0x73,0x43,0x38,0x81, + 0xa8,0xe8,0x3d,0xa1,0x71,0x54,0xe1,0x90,0x7d,0xaf,0x4,0x58,0x60,0x77,0xb5,0xaf, + 0x9e,0xc6,0xee,0x72,0xaf,0xca,0xfe,0xbd,0xdd,0xd6,0x3a,0xf7,0x79,0xf,0xee,0xc3, + 0x64,0x23,0xdd,0xe1,0x92,0x4d,0x3f,0x97,0x44,0x83,0x1a,0x21,0x4d,0x1d,0x37,0x17, + 0x71,0xd8,0x9a,0x1a,0x80,0x2c,0x80,0xfb,0x5c,0x60,0x85,0xb0,0x7,0xe4,0x50,0x25, + 0x11,0x5,0x11,0xcc,0x75,0xad,0x52,0x6a,0x12,0xba,0xd8,0x25,0x70,0x72,0x2f,0xc, + 0x22,0x11,0xee,0x34,0xa2,0x29,0xe9,0xfb,0x44,0x3,0xd1,0x82,0xab,0xfb,0x92,0x3b, + 0xd1,0x41,0x75,0x96,0xc5,0xa8,0x60,0xb2,0x14,0xe7,0x3c,0x9e,0x7f,0x54,0x91,0x95, + 0x79,0x54,0x36,0x49,0x2a,0x76,0x48,0xac,0xfa,0x38,0x65,0xf6,0x77,0xcb,0xd4,0x8b, + 0xe4,0xf0,0x45,0xd5,0x34,0xb4,0xe5,0x3d,0x2c,0x9f,0xfb,0x46,0xf4,0x72,0x1f,0xd1, + 0x17,0xa,0x49,0x2e,0x8d,0x63,0x50,0x65,0x33,0xc3,0xfe,0x3b,0x7a,0x55,0x83,0xb1, + 0x87,0x75,0xa0,0x75,0x43,0x94,0xd1,0x62,0x8f,0x62,0xa,0x3d,0x70,0x21,0xc,0x67, + 0xcc,0xb2,0xd,0x98,0x69,0x58,0x4c,0xf9,0x64,0xd,0x5a,0xa6,0xe,0x5,0x4f,0xb0, + 0x9a,0xb6,0xf5,0xe0,0x9c,0xd6,0x41,0xcf,0x43,0xe8,0x4d,0xa5,0x38,0x84,0x52,0xee, + 0x5a,0xfb,0x97,0xa1,0x4f,0xd9,0x87,0x35,0xf8,0x7a,0xc1,0xbf,0x12,0xc8,0x9e,0x84, + 0x8c,0x11,0x80,0x6,0x76,0xaf,0xda,0xa5,0x52,0x38,0x23,0x30,0xf3,0xa5,0x48,0xee, + 0x64,0x9f,0x75,0x16,0x3e,0xa6,0x1f,0xe4,0xf7,0x47,0xad,0x73,0xad,0xd2,0x4e,0xe5, + 0xc7,0xe8,0x5e,0x22,0xe0,0xeb,0x30,0xc4,0x21,0x5c,0x99,0xcf,0x2,0x1f,0xd3,0xc9, + 0x90,0xad,0xf,0x8b,0xd1,0x14,0xa,0x3d,0xc2,0x4c,0x1c,0x80,0x2c,0xc8,0x6,0xee, + 0x47,0x9f,0xd7,0x7c,0xf1,0x1d,0xc8,0xad,0x2,0x63,0xb8,0xb7,0x28,0xa8,0x7e,0xa, + 0x55,0xd,0x3a,0x9e,0xc5,0xbf,0x6a,0x58,0xad,0x9d,0xc0,0x7a,0x55,0xce,0x11,0x45, + 0x10,0x56,0x5b,0x60,0xf4,0x56,0x6f,0xba,0x8c,0x56,0xd5,0x10,0x90,0x3b,0x18,0xbb, + 0xf2,0xd3,0xab,0xa2,0x16,0xbe,0x36,0x47,0xe6,0xd4,0xe5,0xcc,0x13,0xc7,0x59,0x88, + 0xae,0x73,0xc0,0x3c,0xdb,0xd3,0xa6,0x5b,0xdb,0xde,0x1b,0x19,0xbb,0x18,0x8c,0x3f, + 0x3b,0x1c,0xaa,0x6,0xf1,0x7c,0xb9,0x18,0x43,0x5f,0xd1,0x67,0x44,0x93,0xb9,0xb8, + 0x34,0xa,0x7c,0xe9,0xd6,0x30,0xcf,0xcc,0x1,0x4e,0xd7,0x1e,0xe1,0x12,0xb7,0x28, + 0xc9,0x6a,0x45,0x60,0x62,0x43,0x40,0x9b,0x74,0x2,0xec,0xf1,0xa1,0xa6,0x7e,0x25, + 0xfd,0x1d,0x56,0xef,0xdd,0x2b,0x24,0x4a,0x74,0xa3,0xa,0x20,0x14,0xc6,0x42,0xb8, + 0xa5,0xab,0xb8,0xd5,0xf2,0xc1,0x7e,0x20,0xe8,0x4e,0x8e,0xa,0x8,0xba,0xe4,0x3e, + 0xa8,0x20,0xce,0xc4,0xf2,0xbd,0x1e,0x42,0x8d,0xb3,0xfb,0x61,0x4c,0xe0,0xd0,0x1d, + 0x46,0x76,0xf5,0x26,0x92,0x39,0xda,0x6f,0xf1,0x1e,0xde,0xfd,0xdf,0xab,0x27,0xa7, + 0x14,0xe8,0x13,0x61,0x8,0x64,0xae,0x74,0x3,0x21,0x91,0x91,0xad,0x42,0x1b,0x2, + 0x40,0xeb,0xbf,0x73,0xa0,0x53,0x3,0x8d,0xcb,0xd5,0xb3,0x6d,0xe2,0x28,0x68,0x94, + 0x4c,0xeb,0xe9,0x39,0x9b,0x1d,0xe9,0x90,0x61,0x37,0x7f,0x96,0x90,0x9b,0xf7,0x91, + 0x18,0x78,0x7f,0xda,0xa8,0xa0,0xcf,0x73,0xd5,0xf1,0x34,0xb8,0x43,0x93,0xc0,0xc6, + 0xb4,0xfd,0x53,0xc1,0xd8,0x17,0x68,0x56,0xa6,0x59,0xda,0x50,0x7e,0x8,0x62,0x40, + 0x26,0x2f,0xcc,0xde,0x36,0xba,0x2e,0x30,0x17,0x36,0xa9,0x96,0x5a,0x1b,0xe,0xf6, + 0x9b,0x57,0xf2,0xf,0x2f,0x2,0xba,0x8a,0x58,0x67,0xa9,0xbb,0x88,0xd4,0xd4,0x1b, + 0xd2,0x5d,0x93,0xcc,0x6f,0xc,0xf,0x2b,0xc8,0x9a,0x38,0x8c,0xd5,0x69,0x2,0x30, + 0xb5,0x36,0xe2,0x35,0x40,0x2,0xdc,0x69,0xf1,0xfb,0xba,0xb5,0x85,0x69,0x6c,0x60, + 0xf0,0xf3,0xc6,0x39,0x6e,0xce,0x95,0xe7,0x90,0x2,0x66,0xbb,0x87,0x59,0x74,0xe5, + 0xf7,0x5d,0x5d,0xa4,0xe8,0xe8,0x1,0xfe,0xa2,0x89,0x38,0xb5,0x40,0xb8,0x12,0x45, + 0xd7,0xe9,0x80,0x68,0xa6,0xf9,0x94,0xd2,0x10,0x20,0xa5,0x3d,0x84,0x6c,0x1f,0xb7, + 0xbe,0x96,0xa0,0xab,0x8f,0x0,0x14,0x74,0xd9,0x72,0xf1,0x4d,0x72,0xb9,0x3d,0xe4, + 0xe7,0x75,0x36,0x22,0xc7,0xfe,0xe4,0xc,0x13,0x11,0x34,0xac,0xf6,0x5f,0xcc,0x28, + 0xe8,0xc4,0x4,0x9d,0x98,0xfb,0x66,0x8f,0x80,0xce,0x6a,0x35,0xf2,0x7e,0x18,0x42, + 0x59,0x5,0xac,0xb,0x12,0x1c,0x2,0x35,0x65,0x53,0x8b,0x36,0x36,0x30,0x77,0x1c, + 0x31,0xe8,0x26,0x34,0xa9,0xc3,0x4e,0x50,0x41,0x63,0xba,0xbb,0x9d,0x69,0x83,0x95, + 0x53,0xd4,0x46,0x5,0x76,0x22,0xe8,0xa3,0xbf,0xca,0x49,0x77,0xa5,0x8c,0xca,0xee, + 0x66,0x95,0x9e,0xd9,0xca,0x62,0x67,0x16,0x29,0x4d,0xda,0xf,0x9d,0xa5,0x1f,0xac, + 0xf6,0x56,0xb,0xb2,0xef,0xb3,0x74,0x2b,0xda,0x9f,0x89,0xce,0xf8,0xe4,0x59,0x40, + 0xa1,0x9,0x6d,0x3c,0x50,0x17,0xbb,0x82,0xd7,0x1e,0x57,0x9,0x1,0x96,0xa8,0x4e, + 0x9c,0x68,0x3f,0xa9,0xe1,0x55,0x38,0x55,0xa1,0xc1,0xe2,0x8a,0xb0,0x54,0x3a,0xa9, + 0x4d,0x2d,0x3,0xa9,0x68,0xa8,0x53,0x9,0x3,0xf3,0x75,0x32,0xc0,0xe9,0x9a,0xd7, + 0x52,0x4a,0x47,0x83,0xaf,0x8d,0x3f,0x27,0x43,0x57,0x20,0xc5,0xd1,0x72,0x94,0x5a, + 0x75,0xa4,0x7c,0x52,0x6e,0xa3,0x3e,0x85,0xd2,0x3,0xc6,0xcc,0x99,0x99,0x44,0x50, + 0xba,0x41,0xcb,0x61,0x9e,0xce,0x48,0xaa,0x6c,0x4c,0x14,0xed,0xd3,0x33,0x78,0xf6, + 0x3,0x74,0x30,0x6,0x17,0xe,0x1e,0xd0,0xf3,0x75,0xd6,0x8b,0x64,0x2c,0x3,0xf1, + 0x65,0x62,0x28,0xe0,0xd9,0x74,0x47,0x7,0x2b,0x16,0xf2,0x46,0x91,0x25,0xae,0xc1, + 0xe2,0x13,0x2e,0x22,0xb0,0x48,0x54,0xba,0xa6,0xad,0x7a,0x84,0xb5,0xa4,0xa6,0x21, + 0xe6,0x2c,0xfa,0x7d,0xca,0x13,0x4d,0x2,0xdb,0x74,0x45,0xa2,0x67,0xb7,0x65,0x1c, + 0x7c,0xa8,0xda,0x2,0x5c,0xb8,0xf3,0x36,0x4,0xe4,0x41,0x2f,0xb0,0x1d,0x38,0x4d, + 0x4f,0xfe,0xfe,0x67,0x6d,0x1,0xa2,0x14,0x55,0xf5,0xf,0x7f,0xd8,0xef,0x4b,0x6f, + 0x9e,0x3,0xa2,0xb4,0xfe,0xfe,0xae,0x52,0x5d,0xbb,0xc9,0x3c,0x14,0xf4,0x70,0x52, + 0x62,0xa8,0xb5,0x58,0x9,0x71,0x38,0x53,0xc2,0x1b,0xe3,0x5c,0x1b,0xa,0x3a,0xfd, + 0x73,0xe2,0x80,0xc0,0xfb,0xe7,0x7a,0x1,0xc2,0x66,0x6d,0x44,0x37,0xcd,0xf6,0x82, + 0xf3,0xd1,0xb6,0x50,0xd7,0xb5,0x52,0x52,0x5c,0xd5,0xad,0x52,0x15,0xfa,0xc2,0x41, + 0x60,0x0,0x5e,0xcd,0x23,0xbb,0x5d,0x1c,0x6,0x62,0x8a,0x9b,0xd3,0xcf,0x23,0xc0, + 0xe3,0x26,0x2a,0x9d,0x99,0x74,0x98,0xd9,0xa5,0x85,0x60,0x90,0xd2,0xd7,0x1f,0x5d, + 0x8d,0xaf,0xa0,0x15,0x11,0xea,0x12,0x45,0xc0,0xab,0x59,0x95,0x96,0x42,0x9d,0x2b, + 0xa9,0xb8,0x76,0xc6,0xa5,0x6c,0x66,0xb8,0x4,0xa3,0x67,0x5d,0xe5,0x33,0xdf,0xa8, + 0x3e,0xb3,0x2f,0x7d,0x35,0x4e,0x52,0x82,0xb5,0x25,0x48,0x7d,0xbe,0x96,0xa,0x52, + 0x74,0x32,0x56,0xd,0x15,0x8b,0x54,0x4b,0xc8,0x67,0x9a,0xfc,0x7,0x6d,0xc2,0xc7, + 0xf8,0x4c,0xa9,0x3c,0x65,0x55,0x23,0xe2,0x3d,0x8,0x84,0xcd,0x3c,0x3f,0xec,0x52, + 0x4d,0xfb,0x6d,0x4e,0x18,0xae,0x5c,0xa6,0xd8,0xc0,0x1a,0x80,0x3d,0x94,0xbf,0x98, + 0xca,0x44,0xa3,0xa8,0xec,0x2c,0xbb,0x91,0x96,0x2a,0xc5,0x5,0xca,0x65,0xa3,0xaa, + 0xed,0x9,0x17,0x66,0x18,0x4a,0x70,0x1c,0x74,0xc5,0x2b,0x3,0xe7,0x4d,0x9a,0x9c, + 0x5a,0x6e,0x83,0xf6,0x29,0x32,0xca,0x34,0xa2,0x56,0xbc,0xe6,0xaa,0x79,0x30,0x1, + 0xaf,0xaa,0xa8,0x5c,0x3e,0xf1,0x99,0x8d,0xdc,0x19,0x72,0xab,0xcd,0x6,0x19,0x21, + 0x18,0x75,0xbd,0xe8,0x31,0x66,0xbb,0x62,0x92,0x55,0x75,0x72,0x67,0x12,0xbb,0x5c, + 0xcf,0x62,0xef,0x68,0x60,0x60,0x4f,0xc7,0x8f,0x4d,0x2d,0x8,0x34,0xa4,0x43,0xb8, + 0x29,0x8a,0x72,0x0,0x36,0x14,0xe0,0x5a,0xdc,0xca,0x9,0xba,0x83,0x8d,0x4d,0xc4, + 0x28,0xb9,0x6d,0x4a,0xd8,0x76,0xd5,0x46,0x95,0x66,0x8d,0x41,0x67,0xf5,0xd,0x58, + 0x64,0xb3,0x69,0x34,0xb4,0x2a,0xf4,0x20,0x3a,0xa1,0xb5,0x6a,0xa3,0x9b,0x59,0x3d, + 0x2a,0xd9,0x4f,0x13,0x95,0xad,0xbf,0x10,0xf3,0xf2,0x4f,0x80,0x74,0xef,0x53,0x27, + 0xec,0xa9,0x76,0xc5,0xe8,0x99,0xba,0x91,0x5e,0x83,0xf2,0x95,0x24,0x8b,0x89,0xc7, + 0x32,0x9f,0xb7,0x9,0xd7,0x4f,0x2c,0xf6,0x87,0xbc,0x9d,0xe8,0x31,0x47,0x4,0x26, + 0x92,0xae,0xab,0xf3,0xf2,0xba,0x36,0x6,0x5a,0x42,0x86,0xba,0x22,0x60,0xb,0x89, + 0xf,0x8,0x66,0x3,0x16,0x2e,0x31,0xed,0x70,0x63,0x4,0x27,0xa3,0x70,0x2d,0xb7, + 0x65,0x9d,0x8c,0x36,0xbb,0xd9,0xd8,0xea,0xc2,0xec,0x43,0xe8,0x5b,0x3b,0x33,0x19, + 0x43,0x40,0xf0,0xbe,0x8c,0x6e,0xea,0x5c,0x80,0xd0,0x9,0xff,0x95,0x45,0x73,0x7, + 0xb,0x4a,0x25,0x1d,0xec,0xdb,0x49,0x92,0x11,0x76,0xdd,0xb0,0x1,0xff,0xb5,0xa8, + 0x25,0x4d,0xee,0x8c,0x70,0x57,0x2a,0xdb,0x37,0x62,0x98,0xa7,0xb6,0x73,0xc7,0x3, + 0x76,0xb2,0xfb,0x75,0x66,0xfd,0x89,0xf8,0x57,0x1d,0x60,0x46,0xfb,0x3e,0xbe,0x24, + 0x6d,0xb4,0xea,0xd8,0x18,0x9d,0x1c,0xa6,0x1d,0x38,0xcc,0x7c,0x1f,0x86,0xd6,0x47, + 0x71,0xe6,0x99,0x61,0x8c,0x26,0xb6,0x81,0xce,0xb2,0x6f,0x6c,0x56,0xd5,0xef,0xff, + 0xe,0x90,0x1e,0x6,0x1,0x2a,0x85,0xbe,0xf4,0x79,0x5c,0xd5,0xd7,0xe9,0x8,0x5f, + 0xea,0xa9,0x70,0x5,0x7b,0x39,0x75,0xe3,0x3b,0xed,0x4c,0xfc,0x91,0x64,0x8c,0x67, + 0xd0,0x45,0x27,0x6c,0x42,0x40,0xff,0x17,0xa9,0xe7,0xa0,0x24,0x4e,0x26,0x84,0x8b, + 0xd6,0x1e,0x80,0x32,0xb5,0x31,0x91,0xcc,0x42,0x1c,0xc7,0x6c,0x52,0xfd,0x35,0x2c, + 0x95,0x2f,0x86,0xf5,0xc6,0x37,0xf4,0x9e,0xe4,0x4f,0xf1,0x7e,0x6,0xec,0xcf,0x64, + 0x42,0xbb,0x9b,0x7f,0x98,0xb1,0x94,0x13,0xa6,0x60,0x1d,0x29,0x38,0xdf,0xe7,0x91, + 0xa1,0x6d,0xda,0xfb,0xfd,0x1c,0xf3,0xc6,0x1e,0xed,0x90,0x70,0xf6,0xfe,0x16,0x7f, + 0xb2,0xc4,0x86,0xf0,0xe5,0x8b,0xd4,0x5d,0x97,0x16,0x89,0xb2,0x98,0x31,0xeb,0xef, + 0x3b,0x47,0x5,0x7d,0x19,0x6a,0xeb,0x11,0xa1,0x37,0xa0,0xc2,0x2d,0x6e,0xef,0x11, + 0x41,0xe,0x86,0xc6,0x56,0x22,0x21,0xd8,0x81,0x26,0x7,0x98,0x52,0x82,0x7d,0x4d, + 0x79,0xc0,0x27,0x5c,0x30,0xea,0xeb,0x8b,0x88,0x4e,0x16,0x45,0x15,0x9e,0x9,0x5, + 0x87,0xd2,0x9b,0x94,0x96,0x1a,0x6e,0x25,0xd1,0xd3,0x93,0x54,0x46,0xb0,0x4d,0xc9, + 0x59,0x20,0xef,0x35,0x1c,0xd5,0xc8,0xb3,0x83,0xdd,0x2f,0xa2,0x72,0x5a,0x22,0x8f, + 0x6b,0xd4,0x80,0xc2,0xf5,0xce,0x3f,0xe0,0x54,0xdc,0xcb,0x52,0x55,0xab,0x32,0x6, + 0x61,0xe2,0xa5,0xce,0xa6,0x6c,0xca,0xb0,0x94,0xcc,0x1e,0x96,0x69,0xa7,0xe2,0x8, + 0xd3,0x5,0x26,0xd5,0x99,0x8,0x2,0x89,0xb4,0x6b,0x23,0xe6,0xa6,0xd0,0x64,0x84, + 0x2,0xfa,0x8,0x1a,0x26,0x22,0x48,0x45,0x4f,0xfb,0x24,0x48,0x93,0x7,0xdc,0x81, + 0x54,0x71,0xe1,0x98,0x34,0x8d,0xd,0x9e,0x88,0x77,0xaf,0x5c,0xa3,0x7c,0xd6,0xf3, + 0x1c,0x46,0xcb,0xec,0x6a,0x7c,0xc1,0x22,0x36,0xee,0x54,0xc5,0x6f,0x7d,0xe4,0xa0, + 0x56,0x3d,0x23,0x5c,0x18,0xc4,0x97,0x3,0x76,0x1f,0x62,0xaf,0x23,0xfc,0xa,0x21, + 0x1,0xf1,0xeb,0x52,0x61,0xed,0xd0,0xae,0x29,0x9f,0x4e,0xf0,0x71,0xc3,0x61,0xde, + 0xb,0xa2,0xe2,0x54,0xae,0x9f,0xce,0x27,0xf9,0xa3,0xce,0x86,0x32,0x44,0x73,0xd5, + 0xd4,0x48,0x93,0xb8,0x74,0x88,0x2b,0x9b,0x7f,0xd5,0xfb,0x3e,0x2b,0x18,0xa2,0xf5, + 0x4f,0x76,0xb,0x8,0x56,0xd0,0x41,0x2b,0x9c,0xc5,0x66,0xdf,0x89,0x34,0x6d,0xec, + 0x8e,0x86,0xb2,0xa1,0x14,0x2,0x45,0x67,0x4f,0x33,0x93,0x6e,0x4f,0xb0,0x58,0x79, + 0x9f,0x7d,0x96,0x16,0x31,0x17,0x5d,0x8d,0x98,0xd8,0xcd,0x34,0x28,0xc4,0xae,0x69, + 0x8,0xf3,0x6b,0x3e,0x17,0x3d,0x19,0x37,0xb4,0x33,0xfb,0xa9,0xd1,0x3b,0xbd,0x74, + 0x6d,0x5e,0x5a,0xbb,0xf,0xf9,0x99,0x2b,0x36,0xaa,0x39,0x8d,0x9d,0xdb,0x17,0xbc, + 0xea,0x7,0x5e,0xa0,0x21,0x88,0xeb,0x9d,0xa8,0x0,0x38,0x51,0xc4,0x5c,0xe9,0x2d, + 0xf6,0x15,0x1b,0x32,0xd1,0x5b,0x13,0x6a,0x9b,0x4a,0xf3,0x6b,0xe0,0x42,0xfc,0x94, + 0x4f,0xe5,0xc5,0x1d,0x8c,0x15,0x3e,0x4f,0x39,0xc0,0x9e,0x1b,0x80,0x81,0xaf,0x20, + 0x5,0x17,0xf5,0x9,0xd0,0xd4,0x25,0x3d,0x64,0x61,0xbb,0xb3,0x81,0xb,0xe9,0xb3, + 0x33,0x48,0xd4,0xde,0xca,0x46,0xaf,0x3,0xe9,0x8b,0x42,0xd3,0xd4,0xe5,0xb0,0x35, + 0x21,0xd4,0x70,0xa9,0xdf,0x44,0x93,0xa2,0x8b,0x6a,0x21,0x46,0xcc,0x9a,0x24,0xdc, + 0x9e,0x68,0xc8,0x71,0xea,0x1c,0xcd,0x46,0x20,0x30,0x88,0x64,0xf1,0x39,0x2f,0xdf, + 0xb2,0x3f,0xfa,0x9a,0x8,0x54,0xe7,0x53,0x39,0x9,0x37,0xd6,0xb,0x81,0x9b,0x39, + 0x54,0xb5,0x66,0x7f,0x23,0x46,0x5d,0x71,0x39,0x26,0xa,0x76,0xdd,0x3d,0x9a,0xfb, + 0x45,0x57,0xcd,0x5e,0xc9,0x2a,0x4c,0x52,0x69,0xe,0xd3,0xcd,0x41,0x95,0x1a,0x4e, + 0x72,0x86,0x45,0x49,0xf7,0xa1,0x4d,0x7f,0xea,0xd4,0x5,0xef,0x66,0xd9,0xfe,0x7d, + 0xd,0xd5,0xde,0xf,0x98,0xab,0x4f,0xa4,0xfd,0xfd,0x9a,0x3c,0x5b,0xcd,0xf,0x7b, + 0xb,0x9c,0xf4,0x99,0xf8,0x4d,0x2c,0xe2,0xce,0x92,0x9b,0xa,0x59,0xc9,0x78,0x19, + 0xb6,0xc,0xeb,0xe3,0x17,0x1e,0xfe,0xd6,0xcf,0xa6,0x24,0xd1,0x24,0xc3,0xba,0xb2, + 0x99,0x78,0x65,0x23,0x4,0xfb,0x8d,0x39,0xbc,0x9f,0xd5,0x7a,0x29,0xd1,0x6c,0x62, + 0x2b,0xc9,0x7a,0x88,0x63,0x26,0xa6,0xc5,0xb4,0x7f,0x45,0x1d,0x5d,0x8c,0x4,0x24, + 0x8d,0x94,0x56,0xae,0x9c,0x4c,0xd9,0x75,0x8,0x74,0x9b,0x50,0x93,0xc9,0x2c,0x76, + 0x67,0xb8,0x0,0xc6,0x19,0xf0,0x5a,0x83,0x9b,0x57,0x24,0xea,0xde,0x89,0x9d,0x4, + 0x98,0xdf,0x3f,0x29,0x1f,0x66,0x52,0x85,0xa3,0xa2,0x2c,0xc2,0x37,0x20,0x9,0x88, + 0xae,0xa2,0xc5,0xf0,0x41,0xb9,0xab,0xe0,0x2b,0x19,0xd2,0x61,0x0,0xa2,0x53,0x26, + 0x31,0xfb,0xce,0xf2,0x39,0x6d,0x2a,0x61,0x77,0x99,0x2f,0xa9,0x8f,0x3c,0xc7,0xbe, + 0xbf,0xb5,0x6d,0x6a,0x96,0x84,0x5f,0x23,0x79,0xac,0x2e,0x47,0xbf,0x2c,0x74,0xc5, + 0x8b,0xe2,0xe1,0x87,0x8,0xdb,0xf8,0xb6,0xe,0x14,0xb4,0x2d,0x6b,0xe8,0xda,0xe3, + 0x67,0x93,0xc1,0x8b,0x72,0x83,0x98,0x43,0x93,0x6c,0xbc,0x1a,0xa5,0x8c,0x6c,0x7b, + 0x60,0x69,0x1,0x3e,0x7f,0xc6,0x90,0xbe,0x4d,0x25,0x42,0x19,0x9d,0x4d,0xd6,0x26, + 0x4,0xd6,0x62,0xb6,0xe,0x4b,0x2d,0x79,0x85,0x6a,0x3b,0x14,0x2b,0x86,0x2a,0xb1, + 0x46,0xa4,0x8d,0xec,0xf9,0x8,0x12,0x5a,0x63,0x1d,0xb4,0xb8,0xd2,0x56,0x36,0xc1, + 0xde,0x6b,0xf0,0xa7,0xf0,0x55,0x8e,0x53,0x1c,0xc4,0xb7,0xfe,0xec,0x5,0xc9,0x63, + 0xa4,0xce,0xf3,0xc5,0x87,0xea,0x5e,0x9a,0x8d,0xb,0xae,0x38,0x73,0xde,0xfa,0xbc, + 0x5a,0xdc,0x5b,0x76,0x77,0x5f,0x54,0x48,0xdc,0xe8,0x3,0xd6,0x99,0x72,0xf8,0xa6, + 0xd2,0xa1,0x2d,0xca,0x7b,0x37,0x3f,0x23,0xa4,0x12,0x9f,0x1e,0x50,0x6d,0x96,0xe1, + 0xe3,0x94,0xb6,0x5c,0x70,0x44,0x55,0x6a,0xc1,0x14,0x4c,0xd7,0x9d,0x98,0x7c,0x87, + 0xab,0x50,0x31,0xc5,0x40,0xdb,0xb0,0x77,0x99,0x1,0x8,0x59,0x27,0x9,0x65,0x21, + 0x87,0x84,0x16,0x34,0x3c,0x85,0xe8,0x49,0x84,0x4b,0x70,0xea,0xc,0x36,0x2,0x5b, + 0x9b,0x85,0x91,0xc4,0x1d,0xf,0x33,0x39,0xc8,0xf4,0x89,0x31,0x39,0xa4,0xbb,0xf, + 0x3c,0xb2,0x57,0xe5,0x71,0x32,0x36,0xd,0xca,0x11,0xe2,0x64,0xca,0xaa,0x4f,0x71, + 0xaf,0xac,0x92,0x77,0x9c,0x41,0xcb,0x7d,0x50,0xfa,0x1c,0xc8,0xb4,0x35,0x57,0xf2, + 0xb0,0x60,0x3d,0xe,0x1e,0xc5,0x34,0x9d,0x69,0xe7,0x8f,0xc,0xc4,0x33,0x44,0x32, + 0xc6,0xc1,0xd3,0x9d,0x7e,0xb4,0x30,0x64,0x8a,0x91,0xc2,0x6,0x72,0xe8,0x33,0x69, + 0x98,0xa0,0x23,0x61,0x7a,0x7f,0x75,0x8e,0x78,0x52,0xd9,0x48,0x37,0x32,0xe3,0x8e, + 0xb8,0x2e,0xb9,0xd0,0x83,0xc,0xda,0xb5,0x0,0x91,0xec,0x1f,0xd0,0x7b,0xb3,0xba, + 0x4d,0x94,0xd5,0xce,0x24,0xca,0xd2,0x8,0x59,0xa5,0xfe,0xd7,0xc1,0xda,0x85,0x28, + 0xe9,0xed,0x9c,0x38,0x13,0xbb,0x1a,0x3c,0x74,0x20,0xea,0x96,0x33,0x49,0x8d,0xa1, + 0x78,0x3a,0x11,0x32,0x4b,0xc9,0x7b,0xc4,0x5c,0xcb,0x68,0x50,0x1b,0x80,0x36,0x43, + 0x1f,0xe8,0x6b,0x84,0xc1,0x63,0x4,0x7a,0x60,0x62,0x1b,0xb3,0x1c,0xa2,0x1c,0x93, + 0xc7,0xe9,0x81,0x7e,0xb8,0x68,0x4f,0xe,0x87,0x5e,0x73,0xe7,0x33,0x44,0x55,0x9e, + 0x2d,0x80,0x81,0x81,0x8f,0x30,0x98,0xc1,0x40,0x8,0x9d,0x48,0xab,0xc0,0x29,0x6a, + 0x72,0x8e,0x8f,0x46,0xc,0x8c,0x44,0x4b,0xcb,0xa8,0xbb,0x58,0x13,0x45,0x80,0x7e, + 0x9e,0xaa,0x6a,0xea,0xc5,0xc1,0x8c,0xc,0x87,0xf8,0x1d,0x49,0xd7,0x35,0xb8,0xc6, + 0x84,0x79,0x54,0x73,0x15,0x33,0x44,0x5c,0x4d,0x6d,0x9c,0xab,0x95,0xaf,0x7b,0x92, + 0x3e,0xbc,0xfd,0x91,0x9f,0xfc,0xb1,0x79,0x71,0x71,0xf,0xe8,0xe7,0x34,0x46,0xca, + 0xf6,0x69,0x76,0x49,0x1d,0x82,0x36,0xa8,0x8c,0x6d,0xf4,0x8d,0xe4,0x38,0xf,0xf8, + 0x40,0x2f,0xc4,0xb7,0xf3,0x1b,0xa6,0x96,0xeb,0x50,0x14,0xf3,0xcc,0x13,0xad,0x74, + 0x8,0xac,0x1a,0x88,0x40,0x87,0xef,0xe7,0x37,0x78,0xb4,0xe3,0x6b,0x52,0x84,0xe6, + 0xf8,0x19,0xe1,0xa6,0x93,0x7c,0xe0,0x41,0x8d,0xf6,0x6c,0xaa,0x35,0x89,0x9d,0xa6, + 0x5e,0x45,0x77,0x5c,0xdb,0x81,0x9,0x71,0xd8,0x37,0x5d,0x99,0x55,0xc1,0x27,0xc7, + 0x5,0xd3,0x26,0x3c,0xfc,0x36,0x62,0x23,0x6,0x68,0xdf,0xb9,0xf5,0x9e,0xdd,0x8f, + 0x5,0x26,0x35,0x6a,0x36,0xa3,0x84,0xaf,0x12,0x4d,0x6,0xa8,0x2,0x2b,0x65,0x9a, + 0xdc,0x7a,0xd,0xfa,0x63,0xda,0xf4,0x81,0x7a,0x17,0x28,0x93,0x36,0xe5,0x70,0xc9, + 0x50,0x6c,0x73,0x3b,0x40,0xe6,0xbe,0xb0,0x75,0xb9,0x17,0x31,0x13,0xa6,0x8c,0xb4, + 0xd0,0xd4,0x1,0x54,0x9e,0xb4,0x2d,0x10,0xd5,0xc4,0xe6,0x42,0x98,0x92,0xc7,0x77, + 0xda,0x3b,0x2f,0x17,0xee,0xd1,0x9d,0xcd,0xf3,0xc,0x7c,0xc7,0xfd,0xf3,0xdd,0x5e, + 0xf4,0xfa,0xfb,0x8e,0x2e,0x6c,0x47,0xe,0xfb,0x21,0x78,0x1c,0xff,0x73,0xfa,0x8c, + 0x93,0x4c,0xf2,0x49,0x3a,0x39,0x9,0x9e,0xfc,0x77,0xb8,0x1e,0x7c,0xe3,0xf5,0xc3, + 0xdf,0xdb,0x40,0x35,0xfc,0x30,0xe4,0xec,0x38,0xa8,0x76,0xc6,0xde,0x4a,0x62,0x30, + 0xf2,0xe3,0x4,0x55,0x6e,0x4,0x43,0x32,0x76,0x5a,0x58,0x22,0xb6,0x1,0x32,0x90, + 0x4c,0x61,0xe4,0xeb,0x74,0xc8,0x74,0xaa,0xc4,0xa5,0x34,0x99,0x7e,0xcd,0xae,0x72, + 0xe6,0x3b,0x1d,0xd1,0x98,0x2,0x4d,0x91,0x33,0xa4,0xea,0xb6,0x29,0xcb,0x45,0xd1, + 0x39,0x16,0xeb,0x1c,0x4,0xbd,0xe,0x6e,0xa9,0xf9,0x44,0xe3,0xef,0x2e,0xd4,0xac, + 0x4e,0x83,0x2e,0xdf,0x1c,0x2d,0x9e,0x1,0xea,0x23,0x86,0xca,0x6f,0x16,0x34,0xf8, + 0xfa,0xbf,0xcb,0x88,0x26,0x29,0x93,0x38,0x70,0x75,0xa3,0x6,0xbb,0xfa,0x98,0x69, + 0xcc,0x6d,0x2b,0xbc,0xc3,0xe6,0xbd,0x5d,0xf3,0x3c,0x72,0x72,0x62,0xa2,0x3f,0x37, + 0x12,0xd5,0x94,0xd8,0x54,0x2e,0xc9,0x57,0x2f,0xbe,0x8b,0x6d,0x1,0x6a,0x8f,0x33, + 0xb2,0xf4,0x81,0xc5,0x6f,0x95,0x6d,0x38,0xd9,0x29,0xa4,0xe6,0x4,0xbb,0x80,0xfd, + 0x80,0xb6,0x7,0xb5,0x87,0xc3,0xec,0x43,0x9b,0x14,0x2e,0x83,0x5a,0x12,0xec,0x56, + 0xa4,0xc6,0x74,0xef,0x23,0xad,0x67,0x44,0xb8,0x9c,0xa1,0x48,0x5f,0xda,0xa8,0x61, + 0xac,0x29,0xe8,0xbc,0xfd,0x3,0x4f,0x62,0x13,0x9d,0x76,0xaf,0x16,0xf2,0x7b,0x95, + 0x1d,0x1c,0xb2,0x97,0xe8,0xe4,0x38,0xd5,0x99,0x26,0xf5,0xfa,0xa2,0xa2,0xc9,0xe9, + 0x6,0x4,0xfb,0x5d,0xa1,0x7d,0xc,0x5,0xd2,0x4a,0x32,0x2f,0xb9,0x45,0x31,0x21, + 0x30,0xf4,0xdb,0x90,0xf7,0x73,0xc4,0x2a,0xaf,0x20,0xe,0xa2,0xb7,0x59,0x51,0x8d, + 0xbb,0x80,0x63,0x9b,0x2d,0x2b,0x54,0x74,0x92,0xa7,0xbd,0x4,0x3,0x12,0xd3,0xdb, + 0x76,0x5e,0x21,0xa2,0x66,0x1d,0xdf,0xc3,0x35,0xa4,0x3d,0x57,0x63,0x1a,0x71,0x73, + 0x9,0x6,0x57,0x34,0x67,0xf1,0x77,0xc4,0x27,0xef,0xef,0x49,0x6b,0xa0,0xff,0x46, + 0xfa,0x59,0x86,0x1e,0xa8,0x3a,0xf1,0x70,0xb0,0xdc,0x33,0xa2,0xf1,0xfe,0x3d,0x90, + 0x7d,0xe3,0xad,0x5e,0xa,0xf7,0x29,0xd9,0xcd,0xf,0xf9,0x90,0x47,0x3d,0xf4,0x42, + 0xc,0xed,0xc2,0x11,0x44,0x9b,0xcd,0xe,0xb6,0x96,0x9d,0xe3,0x56,0x10,0xa2,0x69, + 0x70,0x81,0x5e,0xd5,0x17,0x53,0x12,0x15,0xbd,0x58,0x50,0x52,0x76,0xf9,0x96,0x56, + 0x6e,0x86,0x49,0x1c,0xb4,0xa0,0x5,0xdb,0x67,0xd9,0xde,0xa6,0xa2,0x4f,0xf7,0x64, + 0xd3,0x3e,0xec,0xd1,0xc6,0xd6,0x79,0x40,0x2b,0x1a,0x3f,0x82,0x35,0x8a,0x4e,0x6d, + 0x69,0xe8,0x9c,0x26,0xc1,0x20,0x12,0x85,0xa6,0x2b,0xf2,0xa6,0x4c,0xe5,0xee,0x58, + 0x39,0xbb,0xe4,0xee,0xec,0xc9,0x15,0xd4,0x9e,0x31,0xa3,0x45,0x68,0xca,0x54,0x47, + 0xaa,0xf3,0x55,0x5,0xb1,0x1,0x4c,0x92,0x15,0xc1,0x5c,0x72,0xcc,0x2c,0xe6,0xb6, + 0x7,0x5,0x67,0x7b,0x56,0x5a,0xd2,0x27,0x6e,0x3c,0xa5,0x42,0xfc,0xcf,0x73,0xa1, + 0x90,0x13,0x22,0xe1,0x97,0x72,0x16,0x81,0xaf,0x6e,0xc7,0xa8,0xf4,0x4c,0x81,0x18, + 0x23,0x18,0x84,0xe1,0xc3,0xfc,0x15,0x33,0xd3,0xcd,0xec,0xa0,0x82,0x3,0x20,0xea, + 0x69,0xcf,0xe8,0x47,0x6,0xe3,0x11,0x32,0xb4,0xb4,0xd4,0xf,0x4c,0xd5,0xe,0x1e, + 0x8a,0x0,0xc,0x59,0x60,0x4d,0xb3,0xe6,0xa3,0x9e,0x7f,0xef,0x67,0xd,0x83,0x4, + 0x75,0x30,0x7,0x1f,0xfb,0x53,0x78,0xd1,0x7f,0xca,0xe0,0x8f,0xa6,0x10,0x56,0x2f, + 0xc8,0x98,0x53,0x35,0x35,0x59,0xe6,0x42,0x44,0x4e,0xaa,0x66,0x9f,0xd1,0x43,0xe5, + 0x34,0x95,0xa7,0x69,0x9c,0xa1,0x9a,0x9d,0x2f,0xca,0x4d,0xd5,0x3a,0x3b,0xfd,0x20, + 0xa0,0xbb,0xaf,0x1d,0xd,0x3a,0x2,0xdd,0x80,0xba,0x86,0x85,0xe3,0x95,0x56,0x13, + 0x23,0xf6,0x18,0x92,0xbd,0xda,0x1e,0xa0,0x19,0x5d,0x78,0x42,0xf8,0xf4,0xc5,0xbb, + 0xc,0x0,0x4,0x3d,0xc2,0x88,0x38,0x28,0xda,0xc0,0x41,0x92,0xf3,0x71,0xd7,0x32, + 0xa7,0x35,0x78,0x8b,0x62,0x79,0x75,0x8f,0xfb,0x46,0xa,0x83,0x4c,0xee,0xca,0xdb, + 0xd,0x93,0x2a,0x6b,0xd1,0xc7,0x76,0x73,0xef,0x12,0x6e,0x16,0x85,0x9c,0x1c,0x60, + 0x10,0x55,0xf3,0x9a,0x88,0x7e,0xfb,0xb,0xdd,0x14,0xb3,0xca,0xd4,0x8,0x4d,0x1a, + 0x1a,0xe9,0xb1,0x1e,0x23,0x86,0x36,0xc8,0x74,0x59,0x4b,0x2b,0x47,0x89,0x75,0x0, + 0x81,0x8,0x85,0x40,0xad,0xea,0xe1,0x3a,0xe9,0x44,0x75,0xa5,0xbf,0x5c,0xed,0x40, + 0x1b,0xad,0x56,0xf9,0xe5,0x96,0x7c,0x44,0x79,0xa4,0xa3,0xc5,0x86,0xd6,0xd,0xc6, + 0x34,0x5f,0x31,0x81,0x8b,0x57,0xb1,0xfd,0xc8,0xd1,0xbc,0x37,0xdc,0x1c,0x93,0xc1, + 0x3b,0x99,0x12,0x25,0x8d,0x7a,0xa3,0x9c,0x97,0x35,0xc6,0xa8,0x16,0xda,0x45,0xf1, + 0x3a,0xd8,0x48,0xc6,0xdb,0xfe,0x7c,0xed,0x39,0x8a,0x20,0xc,0x27,0xd2,0x83,0xc3, + 0x36,0x8b,0x8,0x33,0x10,0x1f,0x12,0x4b,0x74,0x12,0x6,0x6,0x9d,0x7,0x34,0x19, + 0xd2,0x74,0x84,0x6a,0xd9,0x51,0x8b,0xb,0x5b,0x72,0xb0,0xb9,0x7f,0x8f,0x8e,0x95, + 0x31,0xa0,0x4f,0xcc,0x59,0x56,0xc8,0x2c,0x22,0xfa,0x79,0x1a,0x74,0xbd,0xce,0xe7, + 0x76,0x80,0x83,0x7b,0x87,0x7,0x2d,0xb6,0xf5,0x92,0x4e,0x8a,0x55,0x38,0xf4,0xbf, + 0xce,0xa,0x68,0x3b,0x29,0xfa,0x5f,0x3e,0x7e,0xfc,0x5e,0x55,0xf5,0x5f,0xbd,0xff, + 0x47,0x1f,0x4d,0x99,0xc5,0x3e,0xd6,0x93,0x19,0x25,0xdc,0xa5,0xe3,0x54,0xf7,0xb0, + 0x3e,0x34,0x4d,0xb0,0x7b,0xb2,0xa3,0x43,0x9c,0x75,0xb0,0x6b,0x12,0xd2,0xbf,0xbf, + 0x87,0xad,0xb5,0x50,0x13,0x2,0x93,0xb,0x6c,0xad,0x43,0xc9,0xbe,0x99,0xbd,0xec, + 0xcd,0xe7,0x0,0xbb,0x84,0xed,0x80,0xe3,0xdb,0x21,0xd9,0x9b,0xba,0x98,0x7a,0x56, + 0x65,0x26,0x35,0xc4,0x40,0x70,0x7c,0x7a,0x63,0x62,0x33,0xb9,0xd,0xea,0x2d,0xc1, + 0x64,0x30,0x8c,0x55,0x1f,0x41,0xc9,0x78,0xac,0xee,0x51,0x0,0x60,0x18,0xaf,0x81, + 0x3b,0xbc,0xd2,0x95,0xdf,0x2b,0xe,0xed,0x42,0x97,0x8f,0x2d,0xb8,0xe5,0x30,0x83, + 0x6b,0xb0,0x89,0xab,0x8e,0x7e,0x4e,0x6a,0x7f,0xe0,0x5c,0x35,0xa7,0xc3,0x30,0x23, + 0x87,0x86,0x28,0x74,0x21,0x8e,0x59,0x6f,0xdd,0x28,0xf,0x24,0x1d,0xf5,0x2a,0x4, + 0x73,0x4a,0x7c,0x10,0x20,0x79,0xb,0xad,0xa7,0x45,0x4c,0x62,0x30,0x7b,0x4f,0x51, + 0xe0,0x6b,0x4,0xdf,0x4b,0x7f,0xe1,0x76,0x96,0x53,0x4d,0xfe,0x89,0x6b,0xb1,0xcf, + 0x6d,0x9a,0xa8,0x57,0xd0,0x6e,0xa5,0x50,0x23,0x52,0xb5,0x3f,0x49,0x61,0xce,0x0, + 0xb1,0xf6,0xec,0x77,0x68,0xa,0x58,0xbc,0x58,0xe7,0x8b,0x48,0xea,0x4e,0xc9,0x2a, + 0xd2,0xcf,0x90,0xdd,0xac,0x44,0xb4,0xae,0xcd,0x6a,0xb7,0x2a,0xc8,0xa7,0x7a,0x6e, + 0xfb,0xa8,0xe3,0xc3,0xbe,0xb7,0x36,0xb7,0xdc,0x5b,0x3c,0xe3,0x95,0x89,0xc7,0x87, + 0xbc,0x6d,0xdb,0xf,0x55,0xcd,0xb3,0x3c,0x63,0xb9,0x91,0x91,0xe7,0xb2,0x39,0x42, + 0x5c,0xba,0x2a,0x68,0x6f,0x60,0x13,0x76,0xd7,0x3c,0x7,0x87,0xa,0xc6,0xb5,0xa1, + 0x2f,0x93,0x43,0xad,0x9a,0xc7,0xa1,0xc6,0xe9,0xe2,0x23,0x29,0x63,0x86,0xa3,0x51, + 0xc3,0xdc,0x25,0x30,0xaf,0xa0,0xc9,0x3b,0x4,0xfb,0x6a,0x50,0x83,0xfc,0xe2,0xf5, + 0xaa,0x2b,0x16,0xc1,0xf5,0x1a,0xf1,0xc8,0xe,0xd7,0x4,0x37,0xb1,0x7,0x57,0xc6, + 0xcc,0xa7,0x40,0x26,0xd7,0xf4,0x23,0x86,0x6b,0x43,0x32,0x5d,0x87,0x9b,0xd8,0x5c, + 0xf0,0xd8,0x20,0x3c,0x7e,0x56,0xf1,0x33,0x20,0xd0,0x50,0xaf,0x43,0x4,0x25,0xe6, + 0x22,0xcd,0x2d,0x64,0x70,0x1f,0x4,0x15,0xd4,0x86,0x2e,0x5d,0x10,0x6,0xcd,0xc, + 0x54,0xaa,0xa7,0x10,0x8,0xc2,0x3c,0x72,0xc6,0xb0,0x4d,0xa1,0xea,0x89,0xb4,0x16, + 0x8f,0x4c,0x5a,0xb0,0x43,0xb8,0x88,0x29,0x48,0xb3,0x7b,0x44,0x28,0x9e,0x99,0x4c, + 0xf5,0x86,0xfc,0xd1,0x4,0x58,0xd0,0xc9,0x46,0x32,0x1b,0xcc,0x9a,0x49,0x56,0x14, + 0xf7,0x30,0x99,0x8b,0x72,0x66,0x3b,0xf0,0xba,0xa3,0x23,0x37,0x82,0xd3,0x3e,0xe0, + 0x25,0x4,0x51,0x78,0x95,0x18,0x4b,0x8a,0x2a,0x66,0xa4,0x64,0xb6,0xac,0xa4,0x26, + 0xbe,0x16,0xaa,0x89,0x4d,0x35,0x3,0x3b,0xf4,0xa4,0xc4,0x44,0x6a,0xd0,0xdb,0x71, + 0x9a,0xf0,0xa7,0x2,0x97,0x6,0x67,0x44,0xb2,0xdd,0xf0,0x23,0x64,0x95,0xc5,0x32, + 0xa6,0x42,0x24,0x5,0x56,0xf5,0x2d,0x43,0x9f,0x5d,0x41,0xc1,0x66,0xb0,0x11,0x12, + 0xce,0x41,0x86,0x2b,0x1d,0x97,0xb,0x18,0xdf,0xe,0x78,0x85,0xbe,0x35,0x61,0xa8, + 0x36,0xed,0xd0,0x35,0xfb,0xfb,0xa8,0xa1,0xc,0xfa,0x87,0xc,0x36,0xc6,0xd0,0x4e, + 0x34,0xff,0xc6,0x6a,0xfd,0xc4,0x25,0xa1,0x8a,0x58,0x7b,0xbd,0xde,0xac,0x4a,0x7, + 0xc0,0x7e,0x8e,0x10,0x68,0xa9,0x44,0x3b,0x29,0x8,0x9f,0x5,0x4f,0xa7,0x3d,0x3a, + 0x7c,0x60,0xa6,0x53,0x43,0x78,0xda,0xef,0x71,0x4d,0x8,0x9f,0x80,0xe8,0x9,0x8, + 0xb4,0x1d,0x48,0xdf,0x3b,0x48,0x90,0x5c,0x84,0x64,0x2c,0xdf,0xa9,0x41,0x98,0x46, + 0xe,0x0,0xca,0x28,0xdc,0x83,0xde,0x30,0xde,0xf7,0xe6,0x2,0x11,0xcd,0xb1,0xba, + 0x72,0xee,0x47,0xc5,0x1d,0x92,0x59,0x34,0x53,0x44,0xd2,0x7f,0x7b,0x8,0x8,0x47, + 0x96,0x5f,0x75,0xb5,0xfa,0x93,0xb,0x49,0xe2,0x4a,0x32,0x5e,0x12,0xba,0xa0,0xdd, + 0xcd,0x28,0xf,0x9,0x85,0x85,0x52,0x60,0x7c,0xcd,0x17,0x33,0xc4,0x29,0xf2,0x27, + 0xf7,0xcf,0x67,0x73,0x1e,0xb,0xf1,0x90,0xc8,0x14,0xcb,0x8c,0x67,0xaa,0xe9,0x5e, + 0x6e,0x2,0x19,0x1a,0xfd,0x85,0x71,0xbd,0x9a,0xb2,0x32,0x31,0x4d,0xe3,0x17,0xa2, + 0x58,0x9d,0x45,0xd7,0x90,0xd9,0x15,0x93,0xdd,0x3c,0x84,0x40,0xe3,0x13,0x34,0x91, + 0x86,0xc,0x38,0xba,0xe7,0xb2,0xd7,0x66,0xda,0xf8,0x6e,0xee,0xa2,0x56,0x8d,0xbb, + 0x95,0xc2,0x5d,0x3d,0x61,0x20,0xc9,0xb0,0x46,0x7d,0x7d,0x84,0x1f,0x7b,0x4d,0x8f, + 0x5e,0x4d,0x43,0x9a,0x90,0x4a,0xef,0x98,0x52,0xd0,0x0,0xef,0x23,0x8b,0xb1,0x91, + 0xad,0xbb,0x74,0xde,0x71,0x61,0xe5,0x12,0xfd,0xfb,0x6,0xcc,0x37,0x76,0x3d,0xad, + 0x7a,0xf5,0x9e,0x64,0x69,0x23,0x4f,0x50,0x9,0x17,0xa0,0x5c,0x86,0x47,0xe2,0xd2, + 0x66,0x86,0x25,0x26,0x58,0x59,0xcb,0x7b,0xda,0x24,0x36,0xf,0xc4,0xc2,0x5,0x63, + 0x1a,0x2f,0xc1,0xa1,0x73,0x87,0xb7,0x65,0xc2,0xa4,0x30,0x54,0xef,0xb0,0xfd,0x6b, + 0x9c,0x19,0x91,0xb,0x65,0x8,0xa6,0xe4,0x71,0x63,0x15,0x97,0x76,0xa4,0x64,0x5f, + 0xb0,0x7c,0x12,0xa4,0x4a,0xef,0xa1,0x67,0x31,0xa6,0x4,0x4c,0x7f,0xe6,0x45,0x41, + 0xda,0x12,0xc5,0x41,0x87,0xe5,0x3d,0xe9,0xbb,0x36,0xe9,0x92,0xd5,0xc,0x7c,0x72, + 0x3c,0xcf,0x34,0x3,0x48,0x47,0xda,0x72,0x7a,0x74,0xc9,0x80,0xb,0x44,0xcf,0xe8, + 0xc9,0x8e,0xa2,0x5f,0x3,0x67,0x22,0x64,0x53,0x61,0x8a,0x9a,0xe5,0x2,0x41,0x30, + 0x6c,0x36,0x5a,0x83,0xc,0xc4,0x94,0xbd,0x7f,0x37,0x6,0xc7,0x74,0x86,0xcc,0x40, + 0x4e,0x49,0x4,0x5d,0x2a,0xd7,0x90,0x8,0xb0,0x17,0x3a,0x7a,0x60,0x61,0xd2,0xd5, + 0xaf,0x3a,0x51,0xbb,0x51,0xc3,0x35,0x62,0x50,0xd1,0x6f,0x3a,0x6d,0x83,0xfc,0xb3, + 0x2c,0xbc,0xab,0x11,0x4a,0x0,0x83,0x83,0x5e,0x42,0xa8,0xd0,0xaa,0x51,0xc4,0x2a, + 0x9a,0xb4,0x68,0x88,0xa0,0xa0,0x42,0x97,0x5d,0xb9,0x14,0x88,0xdf,0x39,0xc8,0x42, + 0x4e,0xde,0xb7,0x51,0x35,0x6d,0xa2,0x5f,0x66,0xbd,0x5d,0x2a,0x34,0xb5,0x75,0xa8, + 0xe2,0xc,0x89,0xe,0x84,0xd9,0x47,0x85,0x3a,0x93,0x41,0xc5,0x61,0x90,0xd1,0xe4, + 0xb4,0x7,0xf,0xc,0x8e,0x3e,0xcb,0x82,0x36,0xe4,0x35,0x2d,0x8f,0xe7,0xc8,0x72, + 0x57,0xa0,0x82,0xb,0x2e,0xdc,0x15,0xfa,0x5f,0xfe,0x63,0xff,0xf1,0xc7,0x6f,0xff, + 0xeb,0x7f,0xfb,0x9e,0x84,0x47,0xa,0x44,0xea,0x15,0xc6,0x86,0x3f,0xdc,0x94,0x44, + 0xc5,0x18,0x44,0x1a,0x32,0x68,0x5b,0xcd,0x8f,0xbd,0xca,0x8e,0x5d,0x8c,0x26,0x27, + 0x38,0x26,0x8,0x7e,0x78,0xbb,0x34,0xa8,0xc2,0xab,0x34,0xf4,0x8,0x26,0xb,0x8a, + 0x16,0xc0,0x5d,0x56,0x33,0x47,0xee,0xea,0xda,0x88,0x0,0x9a,0x2f,0x75,0x8a,0x42, + 0xdc,0xf5,0xcc,0x75,0xf2,0xae,0x2f,0xeb,0xdd,0x99,0xae,0xb7,0x5e,0xf,0x5c,0x0, + 0xc8,0xfe,0xac,0x10,0x52,0xa8,0x7d,0x2c,0xd1,0xaa,0x83,0x7b,0xbf,0x6a,0x45,0x41, + 0x6e,0xd3,0x24,0x1b,0x7,0x7c,0x84,0x9c,0x4a,0xcd,0x94,0x5c,0xfe,0xd8,0x94,0x1a, + 0xa5,0x37,0x6b,0xbe,0x2b,0xf4,0x6b,0x57,0x94,0xc3,0xb4,0xc,0xa4,0xaf,0xac,0x2e, + 0x87,0x1b,0x31,0xba,0xbc,0x62,0x52,0xf1,0x90,0xb0,0xac,0x6f,0x6e,0xc2,0x3c,0xdd, + 0xf7,0x48,0x84,0xa8,0x55,0x15,0xbc,0x17,0xad,0xa8,0x4,0x30,0x90,0xe3,0x62,0xbc, + 0x4c,0xd4,0x25,0x19,0xe8,0x23,0x88,0xde,0x32,0x4c,0xd,0xf,0xd6,0x8b,0x43,0x22, + 0x41,0xb7,0x10,0x50,0x29,0x36,0x34,0x69,0x9f,0xd5,0x1c,0x4,0x1b,0xdd,0xbf,0x9d, + 0xc6,0xe5,0x41,0x37,0xd1,0x41,0xca,0xe9,0xa1,0xdd,0x5c,0x26,0xfa,0x15,0x25,0x2b, + 0xe,0xa8,0x27,0xea,0x5,0xff,0x64,0x52,0x9a,0x4,0x5e,0x20,0x9b,0xac,0xa6,0xaf, + 0x7d,0x75,0x7a,0xf8,0xb4,0x47,0x31,0xaa,0x36,0x60,0xc6,0xc2,0xb2,0xae,0x1b,0x25, + 0xa2,0xa7,0x36,0xc4,0x84,0xaf,0x61,0x1c,0x95,0x9d,0xdd,0x75,0x7a,0xc5,0x72,0x21, + 0x95,0xbf,0x18,0xd2,0x8f,0xaa,0x28,0x6,0x34,0x27,0x2c,0xaa,0xe4,0x5f,0xa8,0xee, + 0x2c,0x85,0x2d,0x33,0xee,0x80,0xc9,0x23,0x7d,0x65,0x95,0x97,0x25,0x12,0xab,0x47, + 0xa5,0x4e,0x38,0xc3,0xcc,0xf2,0x94,0x11,0x11,0xe1,0x2,0x4,0xf4,0xcc,0xcd,0xe, + 0x9b,0xde,0x6e,0xc0,0x88,0x7e,0xfb,0x75,0xb4,0x9,0x47,0x53,0x38,0x43,0xe7,0xcb, + 0x9b,0xcc,0x6d,0x8d,0x90,0x3b,0x6,0x7e,0xac,0xb9,0xcf,0x81,0x36,0x27,0x4c,0x13, + 0xda,0x48,0x5d,0x5f,0x4c,0x86,0x9d,0xeb,0x80,0xa3,0x54,0x3b,0xbf,0xfd,0xfb,0xff, + 0xf6,0x7d,0x3b,0x0,0x51,0x34,0xf0,0xd1,0x48,0x5e,0x8d,0xf9,0x2f,0x9e,0xf3,0x98, + 0x34,0xc0,0x55,0xad,0x49,0x36,0x97,0xba,0xde,0x2d,0xe2,0xa2,0x4,0x32,0xe,0x6d, + 0x10,0x17,0xdc,0x40,0x53,0xd2,0x1a,0x10,0xf9,0xad,0x50,0x85,0x6c,0x25,0xc4,0x81, + 0x2b,0xec,0x60,0x25,0x48,0x33,0x38,0x23,0x4b,0x59,0xd,0x1,0xbf,0x85,0x6b,0xe4, + 0xa3,0x65,0xcd,0x81,0x21,0x6e,0xd5,0xb9,0x7c,0x7,0xa2,0xda,0x68,0xc5,0xba,0x29, + 0x47,0x5d,0x3,0x34,0x0,0x33,0x2b,0xa3,0x6,0x19,0x74,0x1b,0x43,0xad,0x1c,0x9b, + 0xf0,0x92,0x92,0xae,0x54,0x57,0xdb,0x18,0xc5,0xa1,0xeb,0x3f,0x39,0x82,0x2d,0x5b, + 0x63,0x4d,0xde,0xfc,0x9e,0x20,0xd8,0xf6,0x14,0xd8,0x72,0xcb,0xc5,0xb2,0x79,0x5, + 0xa0,0x3a,0x94,0xef,0xf2,0xbc,0x15,0xf2,0xc5,0x2f,0xa4,0x84,0x87,0xd6,0x1,0x6, + 0x42,0x24,0xb,0x7,0x96,0xa3,0xfc,0xb2,0x5c,0x9b,0x96,0xa4,0x33,0xb2,0x5c,0xb6, + 0xf5,0x51,0xaf,0x94,0x3,0x9f,0xf9,0xe6,0x49,0x71,0x53,0xaf,0x5,0xa7,0xca,0x41, + 0xde,0x73,0xe1,0x0,0x9e,0x63,0x68,0xbf,0x1e,0x90,0xc8,0x64,0x62,0xa3,0x3f,0xf, + 0x14,0x46,0x7,0x45,0x23,0xb1,0xe2,0x94,0xed,0x62,0x6e,0xdf,0xe6,0x7b,0xb3,0x35, + 0x5c,0x27,0x7f,0x85,0xe1,0xfc,0x9d,0x6e,0x65,0x53,0x3b,0x45,0x1f,0xb4,0x80,0xb7, + 0x24,0x14,0xe5,0xb1,0xb5,0x66,0x62,0x66,0x61,0xf3,0x5,0x51,0xd1,0x93,0x16,0x5, + 0x42,0x39,0x33,0x27,0x30,0xfc,0x7d,0xfb,0x7a,0x2f,0xa,0x4b,0x14,0x42,0xd2,0xc9, + 0x83,0x85,0xe5,0x36,0xa2,0x4f,0xef,0x48,0x69,0xf3,0x1b,0xda,0x91,0x59,0x5b,0xeb, + 0x7f,0x42,0xec,0x10,0x61,0x7,0xd,0xac,0x77,0x15,0xb4,0x8b,0xab,0x3b,0x9,0x65, + 0x60,0xc7,0x18,0xe4,0x69,0x36,0x9b,0x55,0x88,0x8c,0x56,0x49,0x10,0x69,0x51,0xb9, + 0x33,0xd6,0x7d,0xe3,0xb8,0xe,0x48,0xb4,0x3e,0x28,0x62,0x5d,0xa8,0x78,0x7e,0x2a, + 0x55,0x39,0xe1,0x8f,0x56,0xb9,0x73,0x41,0x9f,0x29,0x13,0xba,0x48,0x1c,0xa0,0x49, + 0xe1,0x9a,0xf6,0x79,0x64,0xb6,0xb4,0x31,0xbe,0xbb,0x12,0xfc,0xfc,0xfa,0xb7,0x5f, + 0xfd,0xa9,0x9f,0xf8,0xf8,0xfb,0xbf,0xff,0x6f,0xde,0xff,0xca,0x9f,0xf8,0x89,0x8f, + 0xbf,0xff,0xaf,0xfe,0xcd,0x3b,0x52,0x53,0x5e,0x51,0x3b,0x15,0x78,0x99,0xb8,0xd, + 0x8,0x32,0x5a,0x8c,0x6c,0x35,0xdb,0x59,0x25,0x5b,0x11,0x12,0xe0,0x2f,0x9f,0xb0, + 0x49,0xd9,0xc4,0x81,0xa9,0x6e,0x7e,0xc7,0x39,0x4e,0xf9,0x20,0x35,0xea,0x7,0x8f, + 0xcb,0xd,0x29,0x56,0x8b,0x3f,0xc6,0x50,0x34,0xb0,0x54,0x4c,0x3e,0xb5,0x3,0xbb, + 0x6c,0x13,0x63,0x3c,0x43,0xd1,0x74,0xbf,0xdd,0xee,0x77,0x40,0xa3,0x98,0x9,0x9, + 0x6c,0x36,0x57,0xd7,0x1e,0xc9,0x18,0x6a,0x13,0xb6,0xb4,0x29,0x97,0xc,0xe3,0x73, + 0x1a,0x20,0x71,0xe6,0xac,0xe0,0xd8,0x7f,0x3e,0x90,0x31,0x17,0x44,0xcf,0x20,0x48, + 0x4d,0x6f,0xee,0xa3,0x38,0x5e,0xe5,0xd0,0xd1,0x31,0x60,0xf0,0x84,0x98,0x2a,0xc9, + 0x57,0x55,0x4e,0x24,0x5c,0x38,0x78,0x48,0x80,0x87,0xa2,0xca,0xcf,0x49,0x4c,0x3c, + 0xaf,0x61,0xd4,0xb4,0xd9,0xd8,0x56,0x8e,0xc6,0x1d,0x94,0xab,0x70,0x9e,0x2a,0xd1, + 0xbf,0xcb,0x61,0x9,0xa4,0x44,0x76,0xf8,0x6c,0x38,0xea,0xda,0x7f,0x27,0xd1,0xf9, + 0x1f,0xa3,0xdb,0xd8,0x64,0x3b,0x3a,0xd,0x55,0x6b,0x71,0x37,0x31,0xb0,0x34,0x28, + 0xa6,0x77,0x83,0xc5,0x8f,0x18,0x5,0x5c,0xd2,0xdd,0xec,0x6b,0x8,0x21,0xf4,0x63, + 0x50,0x12,0x7c,0x9,0x3c,0x33,0x6b,0x6d,0x72,0x65,0xf3,0x57,0x9a,0xcc,0x79,0xc4, + 0xc6,0x7e,0x10,0xc8,0xa4,0x85,0x59,0xd0,0xaa,0xf3,0xa8,0x78,0x8e,0xac,0x67,0xb9, + 0x25,0x71,0xa9,0x6,0x56,0xcc,0xe2,0xad,0xea,0xfa,0xa,0x96,0x30,0x77,0x9d,0x91, + 0x48,0xd6,0xc8,0x28,0xb3,0x6d,0xa2,0xfe,0x46,0x26,0x5f,0x15,0x7d,0x16,0xdc,0x46, + 0xc7,0x24,0xeb,0x60,0x48,0x70,0xea,0x3,0x4d,0x12,0x49,0x23,0x56,0x14,0xec,0x81, + 0xeb,0x4f,0xe8,0xa3,0x36,0x27,0xf,0x9c,0x4c,0x10,0x9c,0xf0,0xe0,0x84,0x4b,0x98, + 0x2e,0x37,0x1b,0xca,0xed,0x55,0xd,0x2b,0x17,0x21,0x96,0xb9,0x41,0xe1,0xba,0x4d, + 0x1a,0x10,0xac,0x6a,0xb7,0x3c,0xd,0x27,0xea,0xbe,0x49,0x73,0x3d,0x9,0x11,0x43, + 0x7b,0xe8,0xbf,0xfa,0xc7,0x7f,0xe2,0x43,0xd5,0xbd,0xda,0x7b,0xb1,0x1d,0xa1,0x88, + 0x20,0xfc,0x1,0x83,0x63,0xd1,0xb6,0x94,0xd4,0xc3,0x6c,0x5,0x18,0x6,0x7a,0xa2, + 0x7d,0x62,0xd4,0x50,0x69,0xe1,0x58,0x19,0x70,0x72,0x77,0x4b,0x8,0x3c,0xdc,0x9b, + 0x7a,0x85,0x56,0xbd,0x2c,0xaf,0x98,0x59,0x1e,0x85,0xe8,0x39,0x10,0x8e,0xd8,0xe1, + 0xc5,0x48,0x15,0xad,0xb5,0x54,0x3,0x77,0xb2,0x50,0xb3,0x81,0xfa,0x8c,0xfc,0xd8, + 0x5a,0xbd,0xfa,0xf4,0x78,0x27,0x98,0x55,0x35,0x59,0xb2,0x1a,0xee,0x5b,0x1d,0xaa, + 0x24,0xc,0xa0,0x24,0x6a,0xca,0xc0,0x7c,0xa6,0x3d,0xd0,0x8c,0x1e,0x4f,0x22,0x40, + 0xc,0x55,0x33,0xa4,0x37,0xc4,0xd1,0xbf,0x61,0xba,0x74,0x44,0x8b,0x0,0xad,0xc2, + 0x6a,0xba,0xdc,0xa7,0x2a,0x59,0x91,0x4,0x8a,0x5b,0x9f,0xf4,0xa1,0xd3,0xcf,0x7d, + 0x22,0xad,0xed,0x44,0xcd,0x7f,0x83,0x31,0xf4,0x35,0x21,0xb6,0x9e,0xff,0x46,0xc3, + 0x9a,0xd9,0x95,0xa2,0x40,0x91,0x3c,0x51,0xa,0xa9,0x49,0x49,0x68,0xb5,0x63,0x6, + 0x3f,0x87,0xc9,0x52,0x89,0xed,0x7c,0x43,0xb4,0x1f,0x21,0x9f,0x5b,0xc3,0x2c,0xfc, + 0x3d,0xd,0x74,0x17,0x7d,0x8c,0x24,0x9,0x47,0x25,0x23,0xbf,0xbf,0x7d,0xde,0xa5, + 0x62,0xe8,0xae,0x2a,0xed,0x86,0xd1,0xb4,0x1a,0xd0,0xd7,0xa0,0x9c,0x6f,0xbf,0xf9, + 0xa3,0xff,0xef,0xfd,0x37,0x7f,0xf4,0xff,0xbe,0x77,0x16,0xfd,0x44,0x7e,0x8e,0x69, + 0x17,0xc,0xb8,0x3c,0x30,0xb6,0xc4,0xac,0xac,0xbd,0x2a,0xc,0x63,0xbe,0xd0,0x70, + 0x8b,0xa8,0x57,0xb7,0xdc,0x7a,0xc3,0x4c,0x61,0xf3,0xa,0xa5,0xd0,0x58,0xda,0x14, + 0x92,0xc2,0xa6,0xe1,0xcb,0xf0,0x10,0xd9,0xe5,0x1,0x4d,0x34,0x23,0x3c,0x82,0xf5, + 0xcf,0xc2,0xa1,0xcc,0xc7,0x35,0x14,0x96,0x63,0x9b,0x55,0x1c,0x9c,0xec,0x6d,0xce, + 0x1b,0xe6,0xa1,0x37,0xc0,0x47,0xac,0x6f,0x78,0xb9,0x96,0x90,0x3,0xe5,0x50,0x7, + 0xcb,0x47,0x3f,0xd2,0x80,0x3c,0x6d,0x45,0xa5,0x6a,0x57,0xe1,0x62,0xd3,0x82,0x9c, + 0x24,0x26,0x59,0x2e,0x27,0x1b,0xd5,0x3f,0x92,0x33,0xe0,0x29,0x14,0xae,0xaf,0x1e, + 0x7a,0x56,0x92,0xfc,0xec,0xbd,0xa5,0xcc,0x24,0x70,0xd4,0xf9,0x82,0x8b,0xde,0x60, + 0x83,0x4b,0xbc,0xaa,0x8d,0x70,0x18,0xec,0xd,0xf7,0x8e,0x6f,0xe5,0x60,0x53,0xee, + 0x1c,0xb4,0xa5,0x5f,0x14,0x89,0x51,0x2a,0x38,0x86,0x31,0xf,0xc5,0x37,0x8d,0xfc, + 0x24,0x17,0x15,0x7a,0x1f,0x9f,0x4a,0x8c,0xa,0x42,0xdb,0x63,0xe1,0x4b,0xa6,0x9e, + 0x82,0xd4,0xce,0xa9,0x51,0xcf,0x94,0xdd,0xeb,0xae,0xe4,0x93,0x44,0x20,0xd5,0xb, + 0x5a,0xd0,0x37,0xeb,0xad,0x3e,0x6c,0x79,0x3a,0x9a,0x55,0x3a,0x7,0x6c,0xe3,0x7c, + 0x41,0x96,0xb5,0xb1,0xb0,0x9c,0x3a,0x85,0x79,0x67,0x97,0xce,0x29,0x7,0xea,0xd3, + 0xc6,0xfc,0x9e,0xf1,0x3f,0x6c,0x72,0xa3,0xcb,0x89,0x47,0x1,0x41,0xb9,0x83,0x92, + 0x30,0xd0,0xa4,0x9e,0x73,0x13,0xd3,0xbc,0x1a,0x36,0x13,0x2e,0xef,0x60,0x5b,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x3e,0x55,0x2a,0x61,0x92,0x11,0x6d,0x4,0xea, + 0xb9,0x9f,0xe6,0xa1,0xcd,0x86,0x64,0x90,0xb4,0x0,0x65,0xc6,0x3a,0xc6,0x58,0xaf, + 0xc6,0xf,0x51,0xf2,0xdd,0x20,0x39,0xe1,0x2d,0x8f,0x98,0x1e,0x48,0x16,0x1d,0xe, + 0xf3,0xcd,0x34,0xb4,0x28,0x3,0x1,0x84,0x18,0x59,0xcd,0xde,0x8d,0x39,0x17,0x1f, + 0xee,0x77,0x56,0x98,0xd5,0xa4,0x44,0x79,0xdb,0x56,0xd3,0xa7,0xb5,0x5d,0x79,0xfb, + 0x92,0x89,0x2,0xe1,0x44,0x5c,0xfb,0x6c,0xef,0xa,0x92,0x7b,0x54,0x18,0xba,0xe6, + 0x75,0x32,0x88,0x6c,0x6e,0x75,0x19,0x85,0x17,0x32,0xfd,0x59,0x5e,0x51,0x31,0xd6, + 0xbb,0x11,0xe7,0x20,0x92,0xb3,0xaa,0xf4,0x28,0xa3,0x87,0x74,0x39,0xba,0xbd,0xfd, + 0x28,0xc4,0x4d,0x91,0x4f,0xb7,0x51,0xd6,0xed,0x33,0xe0,0x6b,0x2,0x62,0x70,0x7, + 0x18,0x19,0xb,0x52,0x89,0x51,0x60,0x69,0x96,0x1b,0xd9,0xf7,0x2b,0xa,0x45,0x2f, + 0x9c,0xc6,0xb1,0x2,0x7,0x98,0xd4,0x4b,0x70,0xa2,0x42,0x4d,0x44,0xa,0x1c,0x8, + 0x6,0xa7,0xfe,0xc9,0x89,0xe8,0x10,0x96,0x8e,0x2d,0xc3,0x1f,0x88,0x13,0xa3,0xd3, + 0x1a,0x6,0x41,0x14,0x77,0x28,0x32,0x45,0xaa,0xab,0x43,0xbd,0x47,0x56,0x44,0x83, + 0xbc,0xe,0x54,0xeb,0xaa,0x81,0xd0,0x27,0x87,0x6d,0x54,0x41,0xe4,0xe1,0xbb,0x5a, + 0x9f,0xeb,0x9a,0x7b,0x8f,0x6c,0xb1,0x21,0x46,0xcf,0x6a,0xa8,0x24,0xae,0x60,0xda, + 0x8f,0x4d,0x78,0x27,0xfe,0xd1,0x7b,0xe6,0x13,0x4,0x8a,0x56,0xcd,0x96,0xbb,0x8a, + 0x69,0x5f,0x78,0xfa,0xee,0x80,0x40,0x75,0xc,0xc5,0x12,0x33,0x8a,0x54,0xad,0x90, + 0xcb,0x64,0x9e,0x6d,0x13,0xbc,0x18,0xe,0x52,0xf0,0xb1,0xa3,0xd9,0xc6,0x55,0xcd, + 0x6e,0x82,0xf1,0xce,0xec,0xf3,0x62,0xc1,0xaa,0x5e,0x9c,0xdd,0x2d,0x1c,0xe,0x4, + 0x1d,0x30,0x3e,0x43,0xa1,0x71,0x36,0x98,0x7a,0xcf,0xc4,0x23,0xec,0x38,0xbd,0xba, + 0x70,0xe3,0x46,0xd8,0xa1,0xe,0x23,0x7b,0xf6,0x9e,0xa9,0xda,0x7e,0xa2,0xb5,0xf4, + 0xd9,0x89,0x96,0x46,0x50,0xe3,0xe0,0xb4,0x26,0xaa,0x78,0x25,0xd3,0x1f,0x57,0xef, + 0x67,0xba,0x12,0x5f,0x67,0x1d,0x73,0x3a,0x1,0xa0,0x95,0x53,0x10,0xe9,0xac,0x1a, + 0xf4,0x60,0xed,0xbd,0xd7,0x59,0x3f,0xc2,0x99,0xfa,0x15,0xc6,0x92,0xc1,0xd6,0x6f, + 0x2e,0x71,0xee,0x92,0xcd,0xe4,0x83,0xc4,0x5a,0xa6,0xa2,0x64,0xe3,0xe4,0x8e,0x2b, + 0xac,0x41,0x3c,0xdf,0x41,0x4d,0x68,0x67,0x1b,0x5d,0x23,0x39,0x63,0x7,0x3a,0x1b, + 0xf7,0x32,0x22,0xb1,0x8c,0x67,0x4d,0x7d,0xef,0x35,0x6,0x5b,0x81,0x18,0x96,0xfb, + 0x2d,0xac,0x3d,0x41,0x11,0xf8,0x61,0x90,0x1,0x1d,0x79,0xb4,0xd8,0x75,0x8b,0x84, + 0xb9,0xd6,0xcd,0x83,0x16,0xc1,0x92,0x51,0xc6,0xe8,0xac,0x9f,0x7d,0xd8,0x62,0x69, + 0x8a,0x58,0x30,0xd,0x79,0x1b,0xc3,0xce,0xe1,0x76,0x2b,0x3a,0xa3,0x2d,0x57,0xcf, + 0xd8,0x1a,0x6b,0x8,0x8a,0x59,0xe4,0x88,0x53,0x4f,0xf3,0xbe,0xfc,0x72,0xd1,0x65, + 0xe4,0x9d,0x9d,0x89,0x37,0xfc,0x3b,0x30,0x16,0x85,0x47,0x2b,0x52,0xf5,0x8c,0xe6, + 0x94,0xb1,0xd7,0xec,0xcb,0xbe,0x76,0xda,0x55,0x2a,0xf4,0xd2,0xc4,0x42,0xc2,0x19, + 0xad,0x30,0xa8,0x2e,0x65,0x11,0x79,0x12,0x55,0x57,0x21,0x82,0x14,0x1,0x88,0xd1, + 0x27,0x2b,0x8,0x93,0x1,0xcb,0x74,0x90,0x60,0x13,0xf4,0xa0,0x8d,0xd4,0x49,0x5, + 0x45,0x9d,0x4f,0xe5,0x62,0xb9,0xbb,0x93,0x1a,0x5a,0x16,0x3a,0xb,0x79,0xdc,0xd0, + 0x5d,0x85,0x1f,0x3a,0x75,0xfe,0x37,0xe6,0x7c,0x65,0x12,0x87,0x91,0xcc,0x70,0x1a, + 0x39,0x14,0x3d,0x67,0x17,0x1a,0xe1,0x46,0x81,0x88,0x30,0x6d,0xa1,0x5,0xb9,0x76, + 0xa8,0x86,0x67,0x1a,0x2b,0xc9,0xa1,0x5a,0x9,0x8a,0x4d,0xc9,0xfa,0x8e,0xe,0xe2, + 0xb9,0x38,0x88,0xf4,0xee,0x9a,0xa,0x5b,0x27,0x11,0xba,0x9b,0x76,0x26,0xb9,0xc3, + 0x7c,0x9,0xd0,0xd,0x92,0x4e,0xaa,0x77,0xe8,0xcc,0x21,0x41,0x6b,0x6d,0x4c,0xa9, + 0x7,0x56,0x6d,0xf3,0x98,0xa5,0x45,0x5b,0xa7,0xb3,0x20,0x6,0x9a,0x3c,0x6,0x6b, + 0x16,0xce,0x40,0x73,0x91,0x13,0xbe,0x83,0x28,0x51,0x3a,0x28,0xd5,0x4d,0x67,0xdc, + 0x23,0xa,0x65,0xaa,0x62,0x5a,0x11,0x9a,0x8b,0xd8,0x17,0xdf,0xa0,0x4b,0xa4,0x6c, + 0xe3,0x9c,0xd5,0x56,0x64,0x8e,0x47,0xd1,0x46,0x49,0xd7,0x3c,0xf0,0x1a,0xed,0xdc, + 0x1a,0xe3,0x4b,0xf0,0x85,0x15,0xd6,0xab,0xdc,0xd5,0xbd,0x7c,0x7e,0xf7,0x4f,0xd8, + 0xeb,0x7d,0x35,0x1b,0xa9,0xcf,0x83,0x36,0xee,0xd7,0xc4,0xba,0xd4,0x3c,0x27,0x41, + 0xbe,0xd2,0x56,0x75,0xe,0x8b,0x71,0x3f,0x31,0x66,0x30,0x76,0x32,0x6c,0xb5,0x29, + 0x62,0x17,0x5f,0xb1,0x16,0x2d,0xd9,0x85,0x99,0xaa,0x8b,0x56,0x1a,0x1e,0x72,0x7, + 0xc2,0x55,0x99,0xaa,0x1e,0x82,0x55,0xb7,0xbd,0x8,0xa1,0x4c,0x5c,0x28,0x6f,0x9, + 0x83,0xa3,0x61,0x6a,0x1a,0x18,0xa9,0xf3,0xb3,0x8e,0x45,0xd3,0xe0,0xa1,0x37,0x10, + 0x65,0x31,0xb5,0xd3,0xcb,0x8e,0xfa,0xa6,0x42,0x89,0xaa,0xcb,0xfd,0x1e,0xb2,0x2f, + 0x8f,0x42,0x33,0xb7,0xb9,0x6,0x69,0x9f,0xde,0x5b,0x8a,0x4c,0xa2,0x33,0x15,0x85, + 0xdd,0x3d,0x31,0x35,0x5b,0xcb,0xee,0x40,0xfb,0xaf,0x63,0x91,0xde,0x24,0xaa,0xa0, + 0x2a,0x1e,0xa,0x1,0x89,0xa6,0xfc,0xd8,0x4b,0x10,0xb6,0x8,0xc,0xdb,0xda,0x9e, + 0xd5,0xa0,0x54,0xc2,0xdc,0x9a,0xe4,0xd6,0x97,0x2d,0x81,0x7f,0x90,0x69,0x99,0x88, + 0x98,0x4,0x8d,0xd2,0xad,0x3e,0x21,0xc4,0x25,0x2c,0x28,0x96,0xe8,0xee,0xe5,0x5e, + 0xa0,0xfb,0x7c,0x2d,0x75,0xf6,0xbe,0x5c,0x6f,0x9e,0xd0,0xa9,0x1c,0x84,0x9a,0xde, + 0x43,0x9a,0xa3,0xa9,0x0,0x6e,0x5b,0xd0,0xe4,0x29,0xc,0x3d,0xf3,0x56,0xa9,0xb9, + 0x97,0xdc,0x34,0xf3,0x5d,0x82,0x4c,0x60,0x79,0x77,0x47,0xe5,0x75,0x75,0xf4,0xa4, + 0x79,0x8,0x20,0x60,0xb6,0xab,0xc3,0xc2,0x7a,0xed,0x3c,0xa1,0x28,0x98,0xaa,0xc4, + 0x94,0xff,0x71,0x55,0x32,0xd7,0xb3,0x77,0x6,0x6b,0x61,0x4f,0x7f,0x30,0x5b,0xcb, + 0xca,0x3,0xb1,0x56,0xf3,0xfd,0xfa,0x1b,0x1,0x59,0x28,0x2,0xf6,0x75,0x67,0xb5, + 0xc7,0x8,0xc6,0xd6,0x65,0x2a,0x17,0x42,0x51,0x1c,0xb7,0xad,0x46,0xe9,0xd,0x33, + 0x7b,0xbb,0xad,0xf5,0xd6,0x47,0xf4,0x8c,0xe0,0x39,0xea,0x79,0x23,0xd8,0xd7,0xca, + 0x8a,0x46,0x64,0xb3,0x10,0xb6,0x3f,0x7c,0x9f,0x8b,0xf8,0x8d,0xc5,0x4,0x61,0x58, + 0x3f,0x63,0xb4,0x18,0xb4,0xe0,0x97,0xfc,0x6b,0xec,0x2b,0x42,0x2c,0x2a,0x49,0x4f, + 0xa2,0x4c,0xf7,0xa0,0xcf,0x31,0xaf,0xdd,0x3b,0xcc,0x44,0x43,0x84,0x5b,0xb4,0x4f, + 0x31,0x55,0x62,0xd0,0x16,0x89,0xf0,0x5d,0x5c,0xfb,0x3,0x3e,0x8d,0x21,0x95,0xf2, + 0x0,0x29,0x78,0xd5,0x59,0x83,0x97,0xf7,0x40,0xbe,0x63,0x55,0xe3,0x41,0x0,0x75, + 0x14,0xff,0xd2,0x18,0xd0,0x49,0x62,0x3,0xd9,0x2f,0x39,0x2d,0xed,0xd8,0xef,0xdc, + 0x8e,0x2f,0xe,0x2b,0xd6,0x1e,0xc1,0xcb,0xe0,0x31,0x73,0x16,0x6b,0xbe,0xa2,0x3a, + 0xd1,0x24,0xd3,0x3d,0x70,0x72,0xd3,0xb6,0xdf,0xfc,0x8a,0x68,0x39,0x21,0xc8,0x39, + 0x81,0x31,0x81,0xc6,0xac,0x98,0xf0,0x38,0x78,0x35,0xc8,0x6d,0x78,0xd3,0xbe,0xc0, + 0xc6,0xf8,0x4b,0x5c,0xac,0xe0,0x7d,0x19,0x73,0xbc,0xf1,0xea,0x5a,0x33,0xcc,0xc6, + 0xe4,0x92,0x8a,0x74,0x67,0xfd,0xb4,0x43,0xd7,0xe,0x62,0xb1,0x46,0xdd,0x45,0x9b, + 0xbe,0x9e,0x16,0x5c,0x19,0xbd,0xc,0x6,0x92,0x10,0xc4,0xe1,0x26,0x38,0x82,0x71, + 0xa1,0xba,0x9f,0xb0,0x4b,0x40,0x96,0xbb,0x5f,0x5d,0xfe,0x81,0x3a,0xc7,0xdd,0x24, + 0x52,0x87,0x76,0x6d,0xf6,0x64,0x18,0xfa,0xcf,0x59,0xd1,0x30,0xc9,0x4f,0xd0,0xbc, + 0x9a,0x23,0x58,0xb0,0x9c,0x69,0x3f,0x3d,0xab,0x27,0x77,0xd5,0x9e,0x2c,0xd9,0xaf, + 0x97,0xec,0xfe,0x93,0x56,0xb,0x93,0xec,0xa7,0x9,0x1d,0xd8,0x7a,0x28,0x9f,0xb5, + 0x5e,0x9f,0x7f,0x99,0xf6,0x96,0xe9,0x70,0x21,0x7e,0x8d,0xf8,0xbd,0x6f,0x6b,0x5e, + 0xbd,0xe6,0x9c,0x92,0xa8,0x32,0x1,0x94,0x85,0x26,0xf4,0xfb,0x5d,0x22,0xaa,0xc2, + 0xe5,0xd,0xaf,0xba,0x14,0xca,0x86,0xa7,0x99,0xdf,0xe8,0xeb,0x50,0x3d,0x29,0x58, + 0x2e,0x86,0x41,0x90,0x82,0x59,0xfb,0xd2,0x5f,0xd7,0xec,0x72,0x45,0x86,0xf7,0x66, + 0xdf,0x82,0xbd,0xa5,0xc4,0x84,0xe7,0xe,0x20,0x2e,0xa3,0xc2,0x59,0x5a,0xd5,0x6, + 0xd4,0x28,0x9b,0xde,0xef,0x29,0x6,0x32,0xac,0x5,0x58,0x3a,0x7f,0x9,0x8c,0xd9, + 0xe6,0x9a,0xcb,0x94,0x1c,0xa0,0xb0,0xea,0x3a,0xd4,0xff,0x1c,0xf3,0x68,0x4c,0xad, + 0x76,0xbf,0xf3,0xba,0x1b,0x1,0x18,0x7,0x74,0xb2,0xf0,0x8d,0xb1,0xad,0x93,0x69, + 0x8c,0x26,0xbd,0x4f,0xa2,0x70,0x19,0x6a,0xf4,0x75,0xc9,0x57,0xe7,0xff,0x44,0x4b, + 0xc,0x13,0x11,0xc1,0x7e,0x1f,0x7,0x72,0x48,0x85,0x1f,0x7b,0xd,0x4,0xce,0xd6, + 0x2c,0xad,0xa3,0x3d,0xe3,0x2,0x1d,0x7,0xe7,0xb8,0xd6,0x24,0x57,0x2e,0x8,0x9a, + 0xec,0x6a,0x83,0xc,0x28,0xec,0x93,0xe9,0xfd,0x4b,0xdc,0x9,0x33,0x19,0xc6,0x44, + 0x6f,0xa2,0x47,0xcd,0xcd,0xad,0xd8,0x49,0x9d,0xaa,0x19,0x9d,0xf8,0x77,0x30,0x7e, + 0x51,0x23,0xbb,0x85,0x25,0xe9,0x8a,0x95,0x64,0x8b,0x13,0x3b,0x39,0x7b,0xe2,0x5a, + 0x4a,0x4a,0x63,0x44,0xc7,0xa9,0xfb,0x6,0x94,0x49,0xb3,0x9d,0xa0,0x2f,0x25,0x43, + 0xd4,0xa3,0xe5,0xde,0x9d,0xba,0x42,0x6b,0xa1,0x29,0xfc,0x22,0x82,0xe5,0x2a,0x74, + 0xaf,0xe7,0x50,0x42,0x64,0x7c,0xd9,0x37,0x62,0x48,0xc,0xe,0xdf,0x85,0xd0,0x7d, + 0x4e,0xd3,0x2,0xe,0x1,0x4b,0xf5,0xc6,0x1d,0xc7,0x6e,0xac,0x8b,0x54,0xd8,0x52, + 0x7b,0x52,0x68,0xf0,0x5a,0x5a,0xdd,0x65,0xa4,0x3d,0x36,0x76,0xf0,0x10,0x48,0xd, + 0x4a,0xee,0x4a,0x7c,0x4f,0xcf,0x9,0x74,0xc,0xbf,0xaf,0xb1,0xc9,0x12,0x14,0x36, + 0xd,0xa2,0x35,0x9b,0x2e,0x2e,0xa3,0xc7,0xdd,0x89,0xda,0x26,0x2,0x6d,0xb3,0x1a, + 0xdd,0x6c,0x34,0x62,0x22,0x4d,0xeb,0xff,0x49,0xf4,0x1e,0x92,0xc6,0x13,0x68,0x97, + 0xbe,0x30,0x5,0x3a,0x6a,0x68,0xb,0xcd,0x98,0x86,0x41,0x26,0xd9,0x89,0xd0,0x86, + 0x9b,0xba,0xd3,0xd5,0xde,0x5e,0x14,0x74,0x6,0x6a,0xb0,0xc3,0xf0,0x92,0xc6,0xe0, + 0x43,0x1c,0x8a,0x79,0x86,0xa8,0xb0,0x4f,0x37,0x6f,0x98,0x11,0xcb,0x16,0x78,0xdd, + 0x6b,0xd3,0xf3,0xde,0xd5,0x18,0x81,0x46,0xe,0xc5,0xc1,0x70,0x6,0x3,0x92,0xc4, + 0x51,0x84,0x3,0x67,0x4a,0x48,0xdc,0xa7,0xb9,0x47,0x1c,0xd6,0xab,0x90,0xf5,0x3e, + 0xb1,0x72,0x83,0xf0,0xe6,0x24,0x50,0xe,0xac,0xd2,0x53,0x35,0x77,0xe0,0xcc,0x34, + 0x73,0x22,0xca,0xdc,0x2e,0xc7,0x19,0x66,0xf,0x56,0xf7,0xbf,0x5e,0xd8,0xd6,0x9a, + 0x72,0xe8,0xa1,0x9d,0x2e,0xaa,0xb2,0xc5,0x81,0xfc,0x3a,0xb5,0x4d,0xd8,0x3,0x5b, + 0xd,0x41,0xcb,0xfa,0x74,0xbd,0xdd,0x66,0x4f,0x85,0x9c,0x7,0xbf,0xd0,0x94,0xe4, + 0x2d,0x9,0x1b,0x18,0x70,0x23,0xb7,0x68,0x43,0x88,0xd2,0xbe,0xa2,0xf3,0x1e,0xb6, + 0x40,0x1d,0x85,0x27,0x11,0x4,0x2d,0xd1,0xa8,0x6f,0x6d,0x2a,0x6d,0xb2,0x21,0xda, + 0x33,0xec,0x3d,0xff,0xf1,0xdc,0xe2,0x4e,0xda,0xf9,0xa2,0x74,0xb6,0x73,0x8f,0x11, + 0xbb,0x29,0xed,0xb8,0x64,0x10,0xca,0x6b,0xec,0x98,0x5,0x1a,0x9f,0x6f,0x52,0x3b, + 0x65,0x8a,0xee,0xc9,0x33,0x77,0x26,0xba,0x7,0xf8,0x47,0x35,0x91,0x60,0xe2,0x96, + 0xed,0x77,0x8e,0xce,0x17,0x83,0x73,0xa9,0xdd,0x43,0x30,0xac,0x59,0xd0,0x54,0xc4, + 0xab,0x4f,0x2f,0x4d,0xba,0xc3,0xc1,0xb4,0x4,0x4c,0x19,0xaa,0x13,0xb8,0x2,0x3a, + 0x7a,0x22,0x7f,0x72,0x62,0xd4,0xf5,0x47,0x93,0xa,0xb,0xc0,0x34,0x42,0x46,0xa7, + 0xde,0xa,0xa9,0x82,0xcf,0xcd,0xa4,0x8f,0x93,0x84,0x9d,0x1e,0x51,0xe5,0x63,0x48, + 0x1d,0xa7,0xe1,0x41,0x15,0x9,0xe5,0x95,0xc,0x9a,0x8a,0x1d,0x83,0x9d,0x9b,0xda, + 0xde,0x41,0xc6,0x8b,0xe6,0xfd,0xba,0x2f,0x39,0x93,0xad,0x57,0xc5,0xcd,0x70,0x5f, + 0x84,0xe,0x61,0x81,0xef,0xb1,0x10,0xae,0x8c,0x33,0xb9,0x34,0xfc,0xdc,0x56,0x84, + 0x34,0x61,0x99,0xde,0xf,0xb2,0x8a,0x8c,0xd5,0x82,0xae,0x8d,0x74,0xa4,0x42,0xb7, + 0xe9,0xf,0xd0,0x2,0xa0,0x8f,0x93,0xe0,0x4c,0x60,0x4f,0x91,0x8f,0x66,0xb9,0xd9, + 0x3f,0x82,0x26,0xe0,0xdf,0x95,0xad,0x3c,0x5e,0x42,0x66,0xd5,0x27,0x5b,0xda,0x67, + 0x4c,0x2c,0x62,0xeb,0xe5,0x1d,0xfb,0x2f,0x96,0x6d,0x9d,0x4f,0xa8,0x81,0xd0,0x54, + 0x46,0x3e,0xac,0xc1,0xfe,0x76,0x78,0x1f,0x9a,0x26,0xdc,0x71,0xac,0x70,0x2a,0x3, + 0x47,0xd,0x87,0x69,0xa4,0x8d,0xdd,0x9f,0xc0,0x2a,0xc4,0x94,0xae,0x4d,0x21,0x17, + 0xd5,0xf4,0x4f,0xb1,0x3,0x3d,0x5,0x9,0x63,0xc8,0x1f,0xd7,0x3,0x7d,0x4e,0x99, + 0xa2,0xa5,0x81,0x81,0xef,0xe2,0x15,0xa5,0x4c,0x0,0x88,0x1,0x0,0x86,0xa0,0x6b, + 0x49,0xca,0xfa,0x2e,0x58,0x42,0xa7,0x7,0x17,0x74,0x42,0x45,0x26,0x58,0x9a,0xd0, + 0x13,0x64,0xbe,0x5e,0x21,0x58,0xc2,0x24,0x66,0xab,0x5,0x73,0x1f,0x99,0x6b,0x3a, + 0xe0,0x21,0xc,0x54,0xc0,0x30,0x62,0xb5,0xa3,0x17,0xdb,0xd4,0x86,0x13,0x7e,0x31, + 0xc8,0x5b,0xf6,0xb9,0x73,0x74,0x5b,0x17,0x11,0x58,0xd2,0x9f,0x99,0xfc,0x26,0x86, + 0x68,0x99,0xef,0x86,0xcb,0x68,0x9f,0xc9,0x19,0x55,0x32,0x1d,0x63,0x88,0x1e,0x96, + 0x83,0x46,0xab,0xf4,0x30,0x39,0x31,0x11,0xab,0xb7,0xf7,0x85,0xec,0x47,0xf8,0xb4, + 0x2,0x13,0xad,0x28,0xdc,0x2d,0x45,0x29,0x92,0xef,0xb,0xfa,0xdb,0xbf,0xf7,0x7, + 0xef,0x7f,0xfb,0xf7,0xfe,0xe0,0x1d,0x4d,0xbb,0xc5,0x45,0x5d,0x9,0x37,0xdd,0xd5, + 0xb6,0x27,0x1b,0x5f,0xf1,0x2b,0xa1,0x79,0xdb,0x22,0x17,0x32,0xf4,0xce,0xb8,0x1, + 0x7c,0xb2,0x81,0x1,0xbe,0x23,0xad,0xb7,0xd5,0x24,0x74,0x15,0x6,0x64,0xdc,0x84, + 0xc8,0xbc,0x55,0x29,0x4b,0x39,0xbd,0xc,0xbf,0x71,0x25,0x68,0x6c,0xa4,0x45,0x8c, + 0x44,0x98,0xc2,0x2,0x1c,0x98,0x8,0x74,0x62,0x92,0x90,0x4c,0x10,0xf0,0xdf,0xa4, + 0x82,0x96,0xc6,0x24,0x2c,0xc,0x8,0xdc,0x94,0xc5,0xd,0xca,0x48,0x47,0xf2,0x0, + 0xa6,0x6f,0xbb,0x2f,0xf7,0x6a,0x50,0x3e,0xe3,0xad,0x7f,0xeb,0xf7,0xfe,0xf5,0x7b, + 0x55,0xd5,0x6f,0xfc,0xe9,0x9f,0xfc,0x68,0x99,0xa3,0x1d,0x94,0x93,0x5,0xac,0xf2, + 0x2d,0xbc,0xc7,0xb6,0x8d,0xde,0xae,0x1a,0xf4,0x53,0x87,0x8a,0x2e,0x1b,0xdb,0xec, + 0x3d,0x28,0x76,0xff,0x5e,0xa4,0x16,0xbd,0xb1,0x62,0x67,0xb2,0xcf,0x44,0x1e,0xfb, + 0x12,0x5c,0x99,0xe6,0xf,0x39,0x40,0x87,0xb9,0x5e,0xa6,0xd9,0x25,0xaa,0x59,0xf2, + 0x46,0x70,0x74,0x9f,0xb0,0x6,0x28,0x28,0xe0,0xa4,0x4a,0xb2,0x63,0xc0,0x78,0x49, + 0xc6,0xa,0x82,0xcd,0x53,0x1,0x58,0x91,0xd9,0x2,0xae,0x4b,0xd8,0x21,0xd6,0xa1, + 0x69,0xa3,0x3,0x73,0x33,0x48,0x6d,0x88,0x1b,0x34,0xcd,0x2d,0xff,0x1c,0xfa,0x0, + 0xc5,0x72,0x19,0xd7,0x48,0x22,0x58,0x8e,0xa0,0x21,0xc6,0xc6,0x46,0x5e,0x6d,0xc2, + 0xe2,0xc3,0x18,0x15,0xab,0xe5,0xc5,0xa6,0x42,0x49,0xd5,0x37,0xf,0x33,0x42,0x1e, + 0x12,0xad,0xfd,0x6c,0x91,0x9c,0xae,0x16,0x6c,0x29,0x3c,0x1e,0x88,0x45,0x27,0x1b, + 0x45,0xb3,0xda,0x8,0xe4,0x71,0x82,0xac,0xba,0xad,0x2d,0x17,0xf9,0x4e,0xf7,0x13, + 0xa5,0x90,0x48,0x2c,0x90,0x87,0xa2,0x1e,0x4e,0xc2,0xd3,0x35,0x3d,0xd0,0x41,0x93, + 0x3,0x12,0x94,0xd7,0x46,0x5e,0xa5,0xb6,0xdb,0xd0,0xa9,0xa0,0x76,0xf,0xc8,0xb6, + 0x77,0xd7,0xe7,0x87,0x98,0x8,0x84,0xec,0xfb,0x54,0xf9,0x10,0x4b,0x5b,0x6b,0x67, + 0x2a,0x32,0x69,0x73,0x9f,0x83,0xc5,0x75,0xdc,0x7d,0x72,0x22,0xcf,0x6d,0x2e,0x92, + 0x12,0xc7,0x73,0xdb,0x2b,0xc2,0xb2,0x12,0x28,0xdb,0xaf,0x8f,0xb0,0xd8,0xfa,0x25, + 0xc3,0x8c,0x4e,0x47,0x3c,0x60,0x14,0xc2,0xdd,0xde,0xbc,0x72,0x31,0xaa,0xab,0x55, + 0x77,0xc6,0xec,0xd9,0x3e,0x35,0xb3,0x8a,0x2,0x82,0x51,0x7d,0x27,0x29,0xce,0x9d, + 0x74,0x3a,0x31,0x1d,0x28,0xa7,0xf3,0xc7,0x8,0x47,0xeb,0xdb,0xa9,0x44,0xe5,0xf0, + 0x1d,0x4a,0xcc,0xa8,0x20,0x9d,0xad,0x2c,0xf5,0xaa,0x81,0x6c,0x30,0x8f,0x88,0x4d, + 0x89,0xf1,0x28,0x82,0x30,0x54,0xdc,0x7,0xa,0x47,0x40,0xf8,0x75,0xf6,0x8,0xb7, + 0x54,0x13,0xbd,0x33,0x79,0xb3,0x33,0x7f,0xe3,0x3f,0xf9,0xc9,0x8f,0xbf,0xf9,0x2f, + 0xbe,0x2,0xbb,0xb3,0x36,0x3d,0xeb,0x7e,0x66,0xd3,0x4d,0xa5,0x88,0x5d,0x20,0x5, + 0x2a,0x1b,0x85,0x10,0x57,0x99,0x30,0x41,0x81,0xb3,0x73,0xd4,0x68,0x33,0xb1,0xd0, + 0xe1,0xa1,0xce,0x4,0x14,0x94,0x9c,0xfe,0x6c,0xe0,0x6a,0x6b,0x48,0xa7,0xa7,0x51, + 0x15,0x4b,0xe5,0x8c,0x31,0x8c,0xcf,0xb1,0xba,0x58,0x9,0xa3,0x82,0x44,0x53,0xfc, + 0x82,0x9,0xa0,0x8,0xa1,0xf4,0x64,0x6a,0xa1,0xf7,0x56,0x2a,0x4e,0x34,0xab,0x5a, + 0x58,0x9e,0xd1,0xb6,0x23,0xa6,0x11,0x29,0x34,0xa2,0x88,0x8e,0xc0,0xfa,0x60,0x47, + 0x30,0x75,0xd9,0xa5,0x2e,0x51,0x68,0xf2,0xc4,0xcf,0x28,0x5b,0xe7,0xad,0xc2,0xd8, + 0xf9,0x10,0xd4,0xa2,0x82,0xb8,0xa9,0x48,0x52,0x93,0x57,0x45,0x1f,0x7d,0xcb,0x19, + 0x42,0xd6,0x96,0x10,0x16,0xba,0x6f,0xa0,0x8c,0x8,0x32,0xea,0xbe,0x8a,0xed,0x1, + 0x90,0xfa,0xec,0x6c,0xda,0xec,0x49,0xee,0xf3,0xe0,0xee,0x6,0x20,0x84,0x5f,0x7f, + 0x6a,0xf8,0x69,0xe0,0x72,0xf4,0xcb,0x7d,0x1c,0x86,0x93,0x64,0x8d,0x16,0xd2,0xe4, + 0x74,0x77,0xc8,0xa7,0xa0,0x5,0x3e,0x51,0xe1,0x63,0x87,0x86,0x22,0xaa,0x2,0x1a, + 0xd1,0x84,0x98,0x4c,0xd5,0xc,0xc2,0xa3,0x51,0x92,0x1d,0x68,0x91,0x47,0xe7,0xb3, + 0x61,0x16,0xbd,0x58,0xe2,0x39,0x3a,0x79,0xa0,0xea,0x98,0xf,0xda,0xa,0x51,0x57, + 0x54,0x12,0xe4,0x4a,0x50,0x99,0x28,0xcd,0x24,0x47,0x85,0xd8,0x1f,0x5f,0xa8,0x9d, + 0x12,0x16,0x91,0x64,0xb5,0x1b,0x61,0x7b,0x2a,0x74,0x6d,0x13,0x90,0xae,0x84,0x69, + 0xa2,0x66,0x4a,0x94,0x5,0x6e,0xde,0x4,0xec,0x5c,0xe6,0xa7,0x17,0x4e,0xd0,0x6b, + 0xa0,0x4c,0xaa,0xa2,0xa3,0xdd,0x14,0x12,0x6d,0xe6,0xd8,0x17,0xaa,0x86,0xfe,0xe4, + 0xc,0xcd,0x4d,0x55,0xe4,0x8,0x53,0x17,0x86,0x5e,0x61,0xe6,0x77,0x68,0x3d,0xbf, + 0x3e,0xea,0x16,0x96,0x82,0x93,0xee,0x6f,0x25,0x85,0x3f,0xa1,0xc9,0xea,0xf3,0xb4, + 0x4d,0x2,0x53,0x25,0x3e,0x67,0xef,0xf3,0xa1,0xd1,0xd6,0xe6,0xd3,0x4d,0x93,0xd7, + 0x74,0xcb,0x6b,0x8d,0x87,0x99,0x2d,0x5f,0x88,0xcf,0xa8,0xf4,0xaa,0x8e,0xb0,0x21, + 0xc,0x14,0x40,0x1f,0xf5,0x6a,0xaa,0x58,0x88,0xea,0x8b,0x9e,0xc8,0xb0,0x37,0xfa, + 0xeb,0xaf,0xfd,0x99,0x9f,0xfa,0xf8,0x1b,0xff,0xfc,0xf,0xde,0x33,0x63,0x6e,0x12, + 0x95,0x8,0x2,0xa4,0x5d,0x27,0x3a,0x74,0x68,0xb3,0x9d,0x7,0x16,0xaa,0x6d,0xa2, + 0xb9,0x4c,0x1,0xdd,0x8c,0x4,0x9,0x1b,0x46,0x2f,0xac,0x12,0xb6,0x43,0xb0,0x68, + 0x85,0x88,0x62,0x88,0xcf,0xa4,0xdd,0x1f,0xf0,0xa2,0x1e,0xc,0xd9,0x91,0xde,0x1, + 0xe3,0xf2,0xa0,0x34,0xc2,0xeb,0xbe,0x19,0xd9,0x12,0xe9,0x40,0x86,0xae,0x9e,0x88, + 0x6a,0x32,0xfc,0x4,0x36,0xfd,0xae,0x9d,0xa0,0xa2,0x21,0x4f,0xbd,0xe5,0xa5,0x3d, + 0x3e,0x9,0xdc,0x10,0x83,0x96,0x6c,0xc7,0x0,0x2d,0x75,0xde,0x76,0xa3,0x1c,0x12, + 0xff,0xa4,0x32,0xee,0x60,0xf2,0x95,0x20,0xea,0x8c,0xf0,0xcc,0x80,0x46,0xf4,0x41, + 0x9f,0x40,0x82,0x50,0x33,0x34,0xa2,0xed,0xad,0x4a,0x86,0xb0,0xe6,0xec,0xe2,0x20, + 0x82,0x62,0x50,0x66,0x86,0xdb,0xe3,0x63,0x53,0xc6,0x83,0xc8,0x37,0xe7,0x1d,0x58, + 0x53,0x35,0xe8,0x30,0xf0,0x34,0xfb,0xee,0x3e,0x4,0xe9,0x1f,0x31,0x19,0xa7,0x40, + 0xfa,0xc0,0x88,0x33,0xc1,0x3b,0x20,0x4a,0x83,0x80,0xb4,0xba,0x58,0x2e,0xfc,0xc2, + 0x4c,0x56,0x25,0xe1,0x47,0x55,0xb,0x90,0x7e,0xbe,0xea,0xa5,0x5e,0xa1,0x51,0x3e, + 0xe5,0xb6,0x77,0x0,0x1d,0x7c,0x39,0x92,0x8f,0x95,0xca,0x98,0xa,0x45,0xb7,0x20, + 0x8b,0x3,0xb,0x1d,0x62,0xdf,0x8c,0xe4,0x91,0x39,0xc2,0x4a,0x56,0xfd,0xb5,0x3f, + 0xfb,0x27,0x3e,0xfe,0xc6,0x3f,0xff,0xfd,0xf7,0xc5,0x2f,0x2,0x3b,0x64,0xaf,0x48, + 0x2c,0x92,0x1d,0xb6,0x87,0x11,0x39,0x6a,0x81,0x38,0x92,0xab,0x49,0x5b,0x61,0x9a, + 0xf6,0x71,0x72,0x2d,0xd7,0x49,0x87,0x92,0x4c,0xae,0xe,0x76,0x44,0xba,0xf3,0xa9, + 0x8d,0xf,0x27,0x96,0xa4,0x17,0x37,0xb3,0x42,0xd5,0x1b,0x4f,0x87,0xcd,0x82,0xaf, + 0x8f,0xd6,0x2f,0xa4,0x30,0xa6,0xb3,0xdf,0x85,0x4e,0x9e,0xac,0x94,0xc1,0xec,0x82, + 0x6,0xd6,0xd7,0x31,0x4a,0xae,0x3e,0x6c,0x77,0x59,0x82,0x66,0xa2,0xda,0xc7,0xb, + 0x74,0x56,0x21,0x63,0x77,0xa1,0x2b,0x9f,0x5b,0x4d,0xd3,0xb,0xeb,0xc,0xe4,0xc8, + 0x49,0x45,0x3f,0x17,0xad,0x5a,0xb3,0x11,0xa8,0xbb,0xef,0xf3,0xd7,0xff,0xec,0x4f, + 0x7d,0xfc,0xf7,0xff,0xe7,0x1f,0xbc,0x6b,0x4f,0x8,0x8e,0xb8,0xdb,0xbc,0xe5,0x73, + 0x20,0x30,0x7a,0x4a,0x29,0xeb,0x60,0x23,0x3d,0xf6,0xda,0x4b,0xbb,0x36,0x2f,0xff, + 0x83,0xa9,0xb7,0x2b,0x87,0xf2,0x9a,0x1b,0x35,0x3f,0x66,0x8,0x97,0xc3,0xd2,0x52, + 0x63,0xff,0x1b,0x8d,0x10,0xf9,0x77,0xd2,0xfb,0x83,0xc2,0x92,0xba,0x49,0xe8,0xbf, + 0x23,0x7c,0x91,0xfd,0x37,0xf8,0x6c,0xbc,0x12,0xe8,0x9c,0x40,0x4a,0x77,0xa4,0x13, + 0x21,0xb,0x1f,0x91,0x83,0x7,0xb1,0x9a,0xfb,0xe1,0xeb,0x5d,0xd2,0x53,0x35,0x32, + 0xe7,0xd4,0x6a,0x11,0xdf,0x6a,0x9b,0xd1,0x65,0x24,0x6d,0xc2,0xcb,0xd8,0xd2,0xbd, + 0x6c,0xe4,0xcc,0x92,0x20,0xcf,0x1,0xa1,0x5a,0xb2,0xd9,0xd5,0xfb,0x8f,0x7b,0xc4, + 0x53,0xea,0x2a,0xf6,0xb4,0x65,0x18,0xaa,0x89,0x99,0x6a,0x34,0xe9,0x63,0x6d,0xe1, + 0x3d,0x9e,0x1,0xcd,0xa6,0x57,0xc5,0x48,0x6,0x1b,0x4e,0xe8,0x58,0x2b,0xe3,0x79, + 0xab,0x14,0xf8,0xaa,0x98,0x20,0xf7,0xec,0x92,0xdf,0x7c,0x19,0x84,0xb,0xbc,0x36, + 0xd1,0x52,0x7e,0x1d,0xb3,0x6f,0x9c,0xbc,0xa2,0xe,0xb8,0x55,0xd5,0x59,0x49,0x71, + 0x94,0xd2,0x17,0xa4,0x53,0xd1,0xa,0xa,0x70,0xcc,0xca,0x56,0xe4,0x7c,0xde,0x56, + 0xd6,0x2a,0x42,0xd4,0xad,0x13,0xd2,0xa2,0x58,0xc4,0x95,0x9,0x35,0xd7,0xf8,0x5a, + 0x1d,0xdf,0x77,0x2e,0x46,0x11,0xa3,0xb2,0x3d,0xd,0xf,0x3e,0x48,0xec,0xb3,0xe7, + 0xbc,0xfc,0xaa,0xaa,0x9b,0x1c,0xd1,0xe0,0x3e,0x47,0xf3,0xc,0x31,0x8d,0x77,0x60, + 0x55,0xe8,0x91,0xed,0xcf,0xce,0x71,0x29,0x2,0x84,0x89,0x4b,0xb3,0x7f,0xe3,0xa5, + 0x92,0x79,0xdd,0xcc,0x20,0x4c,0xb,0x12,0xf6,0xae,0x59,0xe9,0x88,0x96,0x54,0xb8, + 0x26,0xb1,0x5,0x34,0x9d,0x61,0x36,0x9f,0x5,0xc,0xad,0x3c,0xc,0x44,0xa7,0xae, + 0x95,0xbe,0xc8,0x4c,0x23,0xa3,0x58,0x5e,0x23,0x19,0x2d,0x53,0xf8,0xff,0xb9,0x35, + 0x2f,0xa2,0x11,0x1f,0xc2,0x93,0x28,0x5a,0x55,0xcc,0x18,0xd7,0x10,0xd4,0x70,0x69, + 0x1f,0x13,0xcd,0xdc,0xa5,0xc1,0x71,0x95,0x6d,0x4,0x25,0x2,0x49,0xef,0xcc,0xb4, + 0xf8,0x1f,0xef,0xe8,0xdd,0xc1,0x21,0x37,0x3c,0xc6,0xc6,0xd0,0x2c,0x83,0xbc,0x9c, + 0x55,0x9,0x63,0x5c,0xb7,0x31,0x3b,0xdd,0xe0,0x49,0x3c,0x19,0x18,0xa3,0x30,0xa3, + 0x95,0x44,0x72,0x76,0xa0,0x31,0xc5,0xb5,0x20,0x78,0x59,0x3b,0x6,0x63,0xc3,0xa1, + 0x57,0xa5,0xe5,0xb0,0x1a,0x97,0x94,0xe2,0x46,0x47,0xda,0xd4,0x93,0xb6,0x4,0x9e, + 0x9,0xb,0xb3,0xe9,0x1d,0xac,0x31,0x75,0xd,0xc7,0x28,0xd,0x2c,0xab,0xee,0xc7, + 0xcd,0x24,0x4f,0x4e,0x19,0x49,0x69,0x8a,0xc2,0x8a,0xe4,0x4c,0xbc,0x82,0x70,0x34, + 0xcb,0xa4,0x32,0xd1,0x2c,0xad,0x6e,0x51,0xa,0x61,0xf6,0xb5,0xd,0x35,0xb5,0x71, + 0xd4,0xb3,0x32,0x3f,0x37,0xcd,0x0,0x5c,0x36,0x6e,0x93,0x95,0x2f,0x7,0xb3,0x10, + 0xc6,0xec,0x35,0xf,0x8c,0xfe,0x76,0x78,0xc3,0xcf,0x2b,0x6,0x4a,0xd3,0x7d,0x3, + 0x18,0xf7,0x41,0x90,0x23,0xed,0x77,0x5c,0x61,0x30,0xa2,0xfb,0xe5,0x42,0xc7,0x4f, + 0x4c,0xe2,0x70,0xb0,0xd4,0xc5,0xd0,0xda,0x6a,0xe7,0x2d,0x8e,0xe8,0x67,0x8e,0x3c, + 0x35,0xb5,0xb1,0x46,0x8e,0x1c,0x7a,0xa4,0x71,0xf6,0xe7,0xde,0xde,0x5a,0xfc,0xec, + 0xab,0x3d,0xb,0x40,0x43,0xe7,0xe4,0xb7,0xf0,0xd0,0xfe,0xc2,0x40,0x67,0xcf,0xea, + 0x9a,0xbb,0x95,0xd5,0xc,0x8f,0x46,0x6a,0xd3,0xa0,0x8b,0x72,0xc2,0x13,0xcc,0x91, + 0xaf,0x5f,0xde,0x23,0xd9,0x4c,0xd2,0xe6,0xe1,0x9b,0x49,0x91,0x58,0xef,0xb6,0xe0, + 0xc1,0xdd,0x56,0x23,0x79,0x4b,0xa7,0x77,0x7,0xc4,0x6c,0xb7,0xb5,0x8f,0x38,0x8d, + 0xd9,0xdd,0x17,0xf1,0x56,0x21,0x3f,0xd9,0x44,0x40,0x40,0x99,0xba,0x82,0x91,0xd4, + 0x36,0x97,0x49,0x46,0xb6,0xae,0x7b,0xae,0xd9,0x34,0xbe,0xca,0xc7,0xcd,0xd4,0x12, + 0x31,0x68,0xfa,0xf,0x39,0x4f,0xfb,0x25,0x6c,0xcc,0x0,0x79,0x38,0xd7,0x26,0x33, + 0x40,0x2a,0xaa,0x62,0x97,0x97,0x4,0x3d,0xcc,0xb0,0x92,0x11,0x83,0x57,0xfc,0x5b, + 0x41,0x1,0x42,0x4c,0x1f,0xca,0x86,0x15,0xf5,0xb5,0xf5,0xbd,0xa9,0x81,0xd4,0x15, + 0xee,0x64,0x56,0xae,0xd2,0xb2,0x51,0x33,0x1e,0x68,0xf,0xe7,0xb9,0x57,0x76,0x6e, + 0xec,0xef,0xfd,0xfc,0xdc,0xd7,0xf8,0xfc,0x33,0xf8,0xfc,0x73,0xd4,0xc7,0xd0,0x3f, + 0x67,0xf8,0x55,0x7b,0xd0,0xa1,0x7a,0x43,0x33,0x6c,0x4a,0x28,0xbf,0xe9,0x55,0x42, + 0x54,0x6e,0x3b,0x8b,0x41,0x7,0xda,0x7b,0xf3,0x4e,0xe,0x63,0x9b,0x28,0x72,0xb2, + 0xe4,0x12,0xca,0xe1,0x79,0xca,0x6b,0xcf,0x79,0xc3,0xc8,0x90,0x15,0xc2,0x38,0xe9, + 0x98,0xfe,0xf4,0xe,0x47,0xab,0xc9,0x47,0x66,0xf5,0xe9,0xf9,0x21,0xe7,0x24,0x73, + 0x70,0x8a,0x73,0x6b,0x5d,0xc4,0x44,0x19,0x1,0x5f,0x3f,0x13,0x72,0x5f,0x88,0xd9, + 0x50,0x73,0xa5,0x78,0x57,0xc5,0x1c,0x30,0xaa,0x8e,0xc0,0x21,0xaa,0xd2,0xaa,0x17, + 0x5a,0xa1,0x43,0xf6,0x5e,0x4c,0x5e,0xe8,0x62,0xb1,0x8d,0xc4,0xf6,0x1c,0x63,0x4e, + 0x74,0x26,0x3,0x5,0xdb,0x16,0x3a,0x43,0x9c,0x4c,0x5c,0xd6,0xf9,0x13,0x6c,0x8e, + 0x8a,0x35,0xc8,0x20,0x7a,0xa1,0x96,0x82,0x15,0xc3,0x5b,0xc1,0x48,0x23,0x78,0x26, + 0xcf,0xb6,0x7b,0xd0,0x45,0xfc,0xab,0x26,0x45,0x4a,0x22,0x95,0x74,0x66,0x2,0xea, + 0x7d,0xcf,0xaf,0x87,0xf8,0x77,0x54,0xde,0x1c,0x38,0x2f,0x8d,0xa8,0x39,0x5c,0xbf, + 0x8d,0x64,0x86,0xe4,0x1c,0xd2,0xc5,0x40,0x88,0xc7,0xcf,0x5c,0xb6,0x18,0x33,0x3d, + 0xba,0x4,0xd4,0xea,0xb8,0xcd,0x9f,0xeb,0xfd,0xd8,0x23,0xb2,0xf,0xa2,0xcc,0xc9, + 0x93,0x43,0xaf,0x5,0xe1,0xab,0x80,0x24,0x61,0x96,0x7d,0x66,0x1b,0xce,0xbe,0x3f, + 0xfb,0x39,0x3b,0x3f,0x3f,0x4b,0x66,0xcc,0x3,0xfe,0x8f,0xe0,0xbf,0x13,0x4f,0xf7, + 0x2c,0x61,0xed,0x73,0x96,0x23,0x5c,0xc2,0x7e,0xaf,0x4b,0x55,0x3a,0x7,0xa8,0x45, + 0x1e,0xe1,0x9b,0x4a,0xf3,0x3d,0x15,0x9d,0xd,0xc4,0x43,0xd9,0x7c,0x2a,0xe6,0xc2, + 0xad,0x4d,0x1b,0xb,0x71,0xf5,0xb6,0x28,0xe2,0x19,0x72,0x70,0xaa,0xb0,0xfc,0x13, + 0x10,0xb2,0xd2,0xa1,0xba,0x0,0xa5,0xe2,0x5a,0x8c,0xae,0x6a,0x16,0xbb,0x7f,0xf, + 0xf7,0xdc,0x25,0xfc,0x3b,0x69,0x73,0xea,0x15,0x3e,0xec,0x4a,0x78,0x84,0x77,0x13, + 0xd8,0xf7,0x2,0x22,0x48,0x53,0x66,0x31,0x55,0x94,0x24,0x2d,0x77,0x81,0x39,0xb8, + 0x68,0x25,0x84,0xc1,0xa7,0x97,0x9,0x9e,0xc4,0x5f,0x1a,0xa4,0x18,0x4,0xce,0x87, + 0xa9,0xeb,0xda,0x25,0x77,0x30,0xb0,0xd7,0xc3,0xc,0x77,0x30,0x49,0x18,0xa,0xcb, + 0x1b,0x41,0x91,0x57,0x13,0x9d,0x91,0xd1,0x87,0x66,0xb9,0x33,0xb2,0xa7,0x6d,0x4e, + 0x3f,0x8f,0x68,0x38,0x42,0x3,0x69,0x9,0x2d,0x49,0xdb,0x3c,0x98,0x10,0xf0,0xdf, + 0x93,0x25,0x83,0x4d,0x0,0x68,0x92,0x5,0xf5,0xf5,0xc6,0x70,0x75,0xa0,0xdf,0x9f, + 0x66,0x12,0xc4,0xb9,0x88,0xb0,0x3,0x3c,0x3e,0xd3,0xc6,0xf,0x39,0x1f,0xf8,0x49, + 0xae,0x62,0xa8,0x39,0x98,0x41,0x51,0x36,0x49,0x85,0x86,0xe,0xce,0x63,0x58,0xfd, + 0xd6,0x85,0xc0,0x6,0x66,0x52,0xe8,0x24,0x87,0x9c,0x52,0x9c,0x83,0x30,0x4e,0x47, + 0x4d,0xdd,0x46,0x92,0xa7,0xd7,0x2a,0xab,0x16,0x33,0xec,0xea,0xb7,0x6c,0x9b,0x41, + 0x35,0x4d,0x96,0x71,0xcd,0x4e,0xa2,0x17,0x87,0xf7,0xa4,0xb6,0xf0,0xea,0xef,0x47, + 0xb9,0x90,0x22,0x49,0xec,0x64,0x5f,0xe6,0xf4,0x47,0xbb,0xaf,0xa2,0xfd,0xb0,0xb6, + 0xa5,0xca,0xc9,0xe2,0x3c,0x1d,0x20,0xb2,0xc6,0xe3,0xf4,0x45,0xea,0x87,0xd8,0xcf, + 0xe2,0x88,0x8b,0xb0,0x30,0x24,0xaf,0x88,0xc7,0x43,0x43,0x66,0x3b,0x2f,0x8b,0xc2, + 0x27,0xe1,0x42,0x3e,0x28,0xd7,0xc8,0xb0,0x46,0x62,0x8b,0x1c,0xd2,0xb5,0x56,0x72, + 0xa6,0x3e,0x3,0xb0,0x53,0xb6,0x1e,0x1e,0xc6,0x1d,0xb,0x7f,0xe3,0xff,0xf8,0x57, + 0xef,0x7f,0xf3,0xcf,0xfd,0xc9,0x8f,0x75,0x46,0xea,0x78,0x35,0x5b,0x8e,0xd0,0x4, + 0x9d,0xa0,0x93,0x14,0x52,0x8c,0x94,0x20,0xd1,0x14,0xf5,0x24,0x13,0x33,0xe3,0x50, + 0x9d,0x2b,0xca,0xc8,0x4e,0x39,0x7a,0xcb,0x66,0x7c,0x31,0xab,0x7d,0x34,0x47,0x97, + 0x36,0x57,0x8e,0xbe,0xa7,0x5c,0x93,0x41,0xcc,0x3e,0x47,0xa1,0x1,0x5f,0xac,0x7c, + 0x7a,0x4e,0x53,0xa3,0x48,0x32,0x1,0x6a,0x5,0xc4,0xa,0x21,0x12,0x9a,0x96,0x8, + 0x83,0xa9,0xaf,0xb3,0x7b,0x3d,0x96,0x74,0x61,0x14,0x95,0xb7,0xcc,0x6a,0xd,0xa3, + 0x41,0xd,0xbb,0xb8,0x86,0xef,0xa6,0x6a,0x73,0x8b,0xe0,0xb8,0x10,0x1a,0x76,0x72, + 0xa5,0xbf,0xb0,0x92,0x8a,0x76,0xf0,0xd8,0xae,0x6a,0xdc,0x4a,0x70,0xd8,0xba,0xed, + 0x29,0x22,0xb2,0xd8,0xef,0x18,0xf4,0xf8,0x2d,0xf9,0xa5,0x1b,0xe6,0xc1,0x2b,0xa6, + 0xb4,0x2,0xc4,0xe8,0xd0,0x56,0x75,0xd0,0xd,0xdb,0x30,0x21,0x19,0xc9,0x11,0x9b, + 0xa0,0x91,0xa9,0xb,0xb5,0xbe,0x16,0xe3,0x90,0xcf,0xca,0x2,0xc1,0xa2,0x4b,0xf1, + 0x97,0x6c,0x60,0x4e,0x70,0x76,0x85,0xfa,0xb,0x3c,0xf0,0x85,0x24,0x28,0x2a,0x2d, + 0x7c,0xe3,0x33,0x59,0x7,0xcd,0xca,0xec,0x77,0x60,0xae,0x6,0xa7,0x8a,0x32,0xad, + 0x25,0x25,0x99,0x61,0xd,0x58,0xfe,0x41,0xc7,0x7f,0xa9,0xa,0x62,0xe,0x2e,0x3b, + 0x68,0x69,0x92,0xc5,0x4a,0x39,0xa5,0x3d,0xba,0x29,0xe2,0x52,0x52,0x79,0x15,0x87, + 0x31,0xad,0xea,0xc5,0xb5,0xf7,0xd7,0xd9,0x9a,0xcf,0xe3,0xd1,0xbf,0x8a,0x2f,0x6, + 0x3f,0x85,0x83,0x73,0x5c,0xc2,0xd7,0xbe,0xfe,0x54,0x4c,0x4,0x86,0xfa,0xa9,0xce, + 0x39,0xbd,0x35,0xd9,0xe,0x7b,0xf1,0x6c,0x84,0x4f,0x6f,0xf2,0xd6,0x69,0x30,0xcd, + 0xf4,0xe7,0xcf,0x2f,0x19,0x59,0xc3,0x41,0x63,0x1b,0xf9,0x7c,0xe4,0xf1,0x5e,0x91, + 0xa0,0x5d,0x5b,0xbc,0x4b,0x6f,0xf6,0xbe,0xf,0x8c,0xb9,0xf7,0x5a,0x22,0x3e,0x7a, + 0xaf,0xfc,0x31,0x60,0x40,0x94,0x69,0xd6,0xd8,0x31,0xf9,0xe9,0x6d,0x1d,0x7a,0xdb, + 0x27,0x9f,0x23,0x24,0x1e,0xa8,0xea,0x65,0xa,0xb8,0x20,0xb9,0x5a,0xd8,0xc1,0x77, + 0xf1,0x2b,0x2c,0x29,0xde,0x5,0xe9,0xe6,0x1b,0xe1,0xfe,0xe7,0xc,0x7a,0xb4,0x49, + 0x56,0x55,0xa5,0x2b,0xd7,0x98,0x5a,0x89,0xb2,0x6a,0xc3,0x33,0x25,0xa8,0x85,0xfb, + 0x41,0x71,0x7,0xb5,0x31,0x35,0x8a,0x20,0x58,0xb9,0x30,0xff,0x95,0xc0,0x77,0xef, + 0x49,0x62,0x2e,0xd,0x63,0x90,0x85,0xa1,0x7d,0x8d,0x41,0xe4,0xc3,0x99,0x7a,0x83, + 0xcf,0x2d,0xd0,0x2b,0xa2,0xc9,0xb7,0x7a,0x40,0x1c,0xb8,0xb4,0x93,0x39,0xb2,0x3f, + 0x94,0x44,0x86,0x64,0x13,0xe7,0x77,0x5c,0xf4,0xbe,0x92,0x69,0x1e,0xd3,0xaa,0xee, + 0xc6,0x74,0x1f,0x85,0x3c,0x5e,0xc8,0xbf,0x62,0x78,0x2d,0x12,0xf2,0x8d,0xcf,0x67, + 0x8d,0x15,0x6d,0x13,0x6c,0x90,0x93,0x50,0xb8,0x4c,0xee,0xbc,0xb5,0x60,0xcc,0x90, + 0x5c,0x3c,0x42,0x9,0x81,0x26,0x8c,0xaf,0xeb,0x3a,0xcf,0xdd,0x26,0x1b,0x1d,0xb, + 0xc7,0xd4,0xfb,0xd,0x32,0x8,0x21,0x1b,0xf0,0xe6,0x75,0x2a,0x8b,0x9f,0x43,0x85, + 0x39,0xde,0x33,0xcc,0x53,0x10,0x93,0x7,0x41,0xa2,0xc5,0x19,0xf0,0xa7,0xc7,0x3b, + 0x24,0xc6,0x96,0x77,0xb4,0xb1,0x37,0x77,0x99,0x42,0x1b,0x1b,0xaa,0x26,0x65,0xac, + 0x23,0x77,0xc8,0x8b,0xc4,0x50,0x5d,0x46,0xd2,0xc0,0xf0,0x7c,0x47,0x10,0x4e,0x33, + 0xfc,0x98,0xad,0xb2,0x4e,0x1c,0x0,0x31,0x76,0xda,0x15,0xae,0x66,0xb5,0x3f,0xd, + 0x5c,0x1b,0x95,0x61,0xf3,0x9b,0x4f,0xd7,0xbf,0xcd,0x17,0xd9,0xf9,0x56,0x8a,0xec, + 0xd0,0x68,0x88,0xad,0x25,0x71,0x85,0x30,0x51,0x38,0xf5,0x51,0xb5,0x35,0x86,0x24, + 0xb5,0x9a,0xdf,0x38,0x9c,0x23,0xd2,0x38,0x23,0x35,0x4f,0xe7,0x0,0x83,0x9f,0x8e, + 0x8f,0x3d,0x35,0xb1,0x2f,0xb8,0x75,0x6f,0xca,0x5f,0xdb,0x67,0xb0,0x4f,0x81,0x7e, + 0x5,0x85,0xab,0x27,0x19,0x12,0x50,0x90,0x3c,0x61,0x21,0xa6,0x7a,0xee,0x70,0x35, + 0x6f,0x70,0x5a,0x1c,0xa9,0xe0,0x50,0xc9,0x98,0xb2,0x9a,0xd6,0xc,0x4e,0x86,0xda, + 0x62,0xd2,0x9,0xe,0x36,0x42,0x4f,0xea,0xa0,0x48,0x5f,0x9c,0x49,0x76,0xe,0x69, + 0x6e,0x6d,0x3,0x94,0xa3,0xa,0xb,0x51,0x7e,0xd6,0x3,0x95,0xa8,0x9c,0x52,0xce, + 0x10,0x24,0x82,0xe2,0x7a,0x18,0xb3,0x32,0x50,0xf7,0x36,0x29,0x90,0xe9,0xd3,0x19, + 0x8c,0xb5,0xbc,0xc6,0x42,0x49,0x13,0x61,0x43,0xf0,0x41,0xde,0x7a,0x47,0xb8,0x4c, + 0xe0,0x2,0x1,0x93,0xe,0x14,0xc6,0x1e,0xa0,0xc9,0x5e,0xfd,0x34,0x13,0xe7,0x93, + 0x72,0x15,0xf,0xfe,0xbc,0x43,0x3f,0xd5,0xfa,0xd6,0x26,0x9,0x3c,0x54,0x5f,0x65, + 0x52,0x91,0x99,0x89,0xda,0xdf,0xd5,0xe1,0x92,0x25,0xe5,0xb,0x5b,0xf2,0xd4,0x3f, + 0x19,0x61,0xf4,0x13,0x94,0xd8,0xf6,0x14,0x5d,0x9c,0x23,0x83,0xfc,0xd8,0xa6,0x63, + 0xdf,0xd8,0xfc,0x14,0xd4,0xe3,0xb3,0x4c,0x15,0x6e,0xf7,0xa1,0xf6,0x7b,0x57,0xe6, + 0xc8,0xb2,0x3e,0x55,0x8a,0xfb,0xe4,0xef,0x80,0x40,0x32,0x8f,0x24,0x2a,0xa2,0xa9, + 0xee,0xd2,0x8e,0xb6,0x5b,0xd,0xce,0xd9,0x49,0x59,0x80,0x67,0xec,0x3e,0xf2,0xda, + 0x4b,0xd7,0xea,0x53,0x5d,0xec,0xa,0xd9,0xad,0x76,0x0,0xcb,0xc4,0x37,0x62,0xa2, + 0x60,0x59,0x77,0x42,0xa1,0xbd,0x1b,0x22,0x55,0xe9,0xdb,0x84,0xf5,0xe4,0xf7,0x50, + 0xf4,0xde,0x35,0x30,0x70,0xd8,0x39,0xd4,0xe6,0x8d,0x55,0x6e,0x30,0x13,0xa0,0xa6, + 0x3f,0x18,0x2e,0x75,0xc6,0xc7,0x40,0x47,0x2f,0x8,0xf,0x28,0xd9,0xae,0x54,0x9, + 0x65,0x7b,0x3b,0x53,0x46,0xa4,0x8f,0xda,0x98,0xe4,0xae,0x1c,0x5a,0xde,0xd2,0x45, + 0xe3,0xa2,0x4c,0xd6,0xa4,0x34,0x9e,0x35,0x44,0x22,0xb4,0x4c,0x2,0xdc,0x2b,0x37, + 0x3a,0xaf,0x3,0x7a,0x78,0xc2,0x7d,0xe1,0xc3,0xa5,0x8c,0x48,0x73,0x16,0x36,0x60, + 0x87,0x26,0x20,0x43,0x1f,0x41,0xad,0x6e,0xce,0x46,0x19,0x99,0xa4,0xca,0x3c,0x87, + 0xdc,0x2d,0x52,0x64,0x0,0xe9,0xae,0xb5,0x45,0xaf,0xd2,0x37,0x1,0x21,0x77,0xfb, + 0x8,0xb4,0xec,0x40,0x45,0x63,0xcd,0x27,0x4d,0x9e,0xb6,0x25,0x9f,0x7b,0x98,0x59, + 0x29,0x85,0x17,0x23,0xeb,0x3e,0xd6,0x81,0xee,0x34,0xf5,0xee,0x6,0xd0,0x24,0xbf, + 0xbd,0x4b,0xe1,0x2e,0x79,0xe6,0x15,0x5f,0xa1,0xb3,0x17,0x8e,0x80,0x1b,0x8d,0x75, + 0xfb,0x54,0x8,0xa2,0x82,0x49,0x22,0xd7,0x50,0x50,0x4f,0x5a,0xd7,0x75,0x89,0xc7, + 0xc5,0xaa,0xd6,0xb,0xdf,0x30,0x1a,0x1b,0x32,0x28,0x15,0x36,0xfa,0x9c,0x5a,0xa8, + 0x98,0x35,0xd0,0x1a,0x69,0x13,0x35,0x77,0x2a,0xbe,0x20,0x96,0xab,0x5,0x1b,0x84, + 0xd7,0x2b,0x6,0x48,0xaf,0xa5,0xd8,0xf3,0x1c,0x7a,0x22,0x93,0xc9,0xac,0x6c,0x4a, + 0x7b,0xea,0x94,0x96,0x2c,0x46,0x95,0x96,0xb,0x26,0xe3,0x62,0x78,0x23,0x5e,0xc3, + 0x61,0x74,0xaa,0x79,0x38,0x2b,0x21,0x6b,0x6b,0x1b,0x1b,0x9b,0x16,0x43,0x3b,0x2d, + 0xae,0x15,0x89,0xcd,0xf7,0x39,0xa7,0xaa,0x93,0xe0,0x41,0x1e,0xf6,0x36,0xeb,0x59, + 0x21,0xee,0x80,0xc9,0xef,0xce,0x5d,0xbc,0xb4,0x12,0x7f,0x32,0x47,0x3d,0x5c,0xe9, + 0x99,0x68,0x69,0x2f,0x67,0xe8,0x49,0xa7,0x54,0xad,0xcb,0x8b,0x50,0x24,0xa,0x85, + 0xe9,0xdc,0xe6,0x34,0xbd,0x27,0x6,0x93,0xba,0xd,0xab,0xce,0x8a,0xf9,0x5f,0xcd, + 0xf8,0xb3,0xf7,0x26,0x33,0xd2,0x95,0x58,0x11,0xd2,0xdd,0xce,0x25,0x54,0x39,0xf9, + 0x21,0x97,0xb3,0xb5,0x11,0xdf,0xa3,0xa7,0x20,0xa3,0xa7,0x35,0x3a,0xa1,0x45,0x75, + 0xc2,0xe8,0xe5,0x3a,0x2f,0x49,0x5,0x60,0x50,0x6d,0x4,0x9a,0x3a,0xfa,0x3,0x17, + 0x2e,0x91,0xbe,0x9c,0x49,0xe8,0x72,0xcf,0xe1,0x57,0x6e,0x2f,0x25,0x5,0x96,0xf4, + 0xb5,0x6b,0xf,0x18,0x50,0x89,0x91,0x93,0x66,0x80,0x60,0xc5,0xcc,0x4a,0x5a,0x45, + 0x9b,0xa8,0xf7,0xad,0xa3,0x13,0xa5,0x8e,0x6f,0xf0,0x79,0xf3,0xcd,0xa5,0xe0,0xf6, + 0x49,0xa7,0x1f,0xd4,0x3a,0x83,0x6d,0x92,0xc9,0x4c,0x99,0x91,0x6d,0x8e,0xb1,0xad, + 0xe6,0x7d,0xe2,0x62,0xf3,0x64,0xd5,0x5d,0x31,0xa4,0x49,0xe9,0x42,0x3b,0x8a,0xb2, + 0x2c,0x29,0x53,0x26,0xf7,0x1c,0xe6,0x72,0x98,0xea,0xdd,0x6c,0x7f,0xef,0xe3,0x8b, + 0x80,0x53,0xb0,0xa9,0x6d,0xc1,0xd0,0xf2,0x68,0xeb,0x0,0xf0,0xbd,0xb,0x97,0x41, + 0x1,0xfa,0x24,0x48,0xde,0xcb,0x9a,0x74,0x1,0xe,0x4,0x46,0xea,0x77,0x5f,0x3, + 0xb9,0x71,0xa8,0xf,0xc,0x45,0xdd,0x23,0x5,0x75,0x54,0xf1,0xbd,0x12,0xdd,0x9d, + 0xda,0x6e,0x93,0x49,0xcf,0x14,0xde,0x26,0x77,0x4b,0xd7,0xec,0x60,0xc8,0xe9,0x4e, + 0xb7,0x60,0x98,0x9e,0xb6,0xf5,0xfd,0xdf,0xfd,0xb3,0x1f,0xbd,0xff,0x9d,0xff,0xf4, + 0xa7,0x3f,0xd8,0x1c,0x48,0xe3,0x47,0xc2,0xa7,0x49,0x0,0xe,0x9a,0x20,0x3e,0x12, + 0xf7,0x74,0x63,0x5b,0x96,0x4f,0x4,0xab,0x3a,0xcc,0xe0,0x5b,0x20,0x69,0xc5,0xf4, + 0x30,0x7a,0xf2,0x6c,0x82,0xec,0x2f,0xa6,0xe2,0x59,0xb,0xc0,0x7d,0x68,0xd3,0x42, + 0x23,0xd2,0x80,0x82,0x1e,0xa8,0x7,0xf1,0x5,0x98,0x38,0xc4,0x26,0xd1,0xa1,0x69, + 0xbb,0xc7,0xb8,0x98,0x9,0x56,0x20,0xe6,0x22,0x69,0xc2,0x2e,0x15,0xe,0xc3,0xca, + 0xae,0xcb,0xd1,0x1f,0x86,0x8d,0xa1,0x8a,0x7c,0xf0,0xc5,0xc4,0xe6,0x16,0xe,0x41, + 0x4f,0xd,0xae,0xbb,0xe7,0x73,0xf7,0x30,0x75,0xee,0x51,0x33,0x4d,0x3b,0x50,0x3e, + 0xcb,0x66,0xdb,0x79,0x27,0x77,0x26,0x26,0xc2,0xe8,0x7,0x22,0x49,0x30,0xcf,0x3f, + 0x5c,0xee,0xac,0x17,0x5b,0x66,0xcd,0x3d,0x3f,0x15,0xc,0xa2,0x82,0xa4,0x54,0x78, + 0x7a,0x5f,0x59,0x2e,0x6e,0xd1,0x46,0x4,0xd1,0x4c,0xa9,0x8c,0x30,0xd9,0x2,0xac, + 0x56,0xf,0x2e,0x3a,0x63,0xa,0x65,0xf2,0x7d,0xc,0xa1,0xe,0x87,0x82,0xcb,0xe, + 0xc1,0x74,0xd2,0xd3,0xdf,0x89,0x90,0x3e,0xdf,0x42,0x40,0x31,0xd3,0x4b,0x88,0x58, + 0xc5,0x7e,0xa3,0x8d,0x8e,0x19,0x17,0x5,0x4b,0xe8,0x47,0x2d,0x81,0x95,0xf5,0x41, + 0x4d,0x0,0x19,0xf0,0xa4,0x91,0xdd,0xe0,0xea,0x8a,0xd4,0xea,0x1a,0x1,0x35,0x33, + 0xf4,0xff,0xe9,0x2,0x2e,0x8d,0xe0,0xa8,0xda,0x14,0xb4,0xf5,0x3e,0x77,0xe2,0x94, + 0x71,0xcf,0xb6,0xe6,0xc2,0xe1,0xc0,0x84,0x4c,0x54,0x7a,0xd5,0xfc,0xa7,0x2f,0x84, + 0xe5,0xac,0x27,0x13,0xad,0x25,0xf6,0x7c,0xe0,0xe5,0xc7,0x56,0x79,0xba,0xba,0xb8, + 0x2e,0x68,0x6c,0x66,0xff,0x2e,0xe,0x41,0xe6,0xfc,0x1f,0x44,0x3f,0x1e,0x7,0x52, + 0x7d,0xeb,0x6f,0xc5,0x64,0x1a,0xe,0xa,0x2f,0x7,0x9,0x92,0x76,0x2f,0x2e,0x57, + 0xe8,0x9c,0x2,0x1b,0x4f,0x88,0x5e,0x44,0xba,0x43,0xa0,0xcd,0xd6,0x11,0x62,0xc4, + 0xcf,0x7b,0xd9,0xa7,0x11,0x38,0x29,0x79,0x31,0xb9,0xbc,0xe5,0xf5,0xa7,0x90,0x8b, + 0xf2,0x8a,0x54,0xa7,0x23,0x48,0xa9,0xf4,0xf1,0x3c,0x44,0x3b,0x7a,0x4d,0x4f,0x3c, + 0xae,0x96,0x94,0xcf,0x6d,0xfe,0xca,0xd1,0xb3,0x5b,0xa6,0x39,0x13,0x32,0xc0,0xb8, + 0x3f,0xa8,0x37,0xd5,0xe4,0x7d,0x8,0x16,0x58,0x4c,0x68,0xe7,0x22,0xd3,0xd,0x41, + 0x5,0xce,0xa,0xd8,0x5,0x1c,0x86,0x6a,0x2b,0x88,0x54,0x25,0x96,0x79,0xae,0xe1, + 0xcc,0x68,0xd,0x2f,0x28,0x74,0xcd,0xee,0xd,0xb4,0x54,0x65,0x9,0xca,0xe7,0xf3, + 0x44,0x18,0x9a,0x1a,0x6,0x2b,0xd1,0xb9,0xc4,0x79,0x2d,0xd8,0xfb,0x2d,0x86,0x63, + 0x5b,0xdc,0x71,0x20,0x7c,0x61,0x67,0xf3,0x54,0xeb,0x41,0xc2,0x61,0x29,0xcb,0xa, + 0xbb,0x13,0x54,0x9f,0xdc,0x42,0x93,0x2,0x5f,0x4,0x8f,0x87,0xf8,0xfa,0x29,0x87, + 0xf8,0xa7,0x40,0xc8,0xa,0xb9,0x2b,0x8c,0xf6,0x29,0x35,0x2e,0x44,0xe6,0xb1,0x61, + 0xb2,0xb5,0x74,0xad,0x11,0x9c,0x5,0xf3,0x1c,0xea,0x6,0x57,0xc3,0xc6,0x16,0x62, + 0x94,0x9,0x82,0xac,0x8e,0xaa,0xac,0x43,0x6d,0x87,0xdd,0xf7,0xc9,0xfc,0xaf,0x15, + 0x36,0xa6,0x98,0xb8,0xc8,0xef,0x32,0xa6,0xac,0x6b,0x40,0xab,0xe7,0xbd,0x5b,0x74, + 0xfb,0x41,0xad,0xeb,0x14,0xcd,0xc2,0xcf,0xe8,0x51,0x9d,0x18,0xc4,0xd0,0x59,0xf8, + 0xd6,0xe4,0x83,0xa1,0x5c,0x87,0x13,0x1f,0x90,0xb1,0x16,0xb4,0x73,0x61,0x94,0xe9, + 0xb5,0xaf,0xc8,0xf7,0x85,0xcf,0xb0,0x3e,0x2b,0x95,0x1b,0x6b,0xed,0x79,0x6c,0x18, + 0x3c,0x75,0xe6,0xaf,0x30,0x54,0xaa,0x8a,0xbd,0x8c,0xd1,0x55,0xd0,0xe,0xf2,0x75, + 0x5e,0x5c,0x8b,0x89,0xac,0xb2,0xd4,0xcc,0x73,0xb9,0xf,0xe1,0xc6,0xd9,0xb3,0x67, + 0x8b,0x55,0xf3,0x5b,0xf7,0xd7,0x5a,0x77,0xd9,0x53,0x1b,0xf8,0x15,0x66,0xb1,0x2b, + 0x6d,0x22,0x30,0xf5,0x8,0x68,0xeb,0xbc,0xbb,0xb3,0x89,0xaf,0xfb,0xd0,0xc6,0x7b, + 0x46,0xbe,0x40,0x77,0x95,0x33,0xf6,0x17,0x6b,0x78,0x86,0xa9,0xd7,0xae,0xb7,0x23, + 0x19,0x91,0x75,0x20,0x68,0x8a,0xe2,0xe5,0xe4,0x8f,0xb0,0xf8,0x38,0xee,0xd2,0xb6, + 0x51,0xbb,0x20,0x68,0x12,0x87,0xda,0x16,0x7e,0x8f,0x93,0x3c,0xd8,0x8e,0x11,0xf9, + 0x6e,0x1c,0xe,0x1c,0x83,0xe4,0xb3,0xfd,0x3a,0x94,0xcc,0xf0,0x42,0xe8,0xfb,0xff, + 0xd9,0xcf,0x7c,0xfc,0xb7,0xff,0xfb,0xbf,0x7c,0x27,0xab,0xfe,0xee,0x2f,0xfc,0xcc, + 0x47,0x6a,0x22,0x4c,0x9d,0x62,0xbd,0xcf,0xac,0x2d,0x4e,0xa3,0xc4,0x64,0xe,0x7b, + 0x9c,0xea,0x11,0xa2,0xe8,0x20,0x20,0x63,0xe2,0x68,0x52,0xd0,0x57,0xc2,0x34,0x9d, + 0x96,0xd8,0x75,0x6e,0x4b,0x61,0xb8,0x72,0xb8,0xac,0x59,0x1a,0xe,0x84,0x60,0x3b, + 0xee,0xe0,0xf,0x49,0x35,0xa2,0x1b,0x88,0xfa,0xe8,0x40,0x13,0xad,0x35,0xcd,0x10, + 0x9e,0x31,0xa2,0x54,0x55,0x53,0x55,0x53,0xd7,0x2f,0x46,0xa5,0xe3,0x6a,0x78,0xc3, + 0xef,0x30,0x88,0x9f,0xee,0xeb,0x91,0xa4,0x1f,0x19,0x75,0x68,0xa9,0xf2,0xc3,0x4b, + 0x20,0x86,0xf9,0xcb,0x6a,0xe2,0xc,0x76,0xaf,0x10,0xc2,0x3c,0xb6,0xe1,0xb8,0xe7, + 0xa1,0x65,0xc4,0x61,0x65,0xf5,0x9c,0xf8,0x6b,0x90,0xd7,0x6c,0x63,0x6,0x58,0x56, + 0x3c,0xb,0x10,0x32,0x38,0x11,0x1b,0x8a,0xf,0x29,0x3a,0x74,0xe7,0x73,0x4c,0xd4, + 0xc4,0xa3,0xfc,0x95,0x6a,0x5c,0x33,0x64,0x60,0x13,0xea,0x42,0xb,0xb7,0x8,0xe6, + 0xda,0x82,0x14,0x2f,0xd8,0x6f,0x18,0x39,0x87,0x3,0x9b,0xdc,0x14,0xc2,0xea,0x52, + 0x50,0xb5,0xed,0x97,0x93,0xe,0x46,0x23,0xe3,0x1d,0x54,0x1a,0x59,0x89,0x8a,0x6c, + 0x88,0x80,0x21,0x48,0xe2,0x9d,0xaa,0xcb,0x12,0x1b,0xa3,0xe9,0xac,0xef,0xbb,0xaa, + 0xfb,0x54,0xd6,0xa0,0x38,0x76,0x75,0x76,0xfb,0xb0,0xc9,0x31,0x54,0x75,0x18,0x60, + 0xcf,0xe2,0x30,0xfa,0x65,0x2c,0x79,0x59,0x6d,0x29,0xbe,0xc1,0xde,0x8b,0x47,0xb6, + 0xba,0x92,0x67,0x8b,0x3c,0x68,0xd8,0x92,0xab,0x9c,0xfb,0x44,0xf6,0xef,0xd8,0xd7, + 0xa2,0x6b,0xaa,0x96,0x8d,0x43,0x15,0x6b,0x50,0x2,0x43,0x8f,0x61,0x27,0x2b,0x54, + 0xbd,0x28,0x38,0x83,0xff,0x34,0xf1,0xe7,0xf0,0x7c,0x56,0x94,0x2a,0x79,0x2c,0x86, + 0x20,0x74,0x48,0xc4,0x8,0x9a,0x3,0xff,0x15,0x21,0x3c,0xd6,0x9c,0xc3,0xd0,0x51, + 0xd4,0xbe,0x9e,0x63,0x8b,0x5f,0x29,0x9c,0xf5,0x1c,0xc3,0x97,0x21,0x37,0x6c,0x94, + 0xec,0x24,0x23,0xce,0x22,0x4e,0xbb,0xeb,0xef,0x53,0x5,0xcf,0x18,0xe3,0xe4,0xd6, + 0x41,0x7a,0x9b,0xee,0xfb,0xff,0xf9,0xcf,0x7c,0xfc,0xdd,0x5f,0xf8,0xd9,0x8f,0x5f, + 0xff,0xa7,0xff,0xf2,0x9d,0x55,0x3,0x9a,0x13,0xae,0x6c,0xd1,0x5a,0x75,0x39,0xee, + 0x6a,0x5,0x27,0xc3,0xbc,0x7,0xb1,0xce,0x18,0xc,0x9a,0x25,0x8c,0x76,0x3f,0xf3, + 0x4b,0xf,0x7,0x5a,0x1c,0x4b,0xd5,0x2f,0x81,0x1c,0xb,0x83,0x47,0x31,0x9c,0xe8, + 0x84,0x72,0x32,0x90,0xf4,0xb3,0x90,0x2c,0xd6,0x41,0xe6,0x8e,0x9,0x63,0xda,0x22, + 0x80,0xc3,0x63,0x19,0x62,0xc2,0x74,0x0,0x8,0xc5,0x35,0x86,0x3a,0x1d,0x14,0x86, + 0xc4,0x76,0xe4,0x81,0x58,0x1f,0xe0,0x60,0xe1,0x8,0x4,0x74,0x18,0x3d,0x2b,0xc0, + 0x44,0x14,0xcd,0x5a,0x71,0x82,0x9d,0x10,0x7a,0xc4,0xe7,0x6e,0x53,0x70,0xdf,0xbd, + 0xc7,0x6,0x85,0xd6,0x35,0x23,0xc,0xf8,0x5d,0xbf,0xfa,0xef,0xfd,0xc2,0x4f,0x7f, + 0xfc,0xd7,0xff,0xe4,0x47,0xef,0x0,0xc2,0x92,0xf3,0x0,0xeb,0xa1,0xd7,0x8d,0x1c, + 0xd8,0xcc,0xa8,0xd4,0xe5,0xc6,0x6b,0x38,0x2e,0x89,0x1f,0x9c,0x2c,0x6f,0x7a,0xb4, + 0x9c,0x38,0x19,0x30,0xc,0xe0,0x1a,0x98,0xc6,0x91,0xb0,0x56,0x12,0xc1,0xb2,0x8d, + 0x84,0x91,0xc7,0x5d,0xea,0xbb,0x3e,0x69,0xd2,0xf,0xf3,0xb6,0x35,0x24,0x35,0x8d, + 0xab,0x62,0x6b,0x82,0xce,0xac,0x4f,0x8d,0x41,0xe4,0x5e,0x84,0x89,0xa9,0xf8,0xc1, + 0x43,0xa7,0x2c,0xe3,0xd0,0x8f,0x4,0x6,0xb9,0x43,0x58,0x2b,0xc4,0x49,0x5e,0xca, + 0x2c,0x9e,0xad,0x61,0x4d,0x29,0x30,0x54,0x28,0x4f,0x49,0x1,0x51,0xa3,0x3d,0xee, + 0xee,0x27,0xd7,0xe0,0x58,0x33,0x24,0x41,0x63,0x60,0xdd,0x8,0x8d,0xf7,0x51,0x60, + 0x68,0xc2,0x90,0x57,0x36,0xc5,0x45,0xef,0x77,0xeb,0x57,0x5e,0x33,0xe4,0x7c,0xe9, + 0xbd,0x1c,0x92,0x3e,0xdb,0x6b,0x97,0x15,0xaf,0x8f,0x5a,0x25,0x5a,0x72,0xa1,0xe, + 0x91,0x77,0xcb,0xec,0xaa,0x9e,0x80,0x5c,0x52,0x34,0x5d,0x9d,0x63,0x5b,0x95,0xa, + 0x98,0x15,0xba,0xf2,0x99,0xa8,0xce,0x44,0xe7,0xd6,0xaf,0xf,0xbe,0x48,0x95,0x56, + 0xcc,0x61,0xe,0xc6,0x81,0x6e,0x21,0x6d,0x23,0xda,0x80,0x63,0x9a,0x4d,0x94,0xdb, + 0x64,0x37,0xa1,0x16,0x57,0xb0,0xf3,0x16,0xe7,0x3d,0x52,0xf8,0x59,0xa6,0xef,0xbf, + 0xca,0x89,0xcf,0xce,0xb7,0x78,0xb8,0x67,0x4b,0xaf,0x7d,0xb5,0x57,0xb7,0xc4,0xf3, + 0x43,0xb2,0x7b,0xa0,0xf7,0x3d,0x29,0xb2,0x89,0xb7,0x10,0x59,0xe8,0x87,0x2b,0x1, + 0xd5,0xa4,0x8,0xde,0x8f,0xe6,0xa9,0x6f,0xc6,0x2a,0xc4,0x34,0x32,0xb6,0xd5,0xc8, + 0x68,0x1,0x0,0x6d,0xc4,0xd7,0xe7,0x97,0x75,0x6e,0x93,0x6,0xef,0xd1,0x18,0xa7, + 0x39,0xce,0x80,0x93,0xd5,0x4b,0x28,0x46,0xb9,0x6d,0xdd,0xaa,0x9a,0x39,0xbc,0x67, + 0x50,0x4c,0xb2,0x3f,0x47,0xf4,0x6e,0x75,0x74,0x21,0xd1,0xac,0x55,0x91,0x29,0xf9, + 0x8a,0x65,0x63,0x87,0x81,0x52,0x2b,0x75,0xb3,0x11,0xe6,0x95,0x6e,0x3b,0x19,0xc0, + 0x73,0x86,0x58,0x6d,0xfe,0xda,0xe6,0xc0,0xe9,0x3d,0xd9,0x20,0x77,0xfc,0xda,0x3f, + 0xfe,0xd1,0xfb,0x6f,0xfe,0xe2,0x4f,0x7f,0x44,0xca,0xba,0x3e,0xe3,0x3c,0x23,0x1d, + 0x7d,0x90,0xaa,0xb1,0x69,0xd6,0xc,0x76,0x96,0xd5,0x68,0xac,0xab,0x14,0x52,0x49, + 0xef,0xd3,0x49,0xf,0x35,0xe7,0xf7,0xf5,0x3a,0x98,0x76,0x9f,0x1b,0x13,0xbe,0xd6, + 0x6c,0x73,0x2b,0xf1,0x84,0x11,0xcd,0xd6,0x4a,0x69,0xd,0xb3,0x5,0xa1,0x62,0x2b, + 0x57,0x8d,0xfd,0xcb,0x68,0x6a,0x4f,0xf2,0x93,0xcf,0x9a,0x31,0x4e,0x2,0x7,0x73, + 0x19,0x84,0xfa,0x96,0x38,0x32,0x61,0x26,0x9f,0xfa,0x60,0x49,0xe8,0xb5,0xc3,0xc7, + 0x74,0xd8,0x88,0x86,0x99,0x4,0x25,0xa,0x8a,0x5e,0x5c,0x5e,0x5f,0xff,0xf,0xa2, + 0x16,0xa9,0x96,0xcb,0x44,0xb2,0xf9,0xf,0xda,0x2c,0x97,0xce,0x11,0x67,0x40,0xcb, + 0x49,0x87,0x74,0x9e,0xc3,0xb8,0x5c,0x17,0x99,0xcf,0x8,0xdb,0x6d,0xbe,0x41,0xe6, + 0xe8,0xb1,0x44,0x45,0x60,0xc2,0x2b,0xd6,0x4c,0xf2,0x2e,0x9e,0x20,0x75,0x4b,0xcc, + 0x4a,0xac,0x3c,0x51,0x3e,0xca,0xf4,0x8c,0x1e,0x19,0x51,0x35,0xb9,0x38,0x74,0x4a, + 0xe9,0xd2,0xcc,0x60,0xc0,0x9,0x22,0xc0,0x42,0x96,0x59,0x61,0xef,0xdf,0xe5,0xea, + 0x93,0x6b,0xe2,0x84,0x93,0xd1,0xd6,0x6e,0xa7,0x55,0x85,0xd8,0x54,0x12,0x5d,0xd1, + 0x74,0x83,0x5a,0x1b,0x4d,0xcf,0x3c,0x22,0x94,0x4c,0x90,0x64,0xd5,0xbb,0x5,0xb8, + 0x7e,0x83,0x5a,0x3,0xb,0x5f,0x8a,0xbb,0x3d,0x46,0x20,0x8c,0x62,0x4b,0xae,0x1b, + 0x5d,0xaf,0xa9,0x7c,0xf2,0x8,0x60,0x6b,0xdb,0xaa,0xfe,0x3f,0xe9,0xf7,0x79,0xb5, + 0x95,0x58,0xed,0x77,0x20,0xda,0x17,0x66,0x78,0x3,0xd7,0xa0,0xa0,0xf8,0x50,0x9b, + 0xab,0x68,0x8c,0xe9,0xf2,0x8e,0x39,0x29,0xd6,0x85,0xb8,0xf7,0xcf,0xef,0xbe,0x74, + 0x53,0x4f,0x1c,0x46,0xd,0xde,0xf3,0x84,0x35,0x3c,0x83,0x4,0xc6,0x2a,0x6e,0xa7, + 0x6a,0xd7,0x5c,0xf7,0x41,0xec,0x2c,0xab,0x3a,0x61,0xa1,0x7a,0x55,0xd9,0x4e,0x33, + 0xc6,0xd4,0x1f,0x30,0x54,0xd2,0x92,0xe7,0xd,0x2a,0x56,0x4d,0x7f,0xb8,0xc2,0xdc, + 0xa5,0xdd,0x26,0x1a,0xfb,0x7b,0xcf,0x41,0x86,0x60,0x3f,0x7b,0x75,0x72,0x79,0x7f, + 0xa0,0x13,0x35,0x1c,0xdf,0xea,0x9a,0xce,0x9c,0x2a,0x1,0x31,0xa1,0x11,0x21,0x84, + 0x87,0x84,0xf1,0xf4,0x70,0x6c,0x81,0x6a,0x7e,0xf0,0x19,0x2c,0x4a,0x64,0x1f,0x23, + 0x82,0xf5,0xa,0x8c,0xe1,0x55,0x2c,0x3d,0xfd,0x65,0xa9,0x98,0x10,0x1e,0x26,0x7d, + 0xe7,0x9c,0xc9,0xa7,0x13,0xcf,0x3a,0x46,0x3d,0xb7,0x7d,0xcc,0xd0,0x12,0x42,0x86, + 0xc3,0x5c,0x2d,0x63,0x26,0x84,0xa1,0x7a,0x95,0xcd,0x30,0xf2,0xc0,0x21,0xf5,0x4c, + 0x27,0xb2,0x5c,0x4f,0x6c,0x2e,0x6c,0x5e,0x21,0x4c,0x9d,0xe5,0x4d,0x58,0xec,0xc5, + 0x7c,0xce,0xff,0x4f,0x6d,0x84,0xe4,0xda,0x8d,0xac,0xa9,0xa1,0x68,0x66,0x79,0x2, + 0xa1,0x2d,0x1f,0x9f,0xfc,0xc6,0xa,0x7e,0x40,0xe2,0xde,0x9a,0x90,0xf8,0xfc,0x2c, + 0xd1,0xc0,0x64,0x7,0xaf,0xe8,0x3,0x6e,0x7b,0x30,0x5,0xbd,0x52,0x54,0x64,0x4c, + 0xd7,0x16,0x87,0xa5,0x66,0x3a,0xf2,0x33,0xfa,0x96,0x81,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x65,0x6a,0x98,0xfb,0x5c,0xd8,0x5e,0xe8,0x8f,0x73,0xa2,0x57,0x8d, + 0xdc,0x48,0x5,0x7b,0xe2,0xc4,0x25,0x3,0xac,0x82,0x20,0xca,0x42,0xa7,0xb1,0x24, + 0x11,0x8c,0xf9,0xd,0xd7,0x4a,0x9b,0xa5,0x2,0xe6,0x2f,0x21,0x4e,0x2e,0x22,0xa2, + 0xf0,0x3a,0xe0,0xee,0x77,0x53,0x22,0xe8,0x3,0xe8,0x3b,0xb6,0xa5,0x47,0x7c,0xf2, + 0x94,0x9b,0x6d,0x6e,0x94,0xf0,0xdd,0xc9,0x32,0x70,0xa,0x6,0x6d,0x5d,0x9c,0xe6, + 0x18,0xd3,0x7,0xb6,0xf,0x1b,0xc4,0xae,0x2d,0x87,0xcc,0xa1,0xf,0xee,0x7a,0xb6, + 0x3f,0x2e,0xa9,0xe6,0xef,0x4,0xf3,0xb3,0x46,0xa2,0x26,0x45,0xbe,0x75,0x50,0x54, + 0x71,0xa4,0x46,0x91,0xee,0xfb,0xf3,0x94,0xb0,0xec,0x82,0x56,0x81,0xf8,0x1a,0x4c, + 0x31,0xb4,0x36,0x6d,0xfd,0xe3,0x51,0x8a,0x7b,0x21,0x63,0x18,0x44,0x8e,0x4a,0x92, + 0x14,0x8d,0x85,0x12,0x7,0x34,0x5d,0x99,0x8b,0x87,0x40,0x6c,0xa9,0x5c,0x27,0x32, + 0xf4,0xca,0xcd,0x52,0xdf,0x79,0x66,0x0,0x13,0x29,0x22,0x8,0x78,0x39,0xa,0x47, + 0x74,0xee,0xdc,0x94,0xc5,0x62,0xb3,0x83,0x7d,0x76,0x94,0xcd,0x1d,0x2a,0x21,0x56, + 0x8,0xb9,0x83,0x87,0xcd,0xd5,0x60,0xe7,0x2a,0x1b,0xd,0x9b,0xb2,0x34,0x36,0x4d, + 0x39,0xac,0x16,0xa5,0x2a,0x8f,0x92,0x9d,0x26,0x64,0xe,0x63,0x3c,0xb5,0x8c,0x31, + 0x90,0x3e,0x20,0xd6,0x9a,0xf4,0x19,0xf8,0x27,0x98,0x5e,0x7c,0x4a,0xb8,0xde,0x3a, + 0x49,0x1e,0x84,0x3c,0xdb,0x45,0x36,0xc,0x8b,0xd4,0xac,0x9a,0x16,0x7d,0x2a,0x64, + 0x59,0x29,0xd9,0xf2,0xaa,0xb8,0xe4,0x35,0x4e,0xb5,0x63,0xab,0x85,0x9b,0xc6,0x73, + 0x5b,0xde,0x22,0x99,0x6b,0xe3,0x59,0xbe,0xa6,0xbd,0x45,0x4a,0x9f,0x65,0x8e,0xbd, + 0xb1,0x2b,0xb9,0x69,0xbd,0x27,0x61,0x8b,0x41,0xd0,0x54,0x42,0x16,0x4c,0xfb,0x97, + 0x61,0xa4,0xb2,0xc7,0xc1,0xf6,0xec,0xbd,0x5e,0x97,0xda,0xca,0x5a,0xb,0xd8,0x88, + 0x2b,0xb4,0x1e,0x1f,0x73,0x16,0x5b,0x5a,0x78,0x9b,0xa3,0x44,0x57,0x52,0xe3,0x26, + 0x85,0x52,0xfa,0x95,0x29,0x7d,0xd9,0x26,0x5,0x6c,0x59,0x6c,0xd,0x0,0xf3,0x2f, + 0x6f,0xc4,0xae,0x6a,0x2e,0x6c,0x49,0x99,0xe9,0x1,0xc3,0x8b,0x1a,0xad,0xc0,0x9b, + 0x2,0x58,0x85,0xf9,0x4b,0x1e,0x49,0xc2,0x27,0x61,0x3b,0xf9,0xa4,0x25,0x54,0x4a, + 0x86,0xa3,0x1c,0xda,0x9c,0x8f,0xce,0xf1,0xf8,0x43,0xd7,0x9,0xb0,0xbe,0xae,0x92, + 0x7e,0x18,0x67,0x88,0xcc,0xc4,0xd3,0x5b,0xa3,0xeb,0xe4,0xba,0x6a,0x76,0x92,0x56, + 0xa4,0xf,0xc1,0xc1,0x69,0x44,0x69,0xf1,0xa1,0xc8,0x6e,0xf,0x47,0x8d,0xca,0x9a, + 0x6c,0x68,0x58,0x5e,0x90,0xac,0x7a,0xbd,0x11,0x37,0xb9,0x10,0x1b,0x17,0xe3,0x2f, + 0x27,0x28,0x2e,0x45,0xca,0x9b,0xab,0xc5,0x89,0xae,0xa9,0x52,0x2b,0x83,0xd4,0x71, + 0xe8,0xb1,0xff,0xe5,0xdf,0xfd,0x7f,0xde,0xab,0xaa,0x7e,0xe7,0x97,0x7f,0xf6,0x83, + 0x6a,0xd9,0xa1,0x7a,0x1d,0xc,0xd,0x8f,0x20,0xb5,0xa2,0xa2,0xdc,0xcf,0x9e,0xc4, + 0xfd,0x95,0x6f,0xa3,0x85,0x93,0xc1,0x96,0xad,0x41,0xd4,0xd4,0xda,0x58,0xd9,0xdb, + 0x83,0x5,0xb0,0x9,0xee,0x73,0x36,0xb3,0x43,0xf8,0x27,0xb9,0x6a,0x44,0x1f,0x7d, + 0x2c,0xf4,0xe1,0xd9,0xe2,0xde,0x9c,0xac,0x36,0xe6,0x1,0x8c,0x62,0xe,0x7c,0xd1, + 0xdf,0x65,0xcd,0xd2,0xae,0x67,0x6,0x55,0x4a,0x9a,0x5c,0xb,0x6,0x53,0x13,0x83, + 0x21,0xf7,0x10,0xff,0x69,0xe,0x92,0xa1,0x5d,0x2,0x7,0xa9,0x59,0x1f,0xa3,0x6a, + 0x4f,0x86,0x98,0x42,0x38,0x4b,0xe3,0xbd,0x42,0xea,0x90,0x6c,0x4d,0x7,0xd8,0x61, + 0x1e,0x89,0x5b,0x85,0x44,0x78,0x5c,0xdb,0x5e,0xcc,0x4a,0x53,0x63,0x74,0xa,0x38, + 0x64,0xde,0x74,0x71,0xcd,0x25,0x31,0xca,0xde,0x12,0x56,0x7,0x2c,0x3e,0x41,0xa4, + 0x8c,0x39,0x6a,0xc7,0x83,0xf8,0xd,0x18,0x14,0x47,0xca,0xbd,0x77,0xb3,0x4,0xa6, + 0x1f,0xfb,0x6a,0x2b,0xe8,0xa1,0x51,0x1,0x73,0x3e,0x41,0x53,0xe,0x48,0x39,0xbc, + 0x9e,0x83,0x6c,0x38,0xf7,0x84,0x30,0x8d,0xc6,0xd0,0x4d,0xdd,0x9d,0x7,0x62,0xe6, + 0xe0,0x7b,0xde,0x40,0xa9,0x9,0x3e,0x3e,0xac,0xfd,0x6e,0x88,0x85,0xa3,0xd1,0x95, + 0x4d,0x22,0xa8,0xdb,0x18,0x3a,0x82,0x61,0x13,0x32,0x88,0x14,0x4b,0x39,0x10,0x83, + 0x11,0x48,0xb6,0xf7,0xf4,0xa0,0x20,0x3b,0xc1,0x12,0xa6,0xd5,0xef,0x81,0x8d,0xb2, + 0x7f,0x34,0x79,0x48,0x1,0x9f,0x47,0x1e,0x15,0xad,0xc5,0x34,0x7,0xf3,0x89,0x6f, + 0xd1,0x44,0x58,0x30,0xec,0x6b,0x38,0xe4,0x5c,0xed,0x9d,0x73,0x51,0x4,0x23,0x9d, + 0xaa,0xf7,0x5,0xbb,0xcc,0xb1,0xc7,0x75,0xf,0xca,0xc3,0x3d,0x58,0xc4,0x44,0x7a, + 0xcc,0x0,0x7b,0xe2,0x94,0x1,0xb2,0xf7,0x67,0x39,0x34,0x34,0xb5,0xef,0x79,0x98, + 0x9f,0x4b,0x7b,0x85,0xc9,0x2f,0xa0,0x15,0x8f,0x74,0x67,0xc7,0x9c,0xde,0x60,0x75, + 0x2d,0x8,0x3d,0x43,0xe3,0xa8,0x5d,0x3c,0xa4,0x9,0xb6,0xb6,0x8c,0xf9,0x4b,0xec, + 0x85,0x9f,0x55,0xff,0xf3,0xaf,0x7c,0xef,0xe3,0x2f,0xfd,0xc3,0x1f,0xbe,0xeb,0x39, + 0x5c,0x36,0x1,0xc5,0xba,0x6e,0x68,0xdd,0x99,0x7f,0x21,0x81,0x4e,0x9c,0xb,0x56, + 0xde,0x8a,0x13,0x68,0x40,0xc1,0xc0,0x32,0xcd,0xc5,0x69,0xa2,0xf,0x32,0x96,0x16, + 0xc,0xa5,0xa4,0xed,0x1b,0xd3,0x11,0x30,0xab,0xc2,0x34,0xb7,0xaf,0xe1,0x0,0x46, + 0x40,0xee,0xee,0x9b,0x1d,0xac,0xed,0x55,0x3d,0xb0,0x93,0x46,0x6c,0xae,0x36,0x2c, + 0xf4,0x1a,0xc1,0x45,0xd1,0xef,0x7d,0x48,0x35,0x46,0x36,0x10,0x2a,0x5c,0x52,0xa5, + 0xc1,0xfb,0xed,0x8d,0x15,0x29,0x3e,0xd0,0xe6,0xbf,0x7e,0x7,0x24,0x13,0xbf,0x88, + 0xa4,0x64,0xb5,0x4c,0xcc,0xe6,0xb3,0xba,0x28,0x2,0x5c,0x6c,0x66,0xc3,0x5a,0x52, + 0x69,0x71,0x5b,0x76,0x42,0xa0,0x77,0xc2,0x33,0x42,0x85,0xed,0xdd,0x98,0x86,0x1, + 0x8a,0xd3,0x8,0x8c,0x7a,0xaf,0xd5,0x8,0x6,0x3a,0xf7,0x3d,0x55,0xed,0x2a,0x16, + 0x2,0x65,0x74,0x3b,0x11,0x6,0x49,0x18,0x97,0x9,0x1,0x37,0xfe,0x42,0x8c,0x9c, + 0x5e,0x5b,0xab,0x3c,0xe0,0xf2,0x2a,0x31,0xf4,0xd1,0x14,0x6d,0xcd,0x8b,0x5f,0xe, + 0x75,0x86,0x4c,0xa7,0x55,0xf0,0x6d,0x9f,0x65,0x17,0x5,0xc1,0xca,0x85,0x23,0x24, + 0xb5,0x65,0x29,0x73,0x14,0xb7,0xd0,0x7b,0x6b,0xe5,0x64,0xf0,0x2e,0x96,0x52,0x18, + 0x28,0x26,0x30,0xef,0xf2,0x13,0xdb,0xbe,0xcf,0x58,0x27,0x63,0xcc,0x39,0x34,0x93, + 0xbc,0x73,0xff,0xb5,0x9b,0x50,0x6b,0x53,0x23,0xe6,0xfa,0xb6,0xfd,0x12,0xcb,0x8c, + 0x9d,0x36,0xb1,0x15,0x27,0xc2,0x21,0xd1,0x59,0xf7,0xb6,0x86,0xb7,0xd6,0xc4,0xe2, + 0xe6,0xc0,0xf5,0xbf,0xdd,0xe0,0xa3,0xb3,0xb2,0xbd,0x65,0x34,0x88,0x64,0xc1,0x67, + 0xfb,0xd1,0x88,0x90,0x18,0x61,0xe4,0x66,0x75,0x8a,0x81,0x99,0xd6,0xe6,0xfc,0xa7, + 0x96,0xa3,0x57,0x7f,0x36,0xb,0x3d,0xc4,0x51,0x30,0x9,0x81,0x38,0x60,0xcc,0x27, + 0x93,0x9d,0x2b,0xdc,0xe9,0x4,0x5e,0x17,0xbd,0xa,0x85,0xdb,0x5f,0xa,0x95,0xd1, + 0xf5,0x27,0xfa,0xad,0xc0,0xb,0x24,0xb8,0xfa,0xd4,0xc,0x72,0x7d,0xc8,0x7a,0xa, + 0xf6,0xb4,0xe,0x68,0xe4,0x19,0x51,0x7,0xe,0xac,0x9e,0xbd,0xd6,0x43,0x4f,0x2, + 0xa0,0x92,0x5b,0xaf,0x8e,0xac,0x28,0x39,0x77,0xfc,0x5e,0x54,0xbd,0x4d,0xe6,0x12, + 0xa4,0x13,0xdc,0x4c,0xe0,0x2f,0xe6,0x4b,0xd5,0x31,0x48,0x7b,0x67,0xa,0x7b,0x70, + 0xa8,0xae,0x17,0x7a,0xf8,0x54,0x2d,0x54,0x88,0x2e,0x34,0xb2,0xdb,0x48,0xc8,0xae, + 0x64,0x38,0x12,0x63,0xb6,0xd1,0x2,0x3,0x1a,0x2e,0xba,0x25,0x24,0x38,0x41,0xeb, + 0x5a,0xfd,0xb0,0x59,0x5,0x9a,0xb6,0xb0,0x55,0x4,0x94,0x91,0x3a,0x38,0x4f,0x8d, + 0xe,0xc9,0x72,0xc8,0x18,0x31,0x58,0xb1,0xa4,0x5,0xa8,0x39,0xc3,0x25,0xe9,0x2f, + 0x46,0x85,0x9e,0x1e,0x3a,0xb1,0xfb,0xe9,0xda,0xfb,0x1,0x83,0xc1,0xaa,0x15,0x7a, + 0x3,0xf1,0x3c,0xfb,0xcc,0x9a,0xbd,0x84,0x38,0xc9,0x48,0xaa,0x1e,0x95,0x23,0x4c, + 0x91,0x6,0x53,0xcd,0x8,0xab,0x64,0x13,0xe2,0x45,0xf3,0xaf,0x94,0xfe,0x6a,0x94, + 0x99,0xee,0xe7,0xe6,0xa4,0x4f,0xa4,0xdc,0xe4,0x9a,0xff,0x1d,0x2a,0x9f,0x6b,0xb0, + 0xec,0xbc,0xc4,0xe5,0x4a,0xdc,0xce,0xc,0xa8,0x22,0x7,0x60,0x4b,0x2d,0x56,0x39, + 0x42,0x8a,0x39,0xed,0xae,0xd5,0xd7,0x42,0x32,0x10,0x55,0x13,0x4e,0xf3,0xe6,0x94, + 0x3d,0x24,0xa3,0x2c,0xee,0xe2,0x20,0x4,0xaa,0x3a,0xd0,0xad,0xd9,0xd9,0x0,0xb1, + 0x47,0x4d,0xca,0xb2,0x86,0x8a,0x2f,0xda,0x8,0xd1,0x3,0x8,0x94,0x30,0xd,0x63, + 0x30,0x76,0x4d,0x91,0xf6,0xc2,0x89,0x8f,0x8e,0x56,0xa5,0xf3,0x21,0x9f,0x45,0x81, + 0xd9,0x4e,0x3e,0x8e,0xb1,0xcd,0xd6,0xb7,0xda,0x58,0x9d,0xb9,0xac,0x64,0xb,0xb2, + 0x11,0x71,0x9b,0x70,0xc0,0xb7,0xf5,0x1b,0x52,0x90,0x85,0xe9,0x31,0x94,0xd6,0x1d, + 0xb9,0xf6,0x27,0xcb,0xed,0x59,0xb6,0xc,0x60,0xac,0xbe,0xbe,0x1e,0x68,0x9d,0xf4, + 0xa9,0xec,0xd7,0x62,0xb3,0x41,0x21,0x5b,0x12,0xba,0xa1,0xf9,0xa8,0x6c,0xa4,0xa1, + 0x41,0x26,0x2e,0x1d,0xeb,0xed,0xc3,0xee,0x9f,0xfc,0xac,0xf1,0xf4,0x30,0x29,0xf2, + 0xee,0xe,0x7e,0xfd,0xaa,0x5f,0xf9,0x9d,0x1f,0xbc,0xff,0x83,0xbf,0xf8,0xbd,0x8f, + 0x9,0x13,0x35,0xcd,0xe,0x6d,0xe0,0x3d,0x5a,0xed,0xf7,0xa5,0xfd,0xca,0xef,0xfc, + 0xf0,0xfe,0xc,0xd4,0x3f,0xf8,0x4b,0xdf,0xfb,0x40,0xca,0x6c,0xaf,0xa4,0x54,0x3e, + 0x27,0x4d,0xc4,0x42,0xb9,0x54,0x5b,0x58,0xea,0x3e,0xca,0x52,0xa5,0xb8,0x1,0xe2, + 0xdc,0x6d,0xed,0xd,0x57,0x13,0xd5,0x33,0x65,0x71,0x61,0x2,0xba,0x84,0x5e,0x9b, + 0x88,0x51,0x32,0xa1,0x92,0x57,0x10,0xba,0x5,0x91,0x99,0x27,0x41,0x9,0xd5,0x6, + 0x8f,0x5a,0xff,0xb9,0x8f,0xa1,0x86,0x2f,0xb9,0x4a,0x7b,0x8e,0xa2,0x0,0x5a,0x21, + 0xe5,0xcc,0x34,0xe6,0xd,0xa6,0x6,0x5,0xc9,0x2b,0x43,0x2d,0x5,0x29,0xcd,0xe2, + 0x39,0xe0,0x96,0x48,0xa2,0x44,0x4d,0x99,0x7b,0x6f,0x83,0x30,0xe5,0x40,0xab,0xf7, + 0xd0,0x11,0x73,0xcf,0xb0,0x19,0x75,0x95,0x13,0x74,0x49,0x59,0x4e,0xbd,0xff,0x46, + 0x91,0x44,0xb,0x48,0xe0,0x44,0x42,0x8b,0xdf,0x86,0xe1,0x90,0x56,0x6d,0xf2,0x21, + 0xa9,0xe8,0x82,0x7,0x49,0xaa,0x73,0xe5,0xc2,0xe4,0x2a,0xea,0x88,0x11,0x86,0x91, + 0x97,0xa1,0xc4,0x15,0x98,0x7f,0xe9,0x4,0x8b,0x98,0x4d,0x54,0x87,0xd3,0x68,0x16, + 0x1f,0xf4,0x65,0x20,0xe3,0xe1,0x90,0xe6,0xcb,0x6f,0xb9,0x4c,0xa2,0x39,0x9f,0x3f, + 0x3c,0xd3,0x1d,0x49,0x37,0x15,0xa4,0xc7,0x6b,0xb0,0x99,0xad,0x2e,0xac,0x15,0xd5, + 0xe6,0x74,0x9b,0x80,0xd9,0x37,0xbc,0xad,0x6a,0x31,0xcb,0x40,0x6b,0x81,0x75,0xc4, + 0x6e,0x1a,0x4d,0xec,0xb3,0xd0,0xb9,0x6,0x86,0xf5,0x61,0x85,0x19,0x6,0x49,0xd3, + 0x90,0x10,0xc5,0x30,0xf6,0x16,0xbf,0xd7,0x66,0xe0,0xa1,0x4e,0x72,0x15,0x92,0xac, + 0x7e,0xff,0x56,0xea,0xd5,0xa4,0x51,0x5d,0xd2,0x3a,0xd5,0xdd,0x50,0x9d,0x64,0x48, + 0x60,0x46,0x47,0x67,0x1a,0x5a,0xff,0x1c,0x3b,0xfb,0x65,0x3f,0xeb,0xb3,0x46,0x22, + 0x61,0x8f,0xe0,0x98,0x90,0xce,0x82,0x4c,0xac,0x44,0x63,0xb5,0x6b,0x36,0x1d,0x8, + 0xe8,0x1c,0x79,0x90,0xd7,0x42,0xab,0x7f,0xfb,0x2b,0x28,0x77,0x4,0xad,0xb2,0x27, + 0x2b,0x24,0x54,0xb5,0x35,0x87,0x4e,0xbd,0xa,0x5d,0x3,0xa,0x3f,0x2,0xe5,0xc8, + 0x60,0xe1,0xda,0xe7,0xa8,0xfe,0x1d,0x3c,0x18,0xaf,0xcf,0x50,0xcf,0x82,0xfb,0x7b, + 0xff,0xe1,0x5f,0xf9,0x53,0x1f,0xbf,0xf2,0xdb,0x3f,0x78,0x57,0x2b,0xd6,0x2a,0x27, + 0x0,0x22,0xc6,0x99,0xb,0x1d,0x95,0x85,0x3c,0x7f,0x0,0x75,0x51,0xe1,0x90,0x80, + 0x71,0x77,0x26,0x77,0x55,0x3f,0x2e,0x31,0x6f,0xe6,0x60,0xec,0x62,0xb2,0xd0,0xc3, + 0xd4,0x5f,0xba,0x5f,0x7b,0x45,0xff,0x5b,0x59,0x9e,0x31,0xbb,0xcd,0xaa,0x79,0x26, + 0x6f,0xe8,0xf7,0x79,0x20,0xc2,0x6c,0xe4,0x66,0x7,0xb1,0x9f,0x48,0xc,0xe8,0xcf, + 0x32,0x50,0x71,0xca,0xda,0xfb,0x9a,0x7d,0x13,0xa1,0x33,0xc1,0xdd,0xb0,0x60,0x57, + 0xe3,0xc,0x85,0xae,0xc2,0xf0,0xcf,0x40,0x8c,0x4e,0x5,0x7c,0xf8,0x29,0xaf,0x93, + 0xf9,0x47,0x85,0xe7,0x15,0x52,0xda,0x7d,0x77,0x76,0x3f,0x6c,0xc,0xbc,0xef,0x26, + 0x75,0x3a,0xb0,0xa6,0xc7,0x49,0x83,0x43,0xf3,0x35,0x45,0x38,0x2,0x93,0x6,0x26, + 0x98,0xed,0x0,0x23,0x4e,0xee,0x56,0x38,0x54,0x80,0x3c,0x9f,0xd9,0x3e,0x2f,0x5d, + 0xd5,0xa7,0x1d,0x34,0x5b,0xbb,0xfa,0xf9,0xa9,0x68,0x1,0x53,0x2e,0x37,0x6c,0x1b, + 0x6d,0xfd,0x4e,0xd2,0x98,0x87,0xfb,0x86,0xc3,0x99,0x3d,0xb4,0xd1,0xd8,0x48,0x9a, + 0xd5,0x9c,0xf1,0x74,0x6a,0x0,0x56,0x40,0x87,0x1f,0xb3,0x48,0x21,0x2b,0xd9,0xca, + 0x5c,0xdb,0xe2,0xc6,0x52,0x61,0x75,0x25,0x20,0x42,0x35,0x25,0x74,0x3c,0xca,0x93, + 0xa4,0xc9,0xc1,0xee,0x99,0xd5,0xe1,0x2a,0x5f,0xe8,0x5a,0xe6,0xe8,0xf3,0x11,0x26, + 0xa5,0x6b,0x57,0xcf,0xd1,0x76,0xb6,0x94,0xb,0x61,0xe2,0x2b,0xe,0xa5,0xab,0xb5, + 0x27,0xcd,0xc1,0x8b,0x7e,0x46,0xaa,0x9e,0x7e,0x6b,0x53,0x38,0xbb,0xbc,0x31,0xa5, + 0x63,0x20,0x84,0xd9,0xf5,0xc8,0x75,0x94,0xfe,0x19,0x70,0x76,0xb6,0xe7,0x94,0xe8, + 0xf9,0xf5,0x30,0x3e,0xab,0xcc,0x77,0x6d,0xbf,0xad,0xb6,0x68,0xb8,0xa8,0x6d,0xf4, + 0x17,0xc1,0x5,0x91,0x62,0x63,0x98,0x3c,0x50,0xee,0xb,0x1f,0x2d,0x93,0x74,0x2b, + 0x46,0x4f,0xc0,0x0,0xe9,0xed,0x27,0x83,0x18,0xd5,0x7d,0x32,0x52,0xfb,0xe3,0x3e, + 0xb,0x29,0xfc,0x95,0xe7,0x79,0x81,0xdc,0x8a,0x6f,0x48,0xf,0x88,0xfd,0xac,0xfe, + 0xcb,0xdf,0xfa,0xc1,0xfb,0xef,0xfe,0xea,0xcf,0x7d,0xe4,0xa4,0xd2,0x2a,0x53,0x3e, + 0x7b,0x8b,0xa0,0x4b,0x33,0xd7,0x1,0xb5,0xe8,0x32,0xc9,0xac,0xaa,0x37,0x14,0x1b, + 0x21,0xdd,0x4c,0x26,0x20,0xda,0x35,0x74,0x72,0x89,0xcd,0x28,0xee,0x74,0x64,0xc1, + 0xb9,0x66,0x50,0x30,0xb1,0xd5,0x19,0xce,0x50,0x46,0x52,0xaa,0x18,0xc,0x77,0x57, + 0x2f,0x23,0x3f,0xc,0xd0,0x60,0x15,0xea,0x97,0x7f,0xeb,0x87,0xef,0x55,0x55,0xff, + 0xeb,0xaf,0xfd,0xec,0x47,0x25,0xe4,0x68,0xce,0x18,0x4c,0xd9,0x39,0xf7,0x44,0x3f, + 0x42,0xdb,0x83,0x21,0xfc,0x84,0x81,0x9d,0x54,0xb5,0x54,0x28,0x80,0xd9,0xd3,0xb, + 0x28,0x32,0x74,0x7d,0x99,0xf6,0xa4,0x4a,0x70,0xab,0xaa,0x5f,0xfe,0xad,0x1f,0xbe, + 0xff,0xee,0xaf,0x7d,0xef,0xe3,0xf9,0xaa,0xdf,0xfd,0xb5,0xef,0x7d,0xfc,0xf2,0x6f, + 0xfe,0xf0,0x9d,0x86,0xdb,0x94,0xf7,0x38,0xa9,0xf3,0x9b,0xe1,0xd5,0x9e,0xb0,0x64, + 0xcc,0xaf,0xaf,0xcf,0x1c,0x50,0x43,0x75,0x6e,0x53,0xe2,0xdb,0x62,0xfc,0xd3,0xa1, + 0xb9,0x33,0xd9,0x90,0x35,0x5a,0xd3,0xcd,0x74,0xdb,0x9a,0xdd,0xe9,0xd4,0xd,0x8a, + 0x51,0xf1,0x9f,0xdc,0x4,0x2b,0x9d,0x87,0xcf,0xa8,0x6d,0xe5,0x38,0x98,0x48,0x27, + 0xc3,0xc9,0x7d,0x6b,0x8d,0x5f,0xfb,0x3e,0xb8,0x65,0xa7,0x3a,0xc7,0x9,0x24,0x27, + 0xd0,0x21,0x6d,0x8e,0xdf,0x95,0xc1,0x1a,0x98,0xbf,0x5c,0xb4,0xca,0xe6,0xa4,0x4b, + 0x89,0xab,0xcf,0xcc,0xb2,0x7d,0xf6,0x46,0x20,0xb6,0x34,0x33,0x4,0x51,0xe6,0x7d, + 0xd8,0x26,0x4b,0x99,0xd1,0x1b,0xf7,0xb6,0x9a,0xa2,0xd2,0xce,0x67,0xd0,0x35,0xde, + 0x45,0x94,0x18,0x1e,0xdf,0x4e,0xaa,0x45,0x20,0xeb,0x49,0x2,0xf3,0x9e,0xfb,0xd7, + 0x1e,0xbf,0x76,0x42,0xc0,0xde,0x15,0x40,0xd2,0xba,0xad,0xa5,0x24,0x73,0xc4,0xaa, + 0xf2,0xa8,0xce,0x65,0xc3,0xec,0xfe,0x38,0xeb,0x74,0xff,0xc1,0x5f,0xf8,0x7b,0x3f, + 0x78,0xaf,0xaa,0xfa,0x47,0xbf,0xfe,0x73,0x1f,0x2c,0xda,0x39,0x78,0x9c,0xb5,0xe, + 0x7f,0xf9,0x2f,0xa5,0x48,0xf3,0xa1,0x2b,0x93,0x66,0x35,0xb7,0x45,0x87,0xbd,0x51, + 0xee,0xb4,0xa8,0x2d,0xb0,0x74,0x80,0xdb,0xae,0x74,0xb0,0xb5,0xc8,0x9,0xc1,0x79, + 0xae,0xab,0x64,0x2,0xa5,0x37,0x19,0x5b,0x46,0xac,0xa2,0x2b,0x36,0xb5,0x61,0x73, + 0xfa,0x9,0x7f,0x6b,0xde,0x4d,0x91,0x35,0x77,0x26,0x3a,0x12,0xf1,0xd3,0x64,0x84, + 0xd5,0x39,0x20,0xb5,0xf9,0xaf,0x7b,0x72,0x86,0xa3,0x21,0x38,0xb3,0x7b,0x47,0xfa, + 0xc,0xff,0xd2,0x6b,0x1d,0x98,0xfd,0x1a,0xf3,0x0,0x6b,0x2b,0xd4,0xa9,0x55,0xcc, + 0x12,0xb7,0x35,0x4,0x44,0x28,0xa3,0x2b,0x3b,0xcd,0x42,0x8c,0xd1,0xc,0xbd,0xaf, + 0xf4,0x71,0x56,0x58,0xd7,0x1d,0x46,0x5c,0x32,0x31,0x58,0x6d,0xb6,0x70,0x78,0x90, + 0x58,0x2c,0xcc,0x5e,0xd6,0x32,0x87,0xed,0x4a,0x3f,0xfe,0x1e,0x8c,0xa6,0x33,0x72, + 0x2d,0xda,0x5f,0x18,0x2d,0x59,0x7,0xf7,0xb7,0x74,0xc1,0x69,0x66,0xc6,0x87,0x8a, + 0x31,0xe2,0x99,0xb,0xb4,0x48,0x0,0x9e,0xde,0x97,0xac,0x28,0x51,0x89,0xd3,0x79, + 0xe6,0x75,0x3f,0x4e,0x4c,0xf9,0xdb,0xd0,0x65,0xd6,0x96,0x19,0xd4,0xf8,0x1e,0xa5, + 0xa9,0x2b,0x4c,0x14,0x52,0x89,0x2b,0x3,0x6c,0x5a,0xc,0x5d,0x8a,0xd1,0x4c,0x33, + 0xdb,0xc,0xe,0x43,0x2e,0x17,0x47,0x47,0x12,0x82,0x87,0x40,0x98,0x5d,0x31,0x5a, + 0x5a,0x3,0x70,0xfb,0x1b,0x5f,0x4e,0xb1,0x4e,0x80,0x80,0xd,0xb7,0xdf,0x1,0xd0, + 0xe7,0xd6,0x31,0xea,0xc0,0xc6,0x64,0x3a,0x60,0xc0,0x6,0x27,0x29,0xd8,0x27,0x6f, + 0xa2,0x13,0xe8,0x94,0x18,0x9a,0x5b,0x96,0x49,0x1e,0xdc,0x8c,0x83,0x7a,0x64,0x5f, + 0x41,0x45,0x7d,0x36,0x2b,0x1f,0xc6,0x69,0xb9,0xc2,0x8c,0x46,0xaa,0x14,0x66,0xeb, + 0x4d,0xaf,0xfd,0x6a,0xce,0x72,0xa5,0x7a,0xef,0x43,0xcf,0xbe,0xdb,0x5a,0xde,0x33, + 0xde,0xc,0x27,0x38,0x15,0x84,0x19,0x98,0x8,0x6d,0xd2,0xc0,0x66,0x92,0x93,0xbf, + 0x21,0xe,0x6f,0x26,0xe,0xc2,0x68,0x19,0x21,0x8c,0x43,0x3b,0xe2,0xc2,0x3,0x6a, + 0xb6,0x9e,0x33,0x52,0x66,0x78,0xde,0xa7,0x50,0x2d,0x86,0x38,0x44,0x1,0x15,0x36, + 0x61,0x79,0x5a,0x9a,0xa4,0x3b,0x1d,0x69,0x43,0xc0,0xea,0x58,0xea,0xbf,0x49,0xa8, + 0x6b,0x8c,0xc,0x74,0xeb,0x6b,0x84,0x4b,0x61,0xde,0x53,0x86,0x16,0xc1,0x42,0x33, + 0x1f,0x5b,0xe6,0x36,0xfd,0x70,0x68,0x6b,0x26,0x30,0xa5,0xc8,0xe,0x9a,0x6a,0xc8, + 0xf9,0xec,0xa,0x74,0x51,0x35,0x50,0x4c,0xa6,0xe4,0xf3,0xd0,0xaa,0x1,0xea,0x1f, + 0xfd,0xfa,0xcf,0x7d,0xfc,0x85,0xef,0xff,0xdf,0xef,0x65,0xc4,0x55,0x3d,0xea,0xaf, + 0x8d,0x8a,0xb2,0x44,0x23,0x45,0x4e,0xde,0xcf,0xea,0x42,0x56,0x72,0x2c,0x5b,0xd7, + 0x31,0xb4,0x51,0x3a,0x2,0xf7,0x48,0xbf,0xca,0xa6,0xee,0xf7,0xe0,0xab,0x5f,0x70, + 0x50,0x94,0xf1,0x3,0xfc,0xe0,0xc8,0x86,0xa8,0x8b,0x9a,0xdc,0x6b,0xf6,0x25,0x27, + 0x17,0xa0,0xb5,0xa0,0xe9,0xfd,0x32,0xcd,0x7e,0xb3,0xf,0x13,0x46,0xf2,0x1c,0x18, + 0x8d,0x6c,0xce,0xd2,0x7,0xf2,0x8e,0x9,0x2e,0xe8,0xd0,0xbf,0x3b,0xf3,0x20,0x12, + 0x11,0x48,0x75,0x6a,0xe2,0x31,0xcd,0xe6,0x93,0x2b,0x40,0xa2,0x20,0x22,0x1e,0x68, + 0x26,0x8a,0x36,0x21,0x32,0x8,0x6e,0x2c,0x31,0x88,0x38,0x3d,0x29,0x2c,0x4b,0x64, + 0x62,0xf3,0x5c,0xf,0xab,0xfe,0xb7,0xff,0xe6,0x4f,0x7d,0xfc,0xd2,0xf7,0xbf,0x90, + 0xd,0xef,0x8b,0x75,0x34,0xfd,0x97,0xfe,0xa7,0x1f,0xbc,0xff,0xd2,0xf7,0x7f,0xf0, + 0xae,0x28,0xc,0xd5,0x5e,0x53,0x19,0xd9,0xed,0xa0,0x73,0x21,0x12,0x19,0x38,0x68, + 0xd4,0x2b,0xd,0x9e,0x96,0x60,0x57,0x2a,0x90,0x21,0xd4,0xa0,0x9c,0x7b,0xf5,0x30, + 0xf8,0x15,0x46,0x27,0x36,0x22,0xb1,0xd8,0xf6,0xf1,0xf7,0x64,0xd5,0x8,0x6,0x99, + 0x1f,0xb5,0xa4,0x7,0xa,0x58,0xa8,0x61,0x89,0xe8,0x2e,0x9b,0x95,0x68,0x70,0x14, + 0xd6,0xff,0x12,0x21,0x9b,0x1b,0x86,0x7,0xd9,0x62,0x49,0xbb,0x4d,0x73,0xa4,0xa3, + 0x8b,0x6c,0xb4,0xce,0x46,0x84,0x38,0x49,0xec,0x9,0xf5,0x7b,0x97,0x35,0x6a,0xa6, + 0x39,0x30,0x8,0x39,0xb8,0x64,0x8d,0x59,0x91,0xbd,0x5e,0x84,0x27,0x3a,0xac,0x65, + 0xc7,0x95,0xd4,0x21,0xa4,0x47,0x77,0xd5,0x49,0x53,0x13,0xe8,0x2,0x53,0x68,0xf4, + 0x2a,0xaf,0x43,0x50,0xae,0x12,0xee,0x8a,0xe1,0xaa,0x72,0x46,0xa9,0x96,0x47,0x38, + 0x54,0x7b,0xeb,0x15,0x3c,0x14,0x95,0x24,0x7d,0xce,0x29,0x9b,0x12,0x71,0x36,0xb4, + 0xf5,0xdb,0x5f,0x58,0x5a,0xa3,0xc9,0x4f,0x57,0x13,0x3d,0xc2,0x70,0x8e,0x23,0x8d, + 0xd9,0x30,0x7b,0x2b,0x70,0xe2,0x26,0x60,0x18,0xd5,0x38,0x2a,0xed,0xe,0x37,0xc, + 0x10,0xc4,0x28,0xe,0x86,0x10,0xe6,0x79,0x61,0xac,0x10,0x88,0xc7,0xac,0x80,0xd6, + 0xb9,0x3a,0x8a,0x7e,0x6,0xe2,0xf8,0xec,0x4d,0xe,0xb1,0x4a,0x93,0x1d,0xd6,0x90, + 0x88,0x8,0x4a,0x71,0xbf,0xff,0xa,0x7b,0x60,0x63,0xca,0xb3,0xc6,0xe2,0xb7,0x1e, + 0xae,0x8c,0x7d,0xbf,0xdb,0x33,0x82,0x95,0x3d,0xb1,0x7a,0xeb,0xe6,0xf4,0x51,0x8c, + 0xb2,0x2,0xbe,0x4c,0xe1,0xc,0x8c,0xf8,0xd1,0x23,0x92,0x41,0x69,0x96,0x2c,0xe6, + 0xb7,0x42,0x98,0x12,0x94,0x18,0xb8,0xa5,0x7b,0x17,0xf8,0xec,0x23,0x15,0x26,0xa2, + 0x2,0x37,0x1b,0x96,0xf4,0x6a,0x34,0xc8,0x58,0x52,0x51,0xa8,0xf0,0x4a,0x6b,0x34, + 0x55,0xb5,0xc3,0xc6,0x21,0xaf,0x7d,0xa3,0xa9,0x12,0x8b,0xa6,0xc3,0x3,0x53,0x76, + 0x55,0xe2,0x85,0x32,0x32,0x53,0xb5,0x8f,0x1a,0x98,0x5,0x4e,0x57,0x49,0x43,0x86, + 0x45,0xa9,0x2a,0xbe,0x3d,0x87,0xd4,0x9a,0x69,0xff,0x9c,0x2b,0x73,0x6,0x59,0x70, + 0x3b,0xb3,0xc1,0x46,0x29,0xc8,0x12,0xd8,0x58,0x18,0xf3,0x70,0x3f,0x8a,0x84,0xbf, + 0x29,0xd5,0xa7,0xb9,0x92,0xb1,0x9a,0x20,0x8c,0xeb,0xec,0xf,0xda,0x56,0x51,0x41, + 0xb5,0x75,0xa9,0xb0,0xf6,0x23,0x70,0x81,0xa4,0xc,0xf,0xfe,0x22,0x39,0x73,0x5c, + 0x89,0x88,0xd0,0x92,0x23,0xe5,0x74,0x2c,0x38,0x32,0x5,0x40,0xf2,0x40,0x61,0x99, + 0x68,0x7,0x2f,0xc6,0xba,0x40,0xb7,0xe,0xb6,0xde,0xa0,0xf,0xe1,0x22,0x7b,0x99, + 0x6,0xe5,0x57,0x83,0xf2,0x28,0xb0,0xa5,0x33,0xb3,0xe1,0xd5,0x6e,0x85,0x9c,0x33, + 0x85,0x49,0x7b,0xc3,0xf6,0x8f,0x84,0xa9,0x2a,0xb0,0x51,0xb4,0xa8,0xd,0xe1,0xeb, + 0xc0,0xaf,0x11,0x37,0xc7,0x31,0x3d,0xd5,0xae,0x62,0xaf,0x32,0x31,0x8,0x55,0x24, + 0x51,0x9c,0x3,0x81,0xde,0x94,0xc2,0xe8,0xf2,0xa6,0x4,0x44,0xc9,0x2d,0x25,0x9a, + 0xf5,0x1e,0x5c,0xa6,0xd3,0x61,0x46,0x69,0xac,0xed,0x86,0xa5,0x2,0x39,0x46,0xcb, + 0x9,0x91,0x94,0xf5,0xbe,0x72,0xee,0x4b,0x25,0x8b,0x9e,0xcd,0x41,0x2f,0xe7,0x53, + 0x9b,0x3,0x60,0x2e,0x46,0xc8,0x29,0x3f,0xb5,0xcc,0x62,0x32,0xc7,0xa6,0x98,0x82, + 0xdd,0xce,0x75,0xf3,0x38,0x4,0xd2,0x13,0xb3,0x32,0xc8,0x25,0xa0,0x25,0x9c,0xd4, + 0xd6,0xe2,0x3,0x67,0xe3,0x5b,0xbe,0xac,0xce,0x64,0x87,0xb2,0xe6,0x81,0x93,0xc9, + 0x66,0xfd,0xf9,0xff,0xf1,0xab,0xc2,0xfe,0xc7,0x7f,0xf5,0xe7,0x3f,0x5a,0x66,0x90, + 0xfe,0x17,0x43,0x96,0xa0,0xd6,0xaa,0x36,0xca,0x9,0x34,0xcf,0xc,0xad,0xe4,0x4b, + 0x98,0xf2,0xa7,0x79,0x7b,0x8c,0xa4,0x46,0x34,0xe8,0xdf,0x7,0x2b,0x58,0x6f,0x18, + 0x9c,0xf1,0xc0,0xe8,0x1,0x84,0xc5,0xa9,0x9,0x5d,0xb0,0x4c,0xad,0xc7,0xb4,0x7, + 0xe8,0xd9,0x68,0x99,0xf0,0x96,0x18,0xa8,0x84,0x8c,0x60,0x5b,0xb3,0xd2,0x47,0x30, + 0x7b,0x4f,0x6a,0x1f,0xac,0x44,0x79,0xea,0xeb,0x35,0x9f,0x94,0x3e,0x31,0x59,0xbf, + 0x78,0x3f,0xc0,0x7f,0xf2,0x57,0x7f,0xfe,0x83,0xa2,0xf5,0xcd,0x74,0x55,0xa3,0x67, + 0x96,0x76,0xd0,0x5b,0x9b,0x75,0x43,0x8a,0x5f,0xbd,0xb4,0x2d,0xc,0xa0,0xea,0xf7, + 0x10,0xb8,0x5c,0x6d,0x40,0x2b,0xc7,0xa6,0xa6,0x2d,0x80,0x6e,0x2,0xd2,0xa8,0x8, + 0xf7,0x75,0xfc,0x17,0xff,0xc3,0xff,0x75,0xff,0xbe,0x9f,0xfb,0xf8,0xa4,0x8f,0x3c, + 0x15,0x6b,0xdd,0x8f,0xf4,0xd1,0x65,0x8c,0x8e,0x7d,0x92,0x26,0x51,0x91,0x70,0xda, + 0xf3,0xea,0x4f,0x23,0xf7,0xc5,0xf8,0x46,0xcc,0x4d,0x33,0x75,0xa9,0x23,0x73,0x5f, + 0x9,0xdb,0x55,0x6d,0x3c,0x6c,0xe1,0x28,0x88,0xd1,0xaa,0x3a,0xb5,0x68,0x6a,0x56, + 0xad,0xab,0xc9,0xd6,0xd6,0xeb,0xb2,0xb6,0x61,0xa8,0x42,0x3b,0x33,0x17,0xad,0x4d, + 0x3b,0xb0,0x83,0xb9,0xa4,0xeb,0x58,0x53,0x2,0xa,0x6,0xd2,0x11,0x2a,0xe0,0xfa, + 0x8c,0x4e,0xc0,0x30,0xd2,0x59,0x32,0x5f,0xaf,0xc1,0x52,0xf,0xc8,0x83,0xe3,0x97, + 0x8a,0xa6,0x54,0x88,0xec,0xac,0xc4,0x97,0xe1,0x8e,0xa7,0xa4,0x4a,0xb1,0x19,0x65, + 0x3f,0xb8,0x61,0xe2,0x47,0xfb,0x69,0xe8,0xde,0x6d,0x2c,0x7c,0x72,0xbf,0x76,0x84, + 0x26,0x65,0xc0,0x37,0x85,0x3d,0xa8,0x3a,0xdd,0x14,0x3f,0x77,0x49,0x61,0x24,0xe1, + 0xcd,0x76,0x96,0xc6,0x8d,0xab,0xca,0xfa,0xc3,0x18,0x26,0x20,0xb6,0x8d,0x2f,0x1b, + 0x57,0x23,0x35,0xfc,0xd5,0xab,0x59,0xad,0x9b,0x75,0xff,0xe5,0xe4,0x4a,0x23,0x32, + 0x56,0xca,0xf0,0xed,0xa2,0xc9,0x77,0xdc,0xc1,0x98,0x7c,0xac,0xfa,0x6a,0x8f,0xa8, + 0x61,0xab,0x1b,0xf6,0xe9,0x7,0xd9,0xdb,0x57,0x67,0x69,0x67,0x1,0xd5,0x68,0x15, + 0xd9,0xa,0xe1,0xde,0x5f,0x48,0x45,0xcc,0xcb,0x51,0xaf,0xd3,0x4c,0x7a,0xe6,0x21, + 0x7e,0x76,0x34,0x7a,0x95,0x9d,0x87,0xde,0x18,0xdc,0xbf,0xed,0x93,0x74,0x1e,0xb, + 0x5d,0x85,0xf2,0x93,0xfd,0xde,0x3e,0x9a,0xfd,0x4,0xef,0xf7,0xbb,0x1d,0xb5,0x26, + 0xf0,0x9f,0x71,0xa0,0xa0,0xe2,0xfe,0xea,0x1e,0x62,0xca,0x11,0x85,0xb6,0xee,0x8d, + 0xe6,0xbd,0xad,0x3a,0x88,0x3e,0x72,0xe1,0xe2,0x1a,0x3a,0xf6,0xa4,0xb3,0xae,0x65, + 0xb2,0xb0,0x5b,0x16,0x91,0x21,0xea,0xe3,0xe4,0x1e,0xc2,0x15,0x8d,0xbe,0x8,0x6, + 0xc,0xc5,0x57,0x27,0x65,0x35,0x52,0x1a,0x73,0xe6,0x96,0x1,0x31,0xd1,0x67,0xae, + 0x55,0x7f,0x97,0xb9,0x3e,0x3d,0x0,0x69,0x75,0xa8,0x20,0x66,0xfa,0xa,0xef,0xd, + 0xe1,0x81,0x2c,0xab,0x34,0xd2,0x49,0x1c,0x4,0x26,0x3c,0x43,0xe6,0xfb,0xbb,0xac, + 0x2d,0x43,0x3c,0x67,0x22,0x92,0x25,0xab,0x9d,0xe1,0x78,0xb6,0xef,0x47,0xc0,0x72, + 0x74,0xe3,0x83,0xa7,0x42,0x7f,0xbe,0xff,0x17,0xff,0xd6,0x9d,0x28,0xfc,0xc6,0xcf, + 0x7f,0x0,0x43,0x25,0xa1,0x23,0x58,0x2a,0xfb,0x59,0x5d,0x93,0x3c,0x3b,0x6c,0x79, + 0xd,0x49,0x60,0xda,0xe7,0xfb,0xe5,0x38,0x64,0x1c,0x10,0x34,0x4b,0x69,0x41,0x16, + 0xe8,0x55,0xb8,0x91,0xc,0x2b,0x24,0x61,0x7,0x45,0xa8,0x51,0x24,0x85,0xbe,0xe6, + 0xa8,0x84,0x28,0xa6,0xbe,0x0,0x7b,0x53,0x98,0x2e,0x1f,0xbb,0x27,0x4b,0x38,0x5a, + 0x5b,0x77,0x45,0xc3,0xc,0x14,0xec,0x24,0xd2,0xa,0xe3,0x89,0x46,0x1a,0xac,0x56, + 0x51,0x6c,0x45,0x31,0x34,0x9d,0xe9,0x36,0xfb,0x5b,0x7e,0xe,0xb8,0x34,0x70,0xa8, + 0xba,0x91,0xfb,0xd0,0xb9,0x51,0x93,0xee,0x86,0x46,0x39,0x30,0xbb,0xc1,0xd,0x1a, + 0xc3,0x7d,0x12,0xb6,0xd1,0x3d,0x96,0x83,0x58,0xf7,0x35,0x5d,0xc,0x17,0x38,0x88, + 0xda,0xe5,0xd0,0x63,0xad,0x2e,0xba,0xc3,0x21,0x99,0x64,0x38,0x39,0x22,0x5a,0x4c, + 0xa8,0xd4,0xc4,0xf0,0x3,0x4d,0x1f,0x9f,0x56,0xe8,0xa3,0x3a,0x66,0xcc,0xd6,0x3b, + 0x92,0xea,0x67,0xe,0x6d,0x8f,0xd,0xc1,0x2d,0x4a,0x29,0x6f,0x43,0xd2,0x27,0x41, + 0x18,0x5,0xc0,0x6d,0xe6,0x84,0xf0,0x3,0xd7,0x31,0xd9,0x44,0x1f,0x1a,0x52,0xa4, + 0xf6,0xd3,0xa5,0x44,0x48,0xae,0xb6,0x13,0xe5,0xb5,0x10,0x44,0x8c,0x46,0x42,0xdd, + 0x89,0x81,0x49,0x35,0x4b,0x82,0x4a,0x6,0xa4,0xff,0xa9,0x68,0x1f,0x1d,0xa5,0x7e, + 0x38,0x58,0xd6,0x36,0xf5,0xa0,0x6f,0x3d,0xf6,0xa8,0x94,0xf7,0xf9,0x18,0x5e,0x19, + 0x9a,0x84,0x7c,0x4a,0xb2,0x5c,0x3a,0xf1,0x34,0x87,0x1b,0x43,0xa5,0x97,0xa6,0xca, + 0x6e,0x7d,0xd5,0xee,0xa1,0x7b,0xf,0xcd,0x47,0x4e,0x4a,0x20,0x53,0x98,0x99,0x84, + 0xf5,0x2c,0x4d,0xbd,0xa,0x55,0x6d,0xaa,0x51,0x7b,0x74,0x21,0xd8,0x88,0xff,0x9f, + 0xb1,0x37,0x6b,0xba,0xec,0x3a,0xcf,0xc3,0xde,0x67,0x75,0xff,0x83,0xfc,0xc,0x57, + 0xa2,0x9d,0x8a,0xe3,0xb2,0x2d,0x91,0x92,0x8,0xa2,0xbb,0xbf,0x1e,0x31,0x35,0x66, + 0x70,0x2,0x7,0x11,0x12,0x67,0x4b,0x16,0xc5,0xc4,0x56,0xac,0xc8,0xb6,0x44,0x29, + 0x24,0x25,0x8a,0x83,0x28,0x42,0x9c,0x0,0x90,0x98,0xd1,0xdd,0xe8,0xe1,0xeb,0x6, + 0x7,0x50,0x94,0x15,0xab,0x4a,0xda,0x94,0xa5,0x8b,0x54,0xca,0xf7,0xc9,0x4d,0x2e, + 0x53,0x95,0xb,0xef,0x37,0x17,0x7b,0xd,0xcf,0xf3,0xbe,0xeb,0x80,0x66,0x49,0x64, + 0xf7,0xd7,0xe7,0x3b,0x67,0x9f,0xbd,0xd7,0x5a,0xef,0xf4,0xc,0x64,0x19,0x97,0xc, + 0x25,0x30,0x65,0x1f,0x85,0x75,0x66,0xcc,0xfb,0x75,0xe2,0x54,0x3f,0xfd,0x3f,0xbf, + 0x63,0x7d,0xdf,0xef,0xec,0x1,0xa9,0xcf,0xa6,0xa2,0x77,0xee,0xc4,0xcb,0xc5,0xc2, + 0xb5,0x44,0x61,0x19,0x65,0x2,0x60,0x5a,0xe1,0x89,0xe4,0x2d,0x66,0xc0,0x32,0xaa, + 0x50,0x11,0x67,0x22,0x98,0x8b,0x19,0x21,0xf3,0x54,0x9a,0x1e,0x75,0xff,0x7e,0x1e, + 0x8a,0x16,0x8c,0xd6,0xa2,0x13,0x8b,0xc0,0xeb,0x85,0x39,0x72,0xc1,0xd3,0xdb,0xe0, + 0x84,0x45,0x40,0xd4,0x20,0x70,0x9e,0x3,0xc5,0x87,0x83,0x0,0x8c,0x9a,0x72,0x64, + 0x82,0x62,0x95,0x91,0xfa,0x1a,0xde,0xc2,0x8b,0x1c,0xa9,0xdf,0x24,0x40,0x99,0xa, + 0x41,0x6d,0x15,0x70,0x99,0x1a,0xde,0x10,0xe6,0x23,0x2a,0x66,0x41,0xaf,0x1,0xc9, + 0x45,0x2d,0x52,0x2a,0x3d,0x78,0x94,0x87,0xe7,0xeb,0x8a,0x23,0x60,0x7b,0xdf,0x8c, + 0xdd,0x0,0x39,0x33,0x23,0x5,0xab,0x3,0x7c,0x4b,0x63,0xae,0xf0,0x41,0xb3,0x98, + 0xc4,0xd1,0x87,0xc5,0x10,0x65,0x71,0x84,0x63,0x9e,0xd6,0xd1,0xc,0x4c,0xe3,0xb3, + 0x67,0x64,0x3a,0x57,0xb7,0xa2,0xa6,0x36,0x69,0x63,0x17,0x3d,0xce,0x38,0x89,0x48, + 0x6c,0x44,0x4c,0xf0,0x37,0xac,0xe9,0x80,0x5c,0xad,0x91,0xa3,0x8b,0x9c,0x2a,0xfb, + 0xeb,0xcb,0x54,0xec,0x6c,0xa2,0xc2,0x9b,0xc6,0x9a,0x71,0x1c,0x9b,0xd6,0x18,0xd1, + 0xb7,0x62,0x75,0xef,0x13,0x91,0x2b,0xc5,0xfe,0x4c,0x66,0xe1,0xcc,0xef,0x36,0xb3, + 0xf7,0xfc,0x2f,0x6f,0x2c,0xef,0xfd,0x37,0x6f,0x2c,0x8,0x1a,0xf8,0x91,0xf5,0xa8, + 0xe3,0x8a,0xa9,0x88,0x40,0xb0,0x1,0x66,0x6c,0xc4,0x18,0x2f,0x22,0x8c,0x6e,0x2c, + 0x9e,0xc1,0x6,0xa5,0x98,0x46,0x5c,0x35,0xfb,0x7e,0x47,0x2d,0x8,0x3f,0xd0,0xc5, + 0xeb,0x49,0x2f,0x6b,0x19,0x4,0x53,0x56,0xa8,0xda,0xa0,0xb,0x2,0x83,0xc0,0x78, + 0xe4,0xcc,0x39,0x92,0x8d,0x80,0x6b,0x89,0x3a,0x52,0x3d,0xc1,0x86,0x34,0x90,0x26, + 0x69,0x7f,0xb7,0x52,0xf5,0x98,0x7c,0x43,0x31,0x49,0xee,0x4c,0xc9,0xb,0x5d,0xa2, + 0x9,0x53,0xe3,0x10,0xde,0x81,0xf5,0x55,0xa,0x73,0xec,0xfc,0xa0,0x4f,0x8,0xf2, + 0x5e,0xb5,0xc3,0x8a,0x79,0x9,0x18,0x36,0x43,0xae,0x22,0x50,0x4,0x26,0xfc,0x43, + 0x6,0x8c,0xf0,0x7b,0x24,0xa0,0xcd,0xc4,0xfa,0xb8,0xcd,0x30,0x3c,0x38,0x8d,0x75, + 0x7,0xb2,0x74,0x61,0x7a,0xd0,0x78,0x77,0xe9,0xe2,0x88,0x8c,0xc0,0xe5,0x45,0x32, + 0x70,0x8b,0x77,0x1e,0x11,0xc0,0x20,0x80,0x23,0x4b,0x3c,0xfa,0x64,0xff,0xc4,0xea, + 0x7c,0x8,0xad,0x55,0x45,0x35,0x11,0xaa,0x7f,0xf8,0xed,0x72,0x4a,0xce,0xff,0xce, + 0x72,0x8e,0x8,0x3a,0xfc,0x3d,0xf3,0x84,0xd9,0x7b,0x7e,0xfb,0x8d,0xe5,0xcf,0xff, + 0xd5,0x5d,0x6b,0x9f,0x17,0xd1,0x6,0x62,0x16,0x41,0xd4,0xef,0x8f,0x9d,0x93,0x79, + 0x60,0x57,0x84,0xfa,0xf8,0xfa,0x6e,0x53,0x69,0xa0,0x60,0x99,0xcb,0xf7,0x52,0x18, + 0x9e,0x20,0x66,0x0,0x53,0xf0,0x66,0xc0,0xc7,0x88,0x74,0x9d,0x2,0x9d,0xe,0x39, + 0xc3,0x67,0x30,0x65,0x4,0x76,0x22,0x56,0xb7,0xa9,0xa,0xcc,0x33,0xb4,0x99,0x8b, + 0xec,0x34,0xca,0x70,0x22,0x89,0x49,0xf0,0x92,0x3,0x42,0xe5,0x2b,0x85,0x62,0x7, + 0xd1,0x99,0x4c,0xc1,0x39,0xd3,0xfe,0x4c,0x78,0xd4,0xe2,0x76,0x37,0x29,0x6b,0x63, + 0xec,0x78,0xcf,0x6f,0xbf,0xb1,0xbc,0xe7,0x5f,0xbf,0xb1,0x48,0x8b,0xbb,0x39,0x92, + 0xd1,0x9a,0xf0,0x8,0xe6,0x55,0xa1,0xb5,0x3,0xf8,0x1b,0xde,0x93,0xc1,0x1,0x51, + 0x14,0x5,0x5d,0x2,0x58,0xa3,0xde,0x49,0xfb,0x9d,0x28,0x7a,0x43,0x8e,0x16,0x8a, + 0xdc,0xe,0xb3,0xdb,0x24,0xb0,0x2f,0x46,0x56,0x10,0x8f,0xec,0x78,0x5e,0x38,0x31, + 0x54,0x7a,0x97,0x6c,0x56,0x6d,0xa0,0x5e,0x2b,0x14,0x15,0xef,0xad,0x3a,0xa4,0x6b, + 0xec,0x49,0x3b,0x3d,0xa3,0x21,0x7a,0x35,0x14,0x3,0xc7,0xa8,0xc0,0x33,0x2b,0xc3, + 0xf2,0xf9,0xe7,0x33,0x67,0x41,0x4,0x7c,0x59,0x40,0xb8,0x8b,0xdf,0x38,0x54,0x3, + 0xae,0x55,0xca,0x51,0x57,0x23,0x36,0xa8,0x0,0x9b,0x88,0x78,0xcd,0xb0,0xec,0x51, + 0x51,0x2e,0x89,0xfe,0xe9,0x79,0x18,0x98,0x22,0x8c,0x42,0x7,0xe8,0x7b,0x13,0x48, + 0x91,0x55,0x35,0x3d,0xd4,0x27,0xc3,0xfb,0x5c,0x13,0x79,0xde,0xa3,0xfc,0xfb,0x59, + 0xfe,0x2,0x86,0x89,0x53,0xa2,0x20,0xfb,0x13,0x42,0x1d,0x56,0x10,0x10,0x87,0x40, + 0x84,0xa7,0x86,0x8c,0x3a,0x54,0x64,0x90,0xac,0xce,0x26,0x2,0xfd,0x41,0x7,0x17, + 0x73,0xdb,0xbf,0x83,0xb4,0x1e,0x8,0x84,0x3d,0x58,0xb6,0x4e,0x68,0x5b,0x7c,0x30, + 0x51,0xfb,0xf7,0xdd,0xbf,0xfd,0xfd,0xe5,0x1b,0xbf,0x7d,0xd7,0xea,0xc9,0xae,0xd3, + 0x82,0x88,0xc,0x7a,0xeb,0xf,0x16,0x9d,0x89,0xc2,0xc2,0x49,0xc8,0xf5,0x3,0x2a, + 0x63,0xb2,0xe1,0xdf,0x2,0xa9,0x79,0x48,0x8,0x5,0xd1,0x9d,0x4d,0x5,0x3,0x40, + 0x98,0x82,0x9e,0xd9,0xbb,0x25,0x21,0xb,0xee,0x50,0xf8,0x44,0x50,0x44,0x54,0x96, + 0xe4,0xcf,0x96,0x5c,0xd8,0x1a,0x1a,0xf7,0x1b,0xbf,0x7d,0xd7,0xfa,0xee,0x7f,0xfd, + 0xc6,0x62,0x41,0x8f,0x3c,0x3d,0x2b,0xfb,0xd9,0xc1,0xcb,0xf4,0xc8,0xb5,0x99,0xb, + 0x6e,0x4e,0x8a,0x82,0x81,0x5,0x26,0xaa,0x68,0x16,0x53,0xdb,0x48,0xc7,0x81,0xbd, + 0xd5,0x18,0xd0,0x82,0xc8,0xc7,0x9c,0x5a,0x47,0x16,0xa3,0xae,0xeb,0x3d,0xe9,0xc9, + 0x10,0x60,0x2c,0x8a,0x9d,0x58,0x50,0xb5,0xf3,0xe4,0xa9,0xe,0x75,0x56,0x9b,0x64, + 0xb4,0x4e,0x6b,0xcd,0x2b,0xda,0x16,0xb4,0xae,0x1d,0x79,0xbf,0x80,0x12,0x23,0x48, + 0x45,0x30,0x2,0x7,0x48,0xf4,0xa8,0x4b,0xa,0x7,0xd8,0xea,0xd0,0xce,0xa7,0x49, + 0xae,0xab,0xca,0x59,0x5b,0x87,0x1e,0x92,0x11,0xb6,0xb9,0x85,0xb1,0xcd,0x2f,0x6, + 0x63,0x80,0x3,0xa0,0x30,0x5c,0xa0,0xd8,0xa,0xe1,0x6e,0x43,0xed,0x4c,0x63,0xb0, + 0xe2,0x6a,0xe,0xfa,0xfd,0x21,0xaa,0x68,0xed,0x3a,0x69,0x27,0x3a,0x77,0x2c,0x4d, + 0xbb,0x98,0x93,0x44,0x36,0xb3,0x6c,0xf3,0xe,0xd1,0xfb,0xc3,0x49,0x15,0x12,0x12, + 0x3d,0x75,0xde,0xac,0x64,0xbb,0x6b,0x8c,0xbe,0x4f,0x96,0x6c,0x6e,0xdf,0xb7,0x48, + 0x27,0x35,0x8e,0x9c,0x9c,0xe8,0x8c,0x39,0x78,0x96,0x94,0xec,0xcd,0x60,0x5e,0x59, + 0xef,0x48,0x7f,0x1f,0x93,0x60,0x16,0x93,0xd5,0x1c,0xdc,0xb8,0xe3,0x68,0x93,0x60, + 0xa7,0xf7,0x99,0x65,0xcb,0xfb,0x7d,0x86,0x2,0xda,0x8c,0x3a,0xbc,0x7d,0x67,0xb, + 0xed,0x6c,0xe8,0xb0,0x38,0x8b,0x72,0x11,0x7d,0xf2,0xdd,0xff,0xea,0xf6,0xf2,0x8d, + 0x7f,0x73,0xf7,0xaa,0xf2,0xbc,0xae,0x82,0x91,0x2a,0xd9,0x99,0x84,0x6a,0x64,0xdc, + 0xc4,0x6b,0x3a,0xce,0x37,0xba,0x72,0xa4,0x57,0x94,0x3b,0x3c,0x71,0xde,0x82,0x5d, + 0xce,0x7c,0x5e,0x35,0xd1,0x2,0x56,0xdc,0xd,0x12,0x4a,0x5c,0xda,0x96,0x69,0x1e, + 0x1d,0x7,0xe5,0x7a,0xf4,0xbb,0x1d,0x0,0x89,0x98,0x4d,0x35,0x8b,0xc5,0xd9,0x86, + 0x90,0x85,0x5a,0xaf,0x91,0x8b,0x17,0x14,0x7c,0x1,0x42,0xb8,0x7a,0x14,0xb1,0x98, + 0x7e,0xf6,0x1c,0xd4,0x64,0xae,0xa0,0x2a,0x9b,0xb4,0x44,0xa7,0x31,0x89,0x1,0x81, + 0xd1,0xb1,0x28,0x5a,0xbd,0xfa,0xec,0x7b,0x16,0x45,0x67,0x6f,0x73,0xf0,0x63,0xbc, + 0xf5,0x43,0x3,0x3e,0xdc,0x43,0x6,0x42,0xb6,0x7f,0xab,0x99,0x28,0x3b,0xe7,0x71, + 0xa0,0xf1,0xe,0x24,0x22,0xfd,0x64,0x76,0x54,0x72,0xb,0xf8,0x2,0x5a,0x1,0x1e, + 0x64,0x1c,0xd5,0xbf,0xcd,0xc4,0xea,0x34,0xda,0x45,0x76,0x84,0xac,0xd9,0x13,0xff, + 0xd3,0x9d,0xc5,0xcc,0xec,0xdb,0xbf,0x73,0xd7,0xea,0x98,0x20,0x6a,0x7d,0xd0,0x20, + 0x13,0x98,0x87,0x2c,0x1a,0xdd,0x63,0x2b,0xcc,0xa5,0x53,0x2,0x77,0xa9,0x72,0x19, + 0x28,0x28,0x6b,0x8b,0xe6,0xed,0xe,0x85,0x5d,0xf6,0xfb,0xd8,0x2a,0x54,0x1e,0x63, + 0x42,0xdb,0xfb,0x8a,0x27,0x83,0xb6,0x27,0xdd,0xb2,0xeb,0x1a,0x72,0xf2,0x82,0x3, + 0xbe,0x5d,0x5c,0x21,0xbb,0x23,0x28,0x90,0x21,0xb1,0x0,0xa6,0x6c,0x61,0xe4,0xf1, + 0x1a,0xcf,0x2e,0x93,0x93,0x5f,0x38,0xb8,0xf5,0x18,0x21,0xb9,0xcb,0x84,0x35,0x8b, + 0x1d,0x9c,0x22,0x62,0x39,0x49,0xb8,0x19,0x13,0x97,0xe5,0x38,0xf2,0x9f,0x7d,0x1d, + 0x9f,0xa1,0xb5,0xe7,0xa7,0x90,0x82,0xb,0xe7,0x1a,0x48,0xd1,0xb1,0xb0,0x9,0xc1, + 0x24,0xe,0x7a,0x6a,0x83,0x12,0x8d,0x15,0x1,0x2b,0x44,0xeb,0xb2,0xfb,0xbb,0x73, + 0x46,0xe9,0x24,0x14,0x23,0x63,0xec,0xe1,0x7f,0x1,0xf2,0x58,0x46,0xc0,0xb2,0xc8, + 0xe1,0x41,0xbe,0x5,0xa0,0x79,0x1c,0x7c,0x2,0x72,0x6f,0x82,0x32,0x8a,0x9a,0xe, + 0xb8,0x80,0x8,0x30,0xd,0xd5,0x76,0xa6,0xf6,0x8c,0xe6,0x6a,0xf7,0x13,0xf1,0x30, + 0xd2,0x42,0xf6,0xd9,0x24,0x9d,0x12,0x9b,0xb4,0xaf,0xf9,0x1c,0x4c,0x33,0xf,0x27, + 0x37,0xc6,0x2d,0xc,0xcb,0x38,0x69,0xdc,0x4c,0xa8,0x8f,0x72,0x53,0x12,0x6,0x29, + 0x4d,0xcf,0xd2,0x3d,0x40,0x14,0x72,0x38,0x60,0x73,0x5e,0x32,0x2f,0x15,0x49,0x90, + 0xc4,0x66,0x1c,0x47,0x59,0xcc,0x25,0xb7,0xd5,0x73,0xc1,0x6c,0xa4,0x5e,0x60,0x82, + 0x21,0x9d,0x38,0x11,0xc5,0x8e,0xa6,0xb7,0x4b,0xd,0xf3,0xb2,0x88,0xfa,0x8e,0x15, + 0x3a,0x57,0xa6,0xa0,0xca,0x95,0x67,0x39,0x46,0x5c,0xe4,0x58,0x15,0x72,0x30,0x37, + 0x9a,0x7,0x22,0x2a,0x52,0xf1,0x18,0x81,0xf0,0x5,0xbd,0xe2,0xf1,0x89,0x7b,0xd5, + 0x6c,0x36,0x66,0x16,0x68,0x37,0xa0,0x79,0x36,0x9b,0xb5,0x20,0xb5,0xc5,0x46,0x5, + 0xae,0x6,0x3b,0xe2,0xdd,0xed,0x44,0xc3,0xa9,0x15,0x91,0x93,0x92,0x9,0xc8,0x47, + 0xfd,0x89,0xcf,0xbc,0xb1,0x7c,0xfb,0x7f,0x7d,0xe7,0x6a,0x80,0x7d,0xeb,0x77,0xee, + 0x5a,0x9f,0xf8,0xcc,0x1b,0xb,0x4b,0x21,0x8a,0x3e,0xbc,0xf0,0xce,0x89,0x92,0x44, + 0x73,0x4b,0x39,0x5c,0x9b,0x35,0x29,0x9c,0x46,0x29,0xb1,0xdb,0x11,0xfe,0xe8,0x8c, + 0x59,0xf0,0x54,0x49,0x20,0x82,0x64,0xea,0x33,0x55,0xec,0x84,0x5e,0x9b,0x53,0x76, + 0xef,0x41,0xb0,0xc3,0xc2,0xb4,0x55,0xb,0x7e,0xea,0x7c,0xc0,0x26,0x8a,0x53,0xb9, + 0xfa,0x7,0xb2,0xac,0x6b,0xf6,0x21,0xd0,0x1,0x4c,0x76,0x68,0x9c,0xe8,0xfe,0x23, + 0xa,0x1d,0x22,0xf0,0xf9,0xf,0x50,0x60,0x90,0xdb,0x96,0x91,0xcb,0x3d,0xae,0x7b, + 0x3c,0x43,0xf,0x73,0xcf,0xc7,0x3f,0x73,0x67,0x79,0xfc,0x33,0x77,0x96,0x43,0x98, + 0x7,0xf,0x17,0x38,0x2a,0xd0,0xe0,0xdd,0x76,0xc0,0x29,0x8c,0x9d,0xee,0x3c,0x76, + 0xe6,0xe,0xf0,0x8e,0xb5,0x9d,0x7e,0x68,0xe6,0xbe,0xff,0xe9,0xf1,0xcf,0xdc,0x59, + 0x9e,0xf8,0xcc,0x9e,0xf4,0x8d,0xe0,0x5,0x6d,0x85,0xfb,0xa4,0xef,0xeb,0x33,0x8e, + 0x30,0x27,0x5b,0x8,0xe3,0xba,0x91,0xac,0x1,0xd1,0x82,0x77,0xec,0x6f,0x5e,0xaf, + 0xd9,0xf1,0x4b,0x16,0xb2,0x54,0xf4,0x8a,0x99,0x23,0xd6,0x1,0x75,0x50,0x10,0x75, + 0xec,0x1b,0x3,0x20,0xea,0xc4,0xcf,0xf4,0x40,0xe4,0x43,0xe3,0x48,0xc3,0x72,0x27, + 0xd7,0x42,0x52,0x10,0xbb,0x8e,0x33,0x59,0xe8,0x43,0xc5,0x62,0xd0,0x66,0xb7,0x98, + 0x90,0xce,0xac,0xb,0x27,0x75,0xba,0xb4,0xbf,0xdd,0xec,0xdb,0xbf,0x7b,0xf7,0xfa, + 0xf8,0x6f,0xdd,0x5e,0x26,0xe1,0x63,0x54,0xd0,0xb3,0xef,0x57,0xf5,0xdc,0x33,0xe6, + 0x82,0x3b,0x9b,0x45,0x8a,0xb6,0xe8,0x59,0xe0,0x7,0x5b,0x82,0xb3,0x80,0x6e,0x13, + 0xe9,0xec,0x4c,0xfa,0x2f,0xaa,0x7,0x8e,0x7e,0xb0,0x26,0x8e,0xdb,0x44,0xa1,0x46, + 0x81,0x8,0x5c,0xbd,0x59,0x2,0x8d,0x75,0xc,0x25,0x5b,0x4c,0xb6,0x23,0xa2,0x66, + 0x5e,0x8f,0xff,0xd6,0x1b,0xcb,0xe3,0x9f,0xbe,0xb3,0x58,0x3c,0xa0,0xd,0x49,0xa1, + 0x4a,0xcb,0x13,0x12,0x93,0x8,0xb3,0xa5,0x38,0x3b,0xfe,0xf6,0xef,0xbe,0x73,0x7d, + 0xec,0xd3,0x75,0x7e,0xd7,0xde,0xdd,0x77,0x8d,0xe0,0x8,0x4,0x63,0x41,0xfe,0x2e, + 0xbe,0x5f,0x67,0x4c,0x8e,0x61,0x69,0xa,0x83,0x58,0x67,0x4a,0x9,0xe1,0x2e,0xed, + 0xda,0xb8,0xa9,0x9c,0x13,0x89,0x6e,0xf,0xa,0x12,0x9d,0xc8,0x33,0x58,0x1c,0x50, + 0x9d,0x1b,0x18,0x1,0x13,0x8e,0x24,0x18,0xf9,0xbe,0x59,0xe,0x44,0x61,0xb1,0xfa, + 0x66,0xf6,0xf8,0x6f,0xdd,0x59,0xbe,0xfd,0xbb,0xef,0x5c,0x39,0x3,0xd7,0x79,0x93, + 0x25,0x8f,0x75,0x13,0xc1,0x91,0xd4,0x25,0xb6,0x99,0xa2,0x56,0x53,0xa8,0x43,0x15, + 0x2d,0xc4,0x5b,0xe1,0x30,0x0,0x51,0x62,0x9a,0x22,0x9e,0x2d,0x52,0xd1,0x68,0x56, + 0xc6,0x1b,0xc,0x53,0xe8,0x63,0x48,0xe2,0xf7,0xf,0x7b,0xec,0xd3,0x77,0x96,0xc7, + 0x3e,0x7d,0x67,0xf1,0xd8,0x3e,0x4,0x26,0x7a,0x17,0xd1,0xe5,0x20,0xb6,0xfa,0xc9, + 0xa2,0x93,0x5a,0xf2,0x59,0x4d,0x2e,0x28,0xb1,0x89,0x8d,0x2c,0xb5,0x41,0x2d,0xfb, + 0x51,0xb3,0x9b,0xc2,0x78,0x1f,0x76,0xcf,0xaa,0x7b,0xc4,0x5d,0x83,0x4d,0xfd,0xbd, + 0xc7,0x3e,0x7d,0x7b,0x79,0xec,0xd3,0x77,0x96,0x21,0xed,0x39,0xc4,0x5b,0xc0,0x46, + 0x3b,0xae,0x33,0xdf,0x5e,0xc9,0x8b,0x30,0x8f,0x8b,0x56,0x3,0x78,0x9d,0xc6,0x71, + 0x1c,0x89,0x2c,0x21,0xa2,0xc8,0x81,0x94,0x0,0x27,0x40,0x97,0x47,0xd5,0x8e,0x0, + 0x9f,0x86,0xc9,0x4c,0x17,0x80,0x3d,0xf6,0x9b,0xb7,0x97,0xef,0xfc,0xdb,0xbb,0xd7, + 0x3e,0xef,0x44,0xae,0xc0,0x11,0x3,0x86,0x1f,0x1a,0xff,0x1c,0x0,0xd5,0x5,0xe1, + 0x71,0x4c,0xc6,0x43,0x12,0xbb,0x58,0x29,0x2e,0x52,0xf5,0x26,0x76,0xb0,0x71,0x5f, + 0xa3,0xa9,0xff,0xc5,0x96,0xec,0x41,0x1c,0x8,0xe6,0xd9,0xe1,0xb4,0x3,0xb,0xad, + 0xc8,0x71,0x0,0xe3,0x11,0xf3,0x32,0xfc,0xac,0xcf,0x8d,0x38,0x7,0x3b,0x80,0x37, + 0xc9,0xf6,0xc3,0x36,0xb1,0xd9,0xc5,0xc,0x52,0x3d,0xd1,0x6a,0x1f,0x1d,0x23,0xb6, + 0x3d,0x26,0xb5,0x4d,0x4c,0x52,0x83,0xda,0xe5,0xeb,0x78,0x2c,0xcb,0x95,0x7c,0x56, + 0xe4,0x8c,0xe2,0x40,0x8,0xce,0x96,0x93,0xcc,0x1c,0xa0,0x22,0x86,0xee,0x70,0x6b, + 0x21,0x9,0x2d,0x73,0xdf,0x37,0x27,0x67,0xad,0x6e,0x76,0x92,0x12,0x7d,0x24,0xb0, + 0x7c,0xa7,0xb,0xa8,0x29,0x4a,0x18,0xe,0x8d,0xe7,0x10,0x9e,0xdd,0x29,0xf3,0xad, + 0x7,0xc8,0x6f,0xde,0x59,0x60,0x66,0xcf,0xfc,0xdb,0xbb,0xd6,0x47,0x3f,0xfd,0xc6, + 0x92,0x5c,0x7e,0x2,0xf0,0x60,0x56,0x8d,0x59,0xe0,0x19,0x3f,0xfa,0x9b,0x77,0x96, + 0x67,0xfe,0xdd,0x3b,0x57,0x98,0xd9,0x33,0xff,0x6e,0x4,0x26,0x99,0xb,0x4f,0x36, + 0x6e,0xa4,0x38,0xc9,0xd0,0x1,0x66,0xf0,0xc1,0x35,0xef,0xde,0xe8,0x25,0xb6,0xaf, + 0x21,0xe2,0x30,0x36,0xe5,0x19,0x8f,0x76,0x3c,0xca,0xce,0x53,0x96,0x20,0x44,0xdc, + 0xdf,0x19,0xa5,0x6a,0x50,0x85,0xd1,0x2d,0x3a,0x65,0x84,0xe8,0x59,0xf0,0x45,0xe8, + 0xad,0xae,0x8b,0xc6,0x89,0xdf,0xfd,0xcc,0xbf,0x6f,0xf7,0xab,0x5d,0x23,0xdb,0xfa, + 0x51,0xe2,0xe7,0xec,0xe2,0x7,0xb2,0xa,0x45,0x4e,0xad,0x3d,0x2,0xe5,0xb8,0x72, + 0x20,0x47,0xb6,0xd9,0x17,0xe9,0x5a,0xc6,0x44,0x77,0x4c,0xfa,0xd9,0x10,0xbd,0x71, + 0xa6,0xa2,0xb9,0x7,0x20,0x9d,0x5b,0xa2,0xcc,0x8c,0x96,0x39,0x42,0x65,0xe1,0x74, + 0xdf,0x90,0x7,0xeb,0x7,0xe,0x36,0xbc,0x5,0x90,0x2c,0x8d,0x5c,0x78,0xcc,0xe5, + 0x48,0x4c,0x6,0x1c,0x98,0x4c,0x41,0x7c,0x38,0xed,0xad,0xfa,0x76,0xc9,0xae,0x20, + 0xe1,0xd,0x58,0x30,0x27,0x18,0x5a,0x60,0x7a,0xf1,0xe3,0x20,0xf3,0xa0,0xdb,0x90, + 0xbb,0x77,0xca,0x6d,0xd1,0xd1,0x53,0x31,0x11,0x40,0x71,0x4,0x12,0x3,0xa6,0xa3, + 0x81,0xa9,0xb,0x6a,0xa8,0xda,0x67,0x66,0x4a,0x49,0xa0,0x28,0xfa,0x53,0xc7,0x68, + 0x5d,0x42,0x72,0xc0,0xfd,0x73,0x51,0xa4,0x3a,0xe0,0x45,0x10,0xc0,0xa1,0x6a,0x81, + 0x3b,0x8a,0x84,0x68,0x97,0x39,0x7d,0x96,0x41,0x9d,0xaa,0x8f,0xc5,0x3c,0x8f,0x5, + 0x3c,0x38,0x7f,0xcd,0xa1,0x96,0x2e,0x1f,0xc1,0xda,0xef,0x79,0x4,0x1,0xd5,0x9a, + 0x31,0x35,0xfc,0x81,0x7b,0x12,0x27,0xe2,0x96,0x77,0xe0,0xf1,0xd6,0xf7,0xde,0xf7, + 0xea,0xa3,0xbf,0xb1,0x57,0xc8,0xcf,0xfe,0xde,0xa9,0x55,0xaa,0x51,0x96,0xf8,0x75, + 0xd3,0x31,0x1d,0xa1,0xe2,0x9d,0xd9,0xa4,0xf4,0xfd,0x1e,0xfd,0x97,0xc7,0x8b,0x99, + 0xd9,0x73,0xbf,0x7f,0x6a,0x65,0x8a,0xb4,0xc1,0xec,0xd1,0xdf,0x38,0x5e,0x9e,0xf9, + 0xbd,0x53,0xab,0x88,0x2,0x89,0xf4,0xb0,0x8f,0x19,0x79,0x48,0xf2,0xdb,0x6a,0x7e, + 0xf6,0xdf,0x9f,0x5a,0x1f,0xf9,0x97,0xc7,0xcb,0xb3,0xbf,0x77,0x6a,0xed,0x53,0x51, + 0x77,0xe1,0xd4,0x1f,0xc2,0x4a,0xc1,0x33,0xb7,0xfe,0xd1,0xdf,0x38,0xee,0xf7,0xa1, + 0x63,0xa2,0x92,0xfe,0x80,0x25,0x8a,0x35,0x3f,0xaf,0x93,0xb3,0x20,0x16,0x3,0xa7, + 0x80,0x3d,0xbc,0x4c,0x8c,0xad,0x83,0xcb,0x52,0x54,0x0,0xd6,0x15,0x40,0x59,0xc5, + 0x98,0x65,0x3c,0xfb,0xfb,0xef,0x5c,0xad,0x70,0xa6,0xe9,0xc9,0xb3,0x39,0x82,0xe9, + 0x1e,0xa9,0xb,0xe1,0xb9,0xdf,0xbf,0x7b,0x1d,0x74,0x5,0xf,0xf3,0xe4,0x61,0x4a, + 0xd1,0xd,0x29,0x28,0x23,0x1b,0x87,0x91,0x2b,0x2b,0xc8,0x91,0x16,0x3c,0xb7,0xd6, + 0xe0,0x1e,0x3e,0x3f,0xf6,0x86,0x48,0x5e,0x85,0xe,0x69,0x56,0xa,0xeb,0x82,0x14, + 0x22,0x84,0xe2,0x79,0xe,0xc5,0x54,0x12,0x37,0x51,0xee,0x12,0xe0,0xc8,0x66,0xf6, + 0xdc,0x67,0xdf,0xb9,0x3e,0xf2,0x1b,0x77,0x96,0x3e,0xd7,0xb6,0x80,0x5e,0xb7,0xb8, + 0x40,0x3c,0xf8,0x72,0x87,0x3,0x84,0x5c,0xae,0x7a,0x46,0x9,0xed,0x2,0xa4,0x59, + 0x53,0xe2,0xb8,0xb9,0x8,0xa0,0x24,0xd,0xf2,0x30,0x8f,0x8e,0x1,0x99,0xe7,0x6b, + 0x6e,0x1,0x95,0x2f,0x80,0x83,0x68,0xc7,0x19,0xb3,0xe5,0xfd,0x7,0xfd,0xb9,0x7d, + 0xb6,0x3e,0xb7,0x39,0x6f,0x51,0x32,0xe9,0xb7,0xec,0x8a,0xfd,0x8c,0x7f,0x49,0xff, + 0x1e,0xb6,0xcf,0x23,0xbf,0x71,0x67,0x5c,0xcf,0x3c,0xf2,0x4f,0xf0,0x28,0xec,0xb9, + 0xe9,0x99,0x49,0xe6,0x39,0x98,0xbc,0xd5,0x55,0x8a,0xe8,0xe9,0xa6,0x50,0x8d,0xb9, + 0x39,0xb7,0xf7,0x80,0x17,0xef,0x6f,0x74,0x4e,0x9,0xf9,0xa3,0xe8,0x17,0xc8,0xfe, + 0xf6,0x21,0x32,0x24,0xe,0xf0,0x51,0xf1,0xd0,0x26,0x38,0x18,0xca,0x44,0x44,0xd7, + 0x32,0x5,0x48,0xf4,0xae,0xdc,0xc3,0xbf,0x7e,0xbc,0x3c,0xf7,0xfb,0xf5,0x50,0xdf, + 0x4c,0x94,0xd2,0xd0,0x3c,0xeb,0x5d,0x3b,0x76,0x4c,0xab,0x6a,0x2a,0x66,0x3c,0xdd, + 0x12,0xc4,0x8f,0x48,0x10,0x40,0xc6,0x3e,0x2e,0xa0,0x9c,0xb1,0xef,0xdd,0xe3,0xfd, + 0x21,0x59,0x67,0x9f,0x29,0x76,0x2a,0x36,0xc6,0xe,0x30,0x90,0xfa,0xf9,0xd7,0x3, + 0xac,0x27,0x16,0x3,0x48,0x0,0x4c,0x3,0x88,0x4b,0x70,0x77,0x64,0x3f,0x7a,0xb7, + 0x0,0x8e,0xe,0xeb,0xdf,0x25,0xb1,0x14,0x93,0xee,0x34,0x4b,0x76,0x57,0xdd,0x11, + 0x40,0x4d,0x6e,0x78,0x4d,0x7a,0x38,0x23,0x7d,0xb2,0xef,0x7d,0x2,0x7a,0xe5,0x35, + 0xdb,0x18,0x2,0x10,0xe0,0xd9,0xa8,0xa0,0x1d,0x6a,0x56,0xc3,0x54,0x69,0xe6,0xa2, + 0xb,0xc4,0x69,0x13,0x85,0x1,0xb,0xb6,0x4c,0xfd,0x3c,0x95,0x9f,0x6f,0x11,0xff, + 0xa,0x61,0xc7,0xbb,0x3c,0x7b,0x4f,0x31,0xb1,0x1b,0x21,0x3,0x13,0xa0,0x88,0xa9, + 0x89,0x86,0x8b,0x33,0x93,0xa2,0x97,0x1d,0x41,0x32,0x33,0x18,0xb2,0x30,0x82,0xd7, + 0x99,0x18,0x6f,0x6e,0xf,0xff,0xfa,0xed,0xe5,0xb9,0xcf,0xbe,0x73,0x75,0xe2,0xe6, + 0xf5,0x4b,0x17,0x34,0x36,0x52,0x60,0x1d,0xb3,0x26,0x4f,0x60,0x3d,0x8f,0x2d,0x10, + 0x9a,0x3f,0xbb,0x87,0xef,0xa,0xcf,0xa8,0xf9,0xd4,0x6,0xc9,0x99,0xbf,0x7,0xeb, + 0xbf,0x84,0xf2,0x97,0x9b,0x69,0x41,0x97,0x99,0x84,0x3f,0x12,0x7f,0x78,0xd6,0xca, + 0xd2,0xd9,0x59,0xd2,0xcc,0x34,0x45,0xb8,0x47,0x4,0x25,0xcf,0x2e,0x67,0x68,0x73, + 0xf5,0xed,0xe,0xb3,0xdd,0xfa,0xb1,0xdf,0xfd,0xec,0xdd,0xeb,0xc3,0xbf,0x7e,0x67, + 0xb1,0xd0,0xd5,0x7c,0xee,0xb3,0x77,0xaf,0xf,0xff,0xfa,0xed,0x3e,0x43,0x7d,0xf8, + 0xd7,0xef,0x2c,0xf,0xff,0x8b,0xdb,0x4b,0xfb,0xc5,0xfe,0xf7,0x83,0xf4,0xf2,0x68, + 0x29,0x39,0x19,0x11,0xd,0xb8,0xd3,0xe1,0x2a,0xe8,0x80,0xde,0x33,0x7f,0x6f,0x65, + 0x3,0xcc,0x6a,0xea,0x88,0x15,0x41,0xba,0x6f,0x79,0x2e,0x8b,0x9c,0xc0,0xd2,0xda, + 0x79,0xf8,0x5f,0xdc,0xae,0xf7,0xc3,0xc8,0xd4,0x46,0x65,0x8c,0x5d,0xb0,0xa2,0x44, + 0xe5,0x9b,0xb5,0x26,0x67,0x93,0x8b,0x94,0xf4,0x42,0x7c,0xe,0x4,0x83,0x11,0xcc, + 0x7c,0xd8,0xbc,0x25,0x69,0x89,0x8b,0xfa,0xba,0xae,0xd7,0xde,0x29,0xea,0xaf,0x7f, + 0xb,0x55,0xb2,0xb6,0xff,0x6b,0xd0,0xfa,0xee,0x67,0x4f,0xad,0xf,0x7f,0xea,0x78, + 0x89,0xd7,0x89,0x30,0x23,0x76,0x1,0x8e,0xf2,0x99,0x33,0x11,0xc6,0x6,0x8d,0xa9, + 0x2c,0x83,0xe5,0x78,0x6e,0xcd,0x8e,0x59,0xfd,0xd7,0x83,0x7f,0x27,0x26,0x8b,0xd5, + 0x39,0x30,0xc4,0xf3,0x91,0xba,0xf,0xed,0xbd,0xc4,0x6,0x13,0x21,0x71,0x71,0x8, + 0x5,0xd7,0xc8,0x87,0x61,0x6c,0x6f,0xe2,0xdb,0x40,0xc7,0x4e,0x8e,0x8c,0xd6,0xf6, + 0xba,0x43,0x7c,0x32,0xa,0x50,0xcf,0xf6,0x62,0xd1,0x6b,0x43,0x12,0x7d,0x10,0xaa, + 0x1f,0x6a,0xae,0xa3,0x10,0xc3,0xf1,0x9e,0xf,0x7f,0xea,0x78,0x79,0xa8,0x3e,0xd3, + 0x88,0xf9,0x10,0x9d,0x8,0x4a,0x22,0x18,0xe3,0xc2,0xd2,0xbf,0x3d,0x18,0x16,0x8, + 0x16,0x83,0x53,0x36,0x3f,0x20,0x56,0x5,0x33,0x7b,0xe8,0x53,0xc7,0xcb,0x77,0xff, + 0xe0,0xf4,0xea,0x44,0x85,0x7c,0xf8,0x53,0xc7,0xcb,0xc3,0x9f,0x3a,0x5e,0x86,0xe4, + 0x30,0xc7,0x1c,0xf5,0x2d,0x78,0xe8,0x53,0xc7,0xcb,0x73,0x7f,0x70,0x6a,0x65,0xe1, + 0xb4,0x21,0x20,0xd6,0x2e,0x63,0x48,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x34, + 0xe8,0xd2,0x2e,0xa0,0xde,0x11,0x70,0x7d,0xa2,0x15,0x62,0xd1,0x24,0x8a,0x9f,0x31, + 0xe2,0x39,0x83,0x20,0x75,0xc3,0x3e,0x25,0xfb,0xdf,0x1e,0xfe,0xd4,0xf1,0xf2,0xf0, + 0x27,0x6f,0x2d,0x1c,0x62,0x44,0x4d,0x1,0xc1,0x88,0x17,0xb4,0x10,0x40,0x33,0x5d, + 0xe5,0x6c,0x7b,0xe0,0xba,0x26,0x39,0x2c,0x9b,0x36,0x1a,0xa5,0x6a,0xa4,0x59,0xc1, + 0xa6,0x75,0x8,0x84,0x78,0xae,0xf4,0x30,0x99,0x1d,0xc5,0x79,0xc5,0x66,0x49,0x17, + 0x9e,0x33,0x32,0x1c,0x8c,0x9e,0x7,0x8c,0xdb,0x3d,0x7f,0x17,0xe5,0x31,0x8e,0xdb, + 0xfe,0xd0,0xa7,0x6e,0x2f,0xf,0x7d,0xf2,0xf6,0x62,0x98,0xcf,0x94,0xa,0xe7,0x53, + 0xf4,0x4f,0xf,0x7d,0xf2,0xf6,0xf2,0xd0,0xa7,0xee,0x2c,0x87,0xf4,0x7d,0xf3,0x1c, + 0x7d,0xbc,0xee,0xa1,0x4f,0xde,0x5e,0xbe,0xfb,0x7,0x7b,0xc5,0x29,0xae,0x6a,0x85, + 0xc0,0x5a,0x74,0xbd,0x73,0xb0,0xe4,0xcc,0x30,0x27,0x6c,0xa8,0x80,0xa4,0x37,0x53, + 0xbc,0x42,0xfa,0xfc,0xc0,0x57,0xc7,0xc4,0xa1,0xc9,0xc4,0x58,0x35,0xcc,0xeb,0xa0, + 0xb7,0xde,0x5,0x59,0xbd,0xff,0xf0,0xa1,0x4f,0xd6,0xfb,0xcd,0xb4,0x1e,0x68,0x85, + 0x3d,0x54,0x2,0x67,0xeb,0x26,0xd2,0x82,0x42,0x73,0x69,0xcb,0x55,0x13,0x5b,0x7b, + 0x82,0xdb,0xfc,0xc1,0x48,0x46,0x7f,0x1f,0xc9,0x46,0x77,0x7f,0x6e,0xa7,0x3a,0xcf, + 0xbf,0x3,0xc0,0x82,0x4f,0x7d,0xe7,0xd4,0x3,0x66,0x33,0xe4,0x7a,0x3,0x5a,0xd1, + 0xde,0x75,0x68,0x32,0xe4,0x2a,0xdf,0x98,0xdc,0xe9,0x40,0xb3,0x45,0x99,0x29,0xcf, + 0xb8,0xd3,0x3c,0x6e,0x23,0x7d,0x7,0x4,0xe0,0x12,0x60,0xf6,0xe0,0x27,0x8e,0x97, + 0x87,0x3e,0x71,0xbc,0x80,0x14,0xba,0x1c,0xfc,0xc,0x90,0x5d,0xbe,0x3c,0x60,0x1b, + 0xdc,0xec,0xa1,0x4f,0xee,0x1,0xe3,0xc1,0x4f,0xee,0xad,0x49,0xb0,0x6e,0x37,0xb4, + 0xbb,0x33,0x34,0xfc,0x4b,0xaf,0xb2,0x5c,0x41,0xd7,0x52,0x19,0x72,0xa5,0x25,0xa2, + 0x42,0x13,0x3c,0xc8,0x6c,0xef,0xc,0xac,0x54,0x0,0xd7,0x9a,0x5,0x35,0x3d,0x2a, + 0x68,0xe,0xec,0x73,0x5d,0x9f,0x1e,0x8a,0x80,0xec,0xe,0xc7,0xd8,0x19,0x31,0x83, + 0x89,0x34,0x4d,0xa8,0xe1,0xcd,0x43,0x9f,0x38,0x5e,0x1e,0xfc,0x44,0xd,0x70,0x48, + 0xb5,0x34,0x51,0x16,0x7d,0x8,0xa6,0x48,0xd0,0xa5,0xf3,0xe7,0x13,0xc7,0xcb,0xf7, + 0xfe,0xf0,0x74,0x5d,0xc7,0x6e,0x98,0x8e,0x32,0xd5,0xb6,0x19,0x54,0xa1,0xf,0xef, + 0x89,0x90,0x8c,0x79,0x9c,0xb8,0x53,0xc5,0x4b,0x85,0x90,0x83,0xfc,0xe7,0x7b,0x57, + 0xcd,0xd3,0x79,0xd5,0xf9,0xfa,0xdb,0xd8,0x8e,0xbd,0x3b,0x13,0xba,0x9d,0x40,0x9c, + 0x81,0x73,0x33,0x65,0xff,0xc7,0xef,0xfd,0xe1,0xe9,0xf5,0xc1,0x4f,0x1c,0x2f,0x51, + 0x58,0x8a,0xbb,0x99,0x69,0x21,0x38,0xf1,0xd4,0x6d,0x72,0xce,0xc8,0xfe,0x64,0xd0, + 0x6e,0xc6,0x0,0xf4,0xee,0x28,0x38,0xa2,0xc4,0x1c,0xa7,0x66,0x64,0xf,0x7e,0xe2, + 0xf6,0xf2,0xe0,0x27,0xee,0x2c,0xf,0x7e,0x62,0xa0,0x0,0xe1,0x7,0x78,0xd6,0x69, + 0x79,0x97,0x29,0x0,0x23,0xce,0xd9,0xb8,0x72,0x9a,0x6a,0xf6,0xb2,0x53,0x4d,0x0, + 0xe,0xc4,0x4c,0x96,0x4f,0x63,0x71,0xca,0xe1,0x4b,0x29,0x61,0x46,0x78,0xe8,0x3b, + 0xd0,0x35,0x5c,0xfe,0x78,0xb,0xce,0x9e,0x50,0x92,0xc2,0xd9,0xb6,0x88,0xaa,0xf7, + 0x79,0x0,0xee,0xb4,0x40,0x97,0x4d,0xe6,0x6e,0xf6,0xbd,0x3f,0xbc,0x7b,0x5f,0x20, + 0x16,0xd1,0xf0,0x81,0x1f,0x4c,0x54,0x8,0xc4,0x2c,0x33,0x55,0xa0,0xae,0xd7,0x4b, + 0x8a,0x68,0x6e,0x48,0xdd,0x1,0xa9,0x43,0x67,0x5d,0x0,0x40,0xfe,0xec,0xa6,0xa, + 0x7c,0x11,0x55,0x2e,0x8a,0x72,0x32,0x79,0x19,0x8,0x7b,0x9f,0x88,0xf2,0xb4,0x2e, + 0x4c,0x14,0xa1,0x11,0x8f,0x69,0xb8,0xae,0x3,0x99,0x2d,0x8f,0x8e,0xcc,0xf7,0x3e, + 0x77,0xaa,0xde,0x57,0xad,0x88,0xd,0xc1,0xd2,0x30,0xfa,0x8f,0xc6,0x8a,0xde,0xd9, + 0x23,0xfb,0x0,0x7a,0x3a,0xa8,0x8b,0xa,0xa,0x99,0x9a,0x2c,0xf,0x7e,0xfc,0x78, + 0xf9,0xde,0xe7,0x4e,0xaf,0x9c,0xe9,0x77,0xa4,0x73,0x84,0x21,0x90,0xc8,0x10,0xd8, + 0x4a,0xd4,0x72,0x77,0x40,0xe4,0x5c,0x3d,0x82,0xcb,0x26,0x73,0x68,0x42,0xaf,0x67, + 0x1e,0xb4,0x76,0x23,0x30,0xa9,0x86,0x14,0x95,0xbd,0x7f,0xaf,0x7,0x3f,0x7e,0xbc, + 0xcc,0xd8,0x17,0x8c,0xe9,0x51,0xad,0xf9,0xcc,0x31,0x7e,0xe0,0x63,0xfb,0x41,0x9, + 0x7a,0xe,0xcf,0xff,0x6f,0xa7,0xd6,0xe7,0x3f,0x77,0x7a,0x7d,0xf0,0xe3,0xc7,0x8b, + 0x47,0x7b,0x5c,0x55,0xae,0x17,0xd4,0xbf,0xd6,0x94,0x30,0x2f,0xa,0x7c,0x75,0xd7, + 0xf1,0x4f,0x16,0x4f,0x1,0xbb,0x33,0x24,0x65,0xb0,0xc,0x9d,0x52,0x30,0x54,0x37, + 0xee,0x81,0x13,0xf,0x86,0x9c,0xfe,0x24,0x99,0xc9,0xf4,0xd9,0xa8,0xc3,0xdf,0x6a, + 0xc1,0xcb,0x1f,0x3f,0x5e,0x9e,0xff,0xdc,0xe9,0x55,0x3b,0x72,0x46,0x6a,0x72,0x2e, + 0xec,0x19,0x4c,0x2a,0x63,0x17,0xf8,0x46,0xdb,0x93,0x8c,0x92,0x67,0xe1,0xa7,0xec, + 0x73,0x7e,0xb9,0xae,0x63,0xd5,0x65,0x47,0x70,0x9c,0x24,0x69,0x5c,0xcc,0x3b,0x68, + 0xa2,0x89,0x42,0xb7,0xf4,0xf2,0xc7,0x6f,0x2d,0x97,0x3f,0x7e,0x6b,0x61,0xfb,0xd2, + 0x29,0x17,0xab,0x2e,0xe0,0xcb,0x1f,0xbb,0xb5,0x3c,0xff,0xf9,0xd3,0x2b,0x53,0x85, + 0xd5,0x6d,0x12,0x49,0x9a,0x36,0x16,0x8d,0xee,0xb1,0x80,0x8c,0x9d,0x44,0x88,0x62, + 0x26,0x9f,0x37,0xf,0xb6,0xcf,0xf,0xb1,0xc4,0xc9,0x32,0x5c,0x19,0x57,0x8,0x9d, + 0xae,0x78,0xe,0x46,0x95,0xd6,0xf1,0x19,0xf2,0xdc,0x45,0xfa,0x95,0xde,0xa4,0xe9, + 0xc2,0xfa,0x66,0xf6,0xfc,0xe7,0x4f,0xad,0xcf,0x7f,0xfe,0xee,0xf5,0xf2,0xc7,0x5a, + 0xcb,0x54,0x5b,0x33,0xd2,0x6,0xc0,0xa4,0xa,0x43,0x74,0x3d,0x19,0xa0,0xa8,0xcb, + 0x1f,0xbb,0xbd,0x3c,0xff,0xf9,0x53,0x2b,0x6f,0x20,0xad,0x20,0x61,0x62,0x60,0xd2, + 0x6f,0xa6,0xf7,0xdf,0x1d,0x9a,0xe5,0xb4,0x70,0x3b,0x47,0x3a,0x54,0xd6,0x4d,0x35, + 0x69,0xb3,0xa9,0x9c,0x65,0xd0,0xf7,0x32,0x98,0xd9,0xe5,0x8f,0xdd,0x5e,0x5e,0xf8, + 0xfc,0xa9,0xf5,0xf2,0xc7,0x8e,0x17,0x2e,0x6b,0x2e,0x7f,0xf4,0x78,0x79,0xfe,0x73, + 0xa7,0xd6,0xe7,0xeb,0xbf,0xd,0x94,0x3f,0xb2,0x2,0x11,0x60,0xf7,0x7f,0xf4,0x78, + 0xb9,0xfc,0xf1,0xe3,0xe5,0xf2,0xc7,0x6e,0x2f,0xce,0xf7,0x86,0x47,0xea,0xb5,0x2a, + 0x7a,0x3e,0x7e,0x9e,0x33,0x8,0x6d,0x64,0xf9,0x20,0xbd,0xe6,0x56,0xf5,0x58,0x44, + 0x11,0x13,0x2a,0x99,0x15,0xa8,0x10,0x69,0xa0,0xd0,0x56,0x9b,0x76,0x71,0x4b,0x42, + 0xb6,0xf7,0x67,0x97,0xe6,0xa2,0x5a,0x31,0xb4,0xbf,0x3f,0xff,0xb9,0xd3,0xfb,0x77, + 0x62,0x8e,0x75,0x3c,0x8e,0x23,0x8d,0xab,0x56,0x9d,0x97,0x3f,0x7a,0xbc,0x5c,0xfe, + 0xe8,0xf1,0x12,0x81,0x97,0x7d,0x84,0x13,0x32,0x5b,0x3e,0xce,0x2f,0x7f,0xec,0x78, + 0x79,0xe1,0xf3,0x63,0x4e,0xca,0x15,0x8d,0xa0,0x49,0xa1,0xad,0x59,0x41,0xa6,0x8b, + 0x72,0x97,0xd,0xa3,0x5,0x10,0x70,0x8a,0xaa,0xfc,0xcb,0x1f,0xdb,0xaf,0xd7,0xcc, + 0xec,0x81,0x8f,0x1e,0x2f,0x2f,0x7c,0x7e,0xaf,0x5c,0x3c,0xa4,0xea,0xad,0x8a,0x18, + 0x1d,0x25,0xda,0x7f,0x91,0x5,0x50,0x86,0x44,0x72,0x9f,0x1d,0xc6,0x71,0x14,0xb5, + 0x93,0x5b,0x55,0xe5,0xa4,0xbc,0xe7,0xe9,0x95,0xda,0xc2,0xc3,0xb4,0xf3,0xe5,0xb2, + 0xa7,0x67,0xa8,0xe8,0x51,0xf9,0xc4,0x75,0x6,0x7b,0xe0,0xa3,0xf5,0xe0,0x99,0x74, + 0x73,0x64,0xc6,0x49,0xea,0x66,0x70,0xb3,0x7,0x3e,0x7a,0x6b,0x79,0xe1,0x8f,0x4e, + 0xaf,0xf,0x7c,0xf4,0x56,0x3f,0x77,0x7a,0x97,0x7,0x41,0x4f,0x22,0xe6,0xca,0x98, + 0x81,0xbe,0x20,0xf6,0xce,0xdd,0xb3,0xa0,0xb6,0xda,0x5f,0xf8,0x7c,0xfd,0x2c,0x1b, + 0xe,0x8c,0x39,0xdf,0x87,0x28,0x81,0x5,0x8,0x74,0xe8,0xec,0x41,0xfc,0xb3,0xe3, + 0x68,0x29,0xc9,0x9f,0xd5,0xbf,0x3e,0xf0,0x91,0x5b,0xcb,0xb,0x5f,0x18,0xf7,0x4b, + 0x40,0xb0,0x13,0xe4,0xb8,0x22,0xb5,0xc3,0x38,0x0,0x46,0x6b,0x60,0x22,0xbf,0x2a, + 0xe8,0xf8,0x99,0xa0,0x4c,0xb4,0x2e,0x45,0x1e,0x49,0x81,0x3b,0x9e,0x3,0x4f,0x73, + 0xb0,0x56,0x4a,0x6c,0xe,0xed,0x8,0x1,0xf9,0x86,0xfa,0x66,0xf6,0xc2,0x17,0xce, + 0xac,0xf,0x7c,0xe4,0xd6,0x92,0xeb,0xcf,0x18,0x63,0x26,0x5d,0x44,0xc2,0xfc,0xbc, + 0xf0,0x85,0xd3,0xeb,0x3,0x1f,0xb9,0xb9,0xf0,0x6b,0x5e,0xf8,0xc2,0x99,0xfe,0xec, + 0x2d,0xe8,0xb0,0x8b,0x9f,0x8,0x7c,0x56,0xf2,0x58,0x7c,0x56,0xea,0xc2,0x16,0xbb, + 0xaa,0x1e,0x3a,0x9c,0xc8,0x9d,0xc4,0x89,0x2c,0x34,0x17,0x6f,0xfb,0x1a,0x39,0xb3, + 0x66,0x7c,0x8f,0x57,0x12,0x38,0xb8,0xed,0x6d,0xc2,0x5b,0xee,0xd4,0x8,0x8f,0x73, + 0x46,0xef,0x33,0xa0,0x19,0x25,0x83,0x54,0x5,0x2d,0xab,0xa8,0x8d,0x8c,0x84,0xf9, + 0x9a,0x30,0xb3,0x17,0xff,0xe8,0xd4,0xfa,0xc0,0x47,0xc6,0xfc,0x15,0x81,0xf3,0xcb, + 0x33,0x8a,0x5e,0xd1,0x3b,0x29,0x19,0x5,0x5b,0x46,0x44,0x1,0x15,0x98,0xbd,0xf0, + 0x85,0x53,0xeb,0xfd,0x1f,0xdd,0xbb,0xe,0x71,0x6f,0x39,0x6d,0xc4,0xfb,0x3f,0x7a, + 0xbc,0xbc,0xf8,0x47,0xa7,0x56,0x6,0xc5,0xf0,0x3c,0x1a,0x50,0x44,0x39,0x8b,0xa9, + 0xb0,0x90,0xfe,0x3,0x1f,0x39,0x5e,0x5e,0xfc,0xa3,0xd3,0xeb,0xb,0x5f,0x38,0xb5, + 0xea,0x7d,0xd4,0x44,0x8c,0xc7,0xe2,0xfb,0x61,0x56,0x13,0x5,0x2,0x49,0x8,0x97, + 0x1a,0xea,0x7f,0x1e,0x95,0xa6,0x62,0xfb,0x3c,0xce,0xfc,0xe3,0xd8,0x21,0x63,0x28, + 0xe6,0xdd,0x7,0x4,0xc4,0xbb,0xaa,0x2a,0xb1,0x12,0x58,0xb0,0xa7,0x74,0x4b,0xf8, + 0xb,0x99,0x3e,0xb5,0x8e,0x30,0x75,0x54,0xee,0xff,0xc8,0xf1,0xf2,0xe2,0x1f,0xd7, + 0x59,0x98,0xe8,0x5,0xd0,0x6c,0x75,0xe2,0x7b,0x1f,0x11,0xdb,0x2d,0x21,0xba,0xff, + 0x23,0xfb,0x33,0xf5,0x99,0x38,0x9,0xdc,0xee,0xff,0xc8,0xf1,0x72,0xff,0x47,0x6e, + 0x2d,0xf7,0x7f,0xe4,0x78,0xe9,0x92,0x8f,0xd1,0x3,0x0,0x41,0x9b,0xdd,0x21,0x88, + 0xdf,0xa4,0x7,0x40,0x9d,0x6,0x36,0xe6,0x88,0x73,0x3c,0xa3,0x39,0x23,0xba,0x57, + 0xbb,0xee,0x2f,0xa5,0xe8,0xe8,0x2f,0x32,0x47,0xbc,0xb7,0x4b,0xa5,0x15,0x8,0x51, + 0xf,0xf4,0xc8,0x1e,0x9,0x7e,0xdc,0x8c,0x36,0xd6,0xf3,0x1c,0xf3,0xd7,0xd3,0xfa, + 0x7f,0xf1,0x8f,0x4f,0xaf,0xf7,0xff,0xda,0xad,0x45,0x99,0x10,0xca,0x3a,0xf0,0x89, + 0xc3,0x1a,0xd0,0x9e,0xf9,0x99,0x95,0xf7,0xb7,0x56,0x4d,0x1,0x73,0xe0,0xd9,0x3a, + 0xb5,0x71,0x85,0x93,0x5a,0x1b,0x59,0x3b,0xa,0xcf,0x98,0xfe,0x1e,0x5b,0xad,0x71, + 0xa3,0x2,0x98,0xd0,0x2b,0xb9,0x4b,0xac,0x58,0x82,0xfb,0x7f,0xed,0xe6,0x72,0xff, + 0xaf,0xdd,0x5a,0x42,0x17,0x39,0x43,0x27,0x9,0x99,0x1e,0xfd,0xd0,0x93,0x59,0x10, + 0x20,0xaf,0x73,0x67,0x76,0x8d,0xb6,0xce,0x31,0x1b,0x6b,0xd0,0xbe,0x29,0x7,0xf0, + 0x2c,0x8a,0x5f,0x99,0x0,0x2b,0x4b,0xd6,0x34,0x7f,0xf1,0x8f,0xcf,0xac,0xf7,0xf7, + 0xc0,0x3b,0xd3,0xc2,0xa3,0x99,0x47,0xe8,0xb4,0xce,0x95,0x32,0xf3,0x1e,0x4a,0xc8, + 0xfd,0x30,0x8a,0xe0,0xd7,0xc9,0x4c,0xda,0x33,0x26,0x86,0x75,0xd5,0x63,0xf7,0xf7, + 0xd0,0x8,0x36,0xe9,0xf1,0x73,0x77,0x50,0x10,0xee,0x93,0xa4,0xf,0x50,0x9c,0x17, + 0xe,0x75,0x32,0xa3,0x56,0x49,0x5c,0xa7,0xba,0x87,0x5a,0x42,0x56,0x8c,0x66,0x72, + 0x4e,0xfc,0x68,0xf4,0x4a,0x16,0x89,0xab,0x37,0xd5,0xe6,0x26,0x54,0x5e,0xef,0xf7, + 0x3b,0x52,0xd5,0xce,0x62,0xff,0x3a,0x37,0xc9,0x1c,0xbe,0xc4,0x27,0x9e,0x20,0x65, + 0xc7,0x6c,0x36,0x70,0xa1,0x29,0xfb,0xf7,0x58,0xc5,0x48,0x66,0x3,0x5,0xe0,0x71, + 0xeb,0x6e,0x23,0x0,0xde,0x16,0x14,0xcd,0x52,0xc5,0x31,0xde,0x4d,0x78,0xa4,0x11, + 0x35,0xbc,0xf1,0xf8,0x21,0x80,0xa3,0x36,0x4d,0x3a,0xbb,0x12,0x1b,0x18,0x78,0x43, + 0x55,0x34,0x83,0x8d,0x26,0xb3,0x22,0x6,0x6b,0x89,0xf6,0x3a,0xb7,0xaf,0xd,0x19, + 0xec,0xc5,0x6d,0x42,0x4c,0xe6,0xa5,0xa6,0x3c,0x62,0x37,0x97,0xce,0x8a,0xf0,0xe1, + 0x63,0x15,0x91,0x30,0x16,0x22,0xe2,0x69,0x66,0xb0,0xfb,0x9e,0xba,0xb5,0xdc,0xf7, + 0xab,0xc7,0xcb,0x7d,0xbf,0x76,0xbc,0xbc,0xf4,0xc7,0xa7,0xd7,0xa1,0xda,0x14,0x8c, + 0x11,0xe8,0xf3,0x5e,0xfc,0xe2,0xe9,0xf5,0xbe,0x5f,0xad,0x0,0x11,0x2,0xee,0xc, + 0x4c,0x6,0x64,0x56,0xd7,0xd5,0xf0,0x68,0xae,0x7d,0xdf,0x53,0xc7,0xcb,0x4b,0x5f, + 0x3c,0xbd,0xbe,0xf4,0x45,0xaa,0xa8,0xdd,0x32,0xcf,0xda,0x26,0x9c,0xe3,0xfa,0x4f, + 0xf7,0xff,0xea,0xad,0xfe,0x1e,0xf7,0x3d,0x75,0x6b,0x69,0xdf,0xf9,0xa5,0x3f,0x3e, + 0xbd,0xde,0xff,0x54,0xd,0x70,0x30,0xbb,0xef,0x57,0x6f,0xed,0xdf,0x8d,0xb3,0xfa, + 0x9,0x4e,0x83,0x51,0x58,0xe2,0x79,0xf,0xb3,0xfb,0x9f,0x3a,0x5e,0xee,0xfb,0x55, + 0xee,0x5c,0x14,0xda,0x87,0x91,0xfc,0x3e,0x7,0x8a,0xc5,0x8a,0x2c,0x6b,0xf4,0xcf, + 0xd0,0xff,0xa3,0x5c,0x6c,0xdf,0x97,0xe7,0xe1,0xbc,0x37,0x63,0x5,0xd9,0x3a,0x58, + 0x63,0xcd,0xc6,0x5d,0x8e,0x49,0xe7,0x82,0xe7,0xa1,0x2e,0x58,0x9b,0xa9,0x8,0x4a, + 0x12,0x2c,0xe1,0xd1,0x97,0x27,0xc,0x88,0x60,0x6b,0xc2,0x4e,0x98,0xcb,0x9e,0xcd, + 0x83,0x15,0x26,0xff,0x7b,0xdf,0x53,0xb7,0x96,0x97,0xbe,0x78,0x66,0x9d,0xee,0xfb, + 0x49,0xcc,0x68,0xdf,0xf7,0xe5,0xba,0x7e,0x66,0xed,0x5e,0xf1,0xb0,0xdc,0x26,0xc, + 0x96,0x4,0x7e,0xb4,0x74,0x6f,0xb8,0x42,0xf7,0x89,0x56,0x8f,0xf9,0xc4,0xf8,0xc6, + 0x2d,0x7c,0x5b,0x4,0xfc,0x81,0x9e,0xc9,0x62,0x49,0xc1,0x5d,0x12,0xaa,0x28,0xf2, + 0xb9,0x14,0xf4,0xda,0xe9,0xfd,0x5e,0xfa,0xe2,0x99,0xf5,0xbe,0xf,0xdf,0x5c,0xc2, + 0xdc,0xae,0x17,0x9c,0xb3,0xca,0x77,0xe8,0xb1,0x4f,0x3c,0x3d,0xd8,0x3d,0x6d,0xd3, + 0x52,0x43,0xbe,0x53,0x8c,0x8b,0xc1,0xae,0xf9,0xe5,0x2f,0x9e,0x59,0xef,0x7d,0xea, + 0xe6,0xb2,0x33,0x9,0x10,0x94,0x10,0x8d,0xba,0xa4,0x38,0xb0,0xde,0xc6,0x99,0x24, + 0x1d,0x6a,0xe8,0xbd,0xef,0x6d,0xf9,0x6d,0xdc,0xff,0x97,0xff,0xe4,0x68,0xbd,0xef, + 0xa9,0x9b,0x8b,0xd,0xb7,0x35,0x4f,0xf8,0xde,0x2e,0x2e,0xef,0x11,0x35,0xee,0x1, + 0xe5,0xab,0x33,0x26,0xd7,0x24,0x7e,0xcf,0xe0,0x30,0xa5,0x61,0x4b,0x95,0xdd,0x1a, + 0x84,0x4e,0x28,0xdb,0xf6,0x6d,0xee,0xfd,0xf0,0xf1,0x72,0xef,0x53,0xc7,0xb,0x8b, + 0x71,0xdc,0xfb,0xd4,0xf1,0xf2,0xf2,0x9f,0x9c,0x5e,0xe3,0x7b,0xf0,0xd,0x90,0x99, + 0x58,0xe0,0xf0,0xe9,0xdc,0xc3,0x87,0x7a,0x13,0xcd,0x6e,0x11,0x66,0x23,0x23,0x7b, + 0xa7,0xec,0x36,0xa2,0x24,0x53,0x45,0xc7,0xdf,0x87,0xee,0x69,0x14,0x74,0xe6,0xc, + 0x92,0x4a,0x9f,0x97,0xbf,0x74,0x7a,0xbd,0xf7,0xc3,0xb7,0x16,0x44,0x87,0xa5,0xfa, + 0x9d,0xef,0xfd,0xf0,0xad,0xe5,0xbe,0xf,0xdf,0x1a,0x73,0x61,0x20,0x65,0xa0,0x7e, + 0x0,0xed,0x3d,0x3,0xed,0xc8,0x61,0x18,0x33,0x28,0x42,0x34,0x1b,0xcd,0x9d,0xd4, + 0x2b,0x9c,0xaa,0xf3,0x4e,0xf3,0x41,0xcf,0x3a,0xdb,0xf7,0x99,0xce,0x90,0x48,0x89, + 0xd0,0xdd,0xec,0xe5,0x3f,0x39,0xbd,0xbe,0xfc,0x27,0xfb,0x5c,0x4e,0xaa,0xa9,0x68, + 0x1e,0xed,0x81,0xf,0x1f,0x6d,0x31,0x3d,0x57,0xce,0x8,0x5a,0xf7,0x2e,0xca,0x4d, + 0x9a,0x75,0xdf,0xfb,0xd4,0xad,0xe5,0xe5,0x2f,0x9d,0x59,0x25,0xeb,0x4e,0xfc,0xda, + 0xa0,0xd6,0x57,0x2f,0xfa,0xe5,0x2f,0x9d,0x5e,0x5f,0xfe,0xd2,0x99,0x95,0xf7,0x10, + 0xaf,0x1f,0xee,0xeb,0x72,0x75,0x78,0xef,0x87,0x6f,0x2e,0xfb,0x73,0x9f,0x14,0x89, + 0xa1,0x3a,0xe3,0xca,0x78,0xb4,0x33,0x5d,0x59,0xc3,0x98,0x1,0xb0,0xdc,0xee,0x7d, + 0xea,0xd6,0x72,0xef,0x53,0xb7,0x96,0x7b,0x7e,0xe5,0xd6,0x22,0xad,0x40,0x41,0xad, + 0xcf,0x5a,0xed,0x48,0x2a,0x66,0xdc,0x5d,0x6a,0xf7,0xf1,0xe5,0x2f,0x9f,0xd9,0xbf, + 0x3f,0x54,0xed,0x8c,0x2b,0xae,0x7b,0x3e,0x7c,0x73,0x11,0xb1,0x1f,0x64,0x2f,0x1, + 0xa4,0xb9,0xa6,0x9b,0x4f,0x1d,0x6c,0x98,0xae,0x13,0x9c,0xfc,0xcc,0x4,0x54,0xc8, + 0x7e,0x7,0x32,0xbb,0x9e,0x74,0xae,0xe,0xb5,0x77,0x63,0x95,0xee,0xa1,0x4d,0x7f, + 0xcf,0x87,0x6f,0x2e,0x2f,0x7f,0x79,0x7f,0xfe,0x2f,0x7f,0xe9,0xcc,0xbe,0x97,0xe5, + 0x31,0x14,0x5,0xc6,0xb2,0xd3,0x2c,0x7f,0x5f,0xc7,0x5c,0x0,0x8a,0x5,0xb0,0x22, + 0x17,0x3d,0xca,0x84,0x42,0x2a,0x82,0x9,0x9b,0xc1,0x26,0xb6,0xb0,0x1c,0xc0,0x46, + 0xd1,0x73,0xcf,0x87,0x6f,0x2e,0xf7,0x7c,0xf8,0xe6,0xd2,0x70,0x16,0xb1,0xdb,0x15, + 0xbb,0x4d,0xc3,0xe1,0xce,0xc8,0x4b,0x1d,0x22,0x89,0xfd,0xf2,0x97,0x8f,0xd6,0x7b, + 0x7f,0xe5,0xe6,0xa2,0x6e,0x9d,0x10,0xbb,0x7b,0x90,0x3f,0xc7,0xf0,0x11,0xf1,0x20, + 0x66,0x94,0xad,0x5b,0x3b,0xa0,0xb7,0x32,0xa2,0x22,0xa6,0xa7,0x73,0xf9,0xe1,0xdd, + 0x4f,0x20,0x56,0xf0,0x2c,0xb5,0xb,0x76,0x49,0x63,0xdc,0x54,0x64,0x1b,0x45,0xe6, + 0x4b,0xc3,0x4f,0xd4,0xa4,0xe6,0xe5,0x2f,0x9f,0x59,0xef,0xf9,0x95,0x9b,0x4b,0xee, + 0xac,0x22,0x81,0x33,0x7b,0xec,0x1,0x88,0x9d,0xe1,0xfd,0xfe,0xb7,0xe7,0x53,0x0, + 0xd8,0x3d,0xbf,0x72,0xbc,0xdc,0xf3,0x2b,0x15,0xa9,0x47,0xa,0x6e,0xa9,0xea,0x63, + 0x6a,0xb,0x73,0xc9,0x2d,0xd2,0xcc,0x77,0x50,0x4,0x28,0xe8,0x61,0x62,0x59,0xca, + 0xfc,0x3f,0x31,0x41,0xa8,0xd9,0xd3,0x3d,0x1f,0x3a,0x5e,0x5e,0xfd,0xf2,0xe9,0xf5, + 0x95,0x2f,0x9d,0x5e,0xef,0xfd,0xd0,0xbe,0x19,0x80,0x5c,0xf1,0x7a,0x68,0x49,0x2, + 0x19,0x2d,0x98,0xda,0xcf,0xe4,0xf9,0xcd,0x26,0x19,0x7d,0x91,0x5,0xa4,0x7c,0xab, + 0x10,0x99,0x43,0xd8,0xce,0x86,0x57,0xbe,0x74,0x7a,0xdd,0xf,0x45,0x48,0x45,0xc7, + 0xd5,0x57,0x43,0x20,0x8f,0xeb,0x8d,0x2d,0x2e,0x4c,0xb5,0x85,0x65,0x1e,0x43,0xaa, + 0x74,0x9,0xbd,0x1d,0xba,0x29,0xfb,0xe7,0xb8,0xa8,0x54,0xbe,0xf2,0xe5,0xd3,0xeb, + 0x2b,0x5f,0xde,0xc1,0x22,0xf1,0xa1,0xe1,0x0,0x35,0x4f,0x1,0x8d,0x50,0x25,0x3a, + 0xb8,0x54,0x75,0x31,0xf3,0x57,0x4,0x71,0xe8,0x7a,0x0,0x59,0xf1,0xe,0xb1,0x72, + 0x9b,0x54,0x6d,0xe0,0x75,0xa7,0xf7,0xad,0xfd,0xef,0xa5,0xf,0xdd,0x5a,0xee,0xf9, + 0xd0,0x1e,0x28,0x3a,0xea,0x76,0xe6,0x46,0x47,0xa8,0xda,0x7b,0x3e,0x74,0x6b,0x79, + 0xe5,0xcb,0x67,0xd6,0x1e,0x30,0xa4,0x3,0xe4,0xd2,0xa1,0xba,0xa7,0xbe,0x7f,0x84, + 0x88,0xdd,0xf3,0xa1,0x9b,0xcb,0xab,0x5f,0xde,0x5b,0xc5,0x8c,0x17,0x81,0xdc,0x23, + 0x9f,0x56,0x87,0xaf,0x7c,0xe5,0xcc,0x7a,0xcf,0x87,0x6e,0x2e,0x1e,0x3a,0x2c,0x36, + 0x81,0xa1,0xa1,0x7e,0xd6,0x2b,0x5f,0x3e,0xb3,0x8a,0x42,0x58,0x7d,0xe9,0x7e,0x7d, + 0x5c,0xdd,0xcd,0x0,0xac,0xfb,0xf5,0xbc,0xf2,0xe5,0x33,0xeb,0xab,0x5f,0x3d,0xb3, + 0xde,0xf3,0x21,0x9d,0x55,0x37,0x65,0x3d,0xc0,0xe,0x6b,0x4d,0x87,0x4e,0x99,0x63, + 0x36,0x1b,0x1c,0x5d,0xe,0x7e,0x7f,0xa0,0xd8,0xab,0x5f,0x3e,0xaa,0x9f,0x5d,0xf, + 0x72,0x37,0xbb,0xe7,0x83,0xfb,0xf7,0xea,0x14,0xb4,0x6d,0x98,0x6e,0x8c,0x35,0xe, + 0xd9,0x7f,0x91,0xef,0x88,0xe8,0x74,0x7,0xc2,0x67,0x38,0x61,0x45,0xb6,0x20,0xb1, + 0xbd,0x85,0xc0,0xc6,0xad,0x75,0x20,0xb9,0xb7,0xb1,0xc4,0x6e,0xb4,0x11,0x35,0xea, + 0x70,0x22,0xae,0x7d,0x1b,0xe8,0x71,0x71,0xd,0x24,0x2c,0xc,0x77,0x21,0x1,0xef, + 0xa8,0x7d,0x98,0x9a,0x3,0xb5,0xd7,0xbc,0xf2,0x95,0xa3,0xb5,0xaf,0x79,0xa1,0xa7, + 0x41,0x81,0x8d,0x8,0x6e,0x94,0x5b,0x3,0x7a,0x46,0xb3,0xa3,0xd0,0xa1,0x60,0x0, + 0x6e,0xc0,0xe8,0xa8,0x83,0x25,0x72,0x87,0x35,0xe4,0x59,0x3d,0xb8,0xf1,0x59,0x6c, + 0xcc,0xcb,0x56,0x26,0x5,0x3f,0x97,0x57,0xbe,0x72,0xb4,0x5e,0xfa,0xe0,0x8d,0x25, + 0x9a,0xbe,0x48,0xdf,0x22,0x7a,0x5a,0xd0,0x5c,0x1c,0x80,0xbd,0xf2,0x95,0xa3,0xf5, + 0x95,0xaf,0x1c,0xad,0x9d,0x3e,0x6a,0xb0,0x57,0xbf,0x7a,0xb4,0xde,0xf3,0xc1,0x9b, + 0x8b,0x74,0x80,0xa1,0xb8,0x14,0xa6,0xd2,0xa9,0xc0,0xd9,0xe4,0xfc,0x9b,0xf1,0xbb, + 0xa0,0x9d,0x60,0x3d,0xeb,0x2,0xc6,0x49,0x1b,0x10,0xca,0x56,0xd9,0x88,0xc4,0x2b, + 0xdd,0x2f,0xb3,0xc2,0xe8,0x3a,0x27,0x8a,0xd8,0xa5,0xf,0x1d,0x2f,0xaf,0x7e,0xe5, + 0xf4,0x6a,0xe4,0xed,0x2a,0x63,0x1,0xec,0x9b,0xd2,0x23,0xc7,0xd1,0xb,0xad,0x4f, + 0x4,0xa1,0x96,0xf1,0xba,0x4b,0x1f,0xbc,0xb5,0xbc,0xfa,0xd5,0x33,0x2b,0x26,0xd5, + 0xaa,0xcc,0x85,0xa2,0xf7,0xb6,0xe9,0xec,0xeb,0xd5,0xaf,0xec,0x87,0x91,0xc3,0xed, + 0xd2,0x87,0x6e,0x2d,0x97,0x3e,0x38,0x2a,0xd6,0x99,0x94,0x5e,0x1a,0x3d,0x46,0x6d, + 0x60,0xcc,0xfc,0x6e,0xd9,0x64,0x4,0x76,0x4f,0xbd,0x76,0xb3,0x58,0x75,0xe4,0x6b, + 0x5,0xcd,0x80,0x58,0x75,0x69,0xd6,0xc6,0x9b,0xcd,0x6d,0x52,0xa5,0xd4,0x29,0x4c, + 0x9e,0xdd,0xd5,0x42,0x85,0x55,0x12,0x88,0x45,0x71,0xc0,0x19,0xb0,0x98,0x59,0xd8, + 0x9,0xa0,0x12,0x2a,0x82,0x66,0xea,0xf0,0xea,0x57,0xcf,0xac,0x97,0x3e,0xb8,0xdf, + 0xff,0x57,0xbf,0xca,0x15,0xad,0xa5,0xf9,0x7a,0xe0,0x3d,0x84,0xee,0xca,0x9c,0xd3, + 0x9c,0x31,0x1c,0xa1,0xaa,0xa9,0xef,0x7d,0xe9,0x83,0x37,0x97,0xd7,0xfe,0xf4,0xcc, + 0x2a,0x9d,0x84,0xfa,0xe6,0xaf,0xfe,0xe9,0x1e,0xbc,0x6c,0xe2,0xe3,0xce,0xa8,0xfc, + 0x34,0xcb,0xf4,0x3,0x1d,0x88,0x50,0xbd,0xb9,0x67,0x1b,0x4f,0xb1,0x9c,0xf4,0xda, + 0x16,0x8f,0x5e,0xcb,0x13,0xd5,0xb2,0xd7,0xbe,0x7a,0xb4,0x5e,0xfa,0xc0,0x1e,0xe8, + 0x10,0x5a,0xfc,0x8e,0xa8,0xd9,0x3f,0x28,0x79,0x16,0x66,0xf8,0x56,0xef,0xc9,0xa5, + 0x7a,0x58,0xb5,0xb7,0x69,0xf7,0x49,0x5b,0x96,0xaa,0xf9,0x9f,0xcc,0x76,0x22,0x6f, + 0xcb,0x70,0x70,0xfd,0x25,0x70,0x55,0x7d,0xdd,0xa5,0xf,0xdc,0x58,0x5e,0xfd,0xd3, + 0x33,0xab,0xd3,0xc8,0xe5,0xd5,0xf6,0x5d,0x79,0x16,0x4c,0xd5,0x1f,0x7c,0xfc,0x5e, + 0x3c,0x23,0x72,0x49,0x48,0x89,0x83,0x8d,0xcf,0xbc,0xf8,0x81,0x9b,0x4b,0x3,0xbb, + 0x39,0xa3,0xf3,0x91,0xd7,0xa6,0xb8,0x95,0x21,0xa3,0xd7,0xfb,0xe8,0xad,0x1d,0xea, + 0xbb,0x9a,0x87,0x5d,0xfa,0xc0,0xcd,0xe5,0xd2,0x7,0x6e,0x2e,0x40,0xbe,0xac,0x51, + 0x59,0x5,0x8f,0xee,0x48,0x85,0x75,0x92,0x84,0x16,0x5,0xb3,0xf1,0x9a,0x8b,0xf5, + 0xfb,0xe8,0x39,0x16,0xf7,0x4d,0xc0,0xbe,0x4,0x5c,0x38,0x77,0x12,0x1,0x4d,0x80, + 0x7c,0xe2,0x9c,0x38,0xf7,0x8c,0xa0,0xf3,0x86,0xc0,0xa5,0xaf,0x7d,0xad,0x3d,0x4f, + 0x44,0xd1,0x43,0xea,0x98,0x22,0x30,0x67,0x44,0x14,0xb2,0x1f,0x4f,0x17,0x3f,0x70, + 0x63,0x79,0xed,0x6b,0x47,0xab,0x73,0x3b,0xdc,0x99,0x21,0x13,0x74,0x9a,0xb8,0x13, + 0xd6,0xf4,0xd6,0x2b,0xcd,0xc9,0x49,0xc7,0x7,0x18,0xe0,0xc7,0x59,0xa7,0xaf,0xe3, + 0xbb,0x10,0xdd,0xda,0x4c,0x4,0xb2,0x5c,0xb0,0xf,0x93,0xb3,0x8a,0x71,0x60,0xd2, + 0xd5,0xf4,0x84,0x45,0x9a,0x9e,0x2b,0xce,0x9c,0x8,0x97,0x6e,0x65,0x14,0x2c,0xaa, + 0x2d,0x77,0x24,0x14,0xaf,0xa0,0x6e,0xe1,0x82,0xa6,0xe4,0xaa,0xe9,0xe2,0xfb,0x6f, + 0x2e,0x97,0xde,0x7f,0x4b,0x85,0xed,0x31,0x71,0x85,0x4f,0xb3,0xad,0xf8,0x7e,0x1, + 0x99,0xb9,0x99,0x5d,0x7c,0xff,0xad,0x71,0xe0,0xf4,0xaa,0x3d,0xcf,0xd8,0xb8,0x2, + 0x66,0xd4,0xe6,0x54,0x27,0x37,0x54,0x27,0x11,0x1d,0x99,0xe,0xd8,0x38,0xfb,0x6, + 0x26,0x9c,0xd5,0x90,0x15,0x86,0xeb,0xe0,0x6c,0xcf,0x2d,0x54,0x16,0x50,0xca,0x18, + 0x6b,0x3,0xb7,0xc3,0xe4,0xb5,0xaf,0x9d,0x59,0x2f,0xbe,0x7f,0xef,0x4e,0x5c,0x7c, + 0xff,0xcd,0xe5,0xe2,0xfb,0xf7,0x59,0xcd,0xc5,0x27,0x6f,0x2d,0xaf,0x7d,0xed,0xcc, + 0xfa,0xda,0x9f,0x9e,0x59,0x2f,0xbe,0x7f,0x47,0x6d,0xb6,0xdf,0xb9,0xf2,0xa7,0x67, + 0xd6,0xd7,0xbe,0x76,0xa6,0x8b,0xf5,0x70,0x4b,0xd6,0xa3,0x78,0xc,0x2,0xff,0x37, + 0x8d,0x1f,0xf4,0xd1,0xe9,0xcc,0xae,0x18,0x6b,0x14,0xcb,0x6c,0x6a,0x53,0x77,0x2d, + 0x8f,0x8,0x50,0xb,0xc8,0x5b,0x57,0xa7,0xa2,0xe,0x68,0x62,0x24,0x35,0x2,0xf5, + 0x11,0x5a,0x1d,0xb6,0xef,0x6d,0xb6,0x1f,0x2a,0x17,0x9f,0xac,0xf7,0x85,0xbc,0xb6, + 0x2d,0x56,0x7b,0x66,0x76,0xf1,0xfd,0x37,0xfa,0x5a,0x6b,0x2d,0xd9,0xd7,0xbe,0x76, + 0x34,0xee,0x2b,0xeb,0xd8,0xcb,0xac,0x4b,0x85,0x56,0xfa,0x67,0x4d,0x12,0x21,0x5e, + 0x7,0x17,0x9f,0xbc,0xb9,0xbc,0xf6,0xb5,0xa3,0x35,0x96,0xbc,0xdc,0x3d,0x70,0xf8, + 0xfe,0xec,0x9f,0xbc,0xb9,0xc4,0x5a,0x84,0x7f,0x7f,0x7c,0xf,0x74,0x4a,0x94,0xcc, + 0x24,0xd3,0x6c,0xe,0xa4,0x52,0x45,0x15,0x60,0xc0,0x7c,0x5c,0xf9,0xda,0xd1,0x7a, + 0xf1,0xc9,0x1b,0x4b,0xc4,0x7a,0xb0,0xaa,0x24,0x42,0x7,0x3,0x86,0x9d,0x87,0xbd, + 0x11,0xe,0x23,0xbc,0x3f,0x63,0x1a,0xc6,0x8,0xcc,0xc3,0xfd,0xb6,0xde,0x4a,0xbd, + 0xf2,0xb5,0xa3,0xf5,0xc2,0xfb,0x6f,0x2c,0xc3,0x1,0x70,0x82,0x9d,0x11,0x7b,0x65, + 0x24,0x59,0xd2,0xbe,0x2e,0x8b,0x56,0x8e,0x7c,0xef,0xcc,0xcc,0xae,0x7c,0xed,0xec, + 0xbe,0x66,0x8c,0xe8,0x5b,0x16,0xa8,0x5e,0x66,0x76,0xe1,0xc9,0x9b,0xcb,0x78,0xdd, + 0x58,0xbb,0x91,0xdd,0x22,0x98,0x98,0xfe,0xfe,0x37,0x16,0x1,0x71,0x21,0xe8,0xef, + 0x6d,0xa3,0x20,0x16,0x87,0xc3,0x50,0x1,0x47,0x2c,0xb,0x8c,0x67,0xab,0x7a,0xac, + 0x5d,0x78,0xdf,0x8d,0xe5,0xe2,0x93,0x37,0x16,0xf,0x63,0x22,0xdf,0xcc,0x5e,0xfb, + 0xb3,0xb3,0xeb,0x85,0x27,0x47,0xc5,0x6b,0x6e,0x76,0xf1,0xc9,0xfd,0xf5,0xdd,0xb6, + 0xd6,0x6,0xaf,0xff,0xc2,0x93,0x37,0x96,0x2b,0x5f,0x3b,0xbb,0x46,0x6c,0x4a,0x77, + 0xf,0x74,0xea,0x52,0x32,0xd6,0xc7,0x60,0x17,0x9f,0xbc,0xb1,0x5c,0x78,0xf2,0xc6, + 0xd2,0x29,0x78,0xe,0xc1,0x43,0x88,0xa6,0x3a,0x75,0x39,0xf4,0xc,0x83,0x5d,0xf9, + 0xb3,0xa3,0xf5,0xc2,0xfb,0xae,0x2f,0x60,0x45,0xbb,0xf6,0x19,0xef,0xbb,0xb1,0x5c, + 0xf9,0xb3,0xa3,0xb5,0xcf,0x9c,0xb7,0xf1,0xe4,0xe4,0x79,0xbb,0x3a,0x21,0x72,0xb5, + 0x8c,0xc0,0x3a,0x19,0xc8,0x4b,0xc5,0x25,0xc0,0x42,0x97,0x1,0xba,0x8f,0xcd,0x2, + 0x46,0x29,0x3,0x15,0x52,0x5c,0x51,0xd5,0x45,0x24,0xd1,0xa8,0xfd,0xfb,0x9d,0x5d, + 0x65,0x5d,0xd2,0x5e,0x2e,0x17,0xde,0x7f,0x73,0xb9,0xf2,0x67,0x67,0x56,0xf7,0x19, + 0xdf,0xd8,0x3,0xea,0x4f,0x3f,0x20,0x2a,0x70,0x49,0x7d,0x7,0xe5,0xd0,0xc5,0x6b, + 0xe3,0x19,0x46,0x7,0xd,0x4c,0xdc,0xd1,0xda,0x7f,0xae,0x7c,0xfd,0xcc,0x7a,0xe1, + 0xc9,0x9b,0xcb,0x85,0x27,0xf7,0xeb,0x15,0xeb,0x51,0xaa,0x6c,0xae,0xfc,0xd9,0xfe, + 0x3a,0x51,0x83,0x9b,0x18,0x11,0xcb,0xe7,0x7b,0x0,0xe6,0x79,0x91,0xb9,0xa0,0x23, + 0xf0,0x90,0x39,0x93,0xf,0xd5,0x7c,0xe4,0xe5,0xc6,0x19,0x87,0x20,0x88,0x5d,0x79, + 0x9e,0xdc,0x79,0x60,0xd,0x7c,0x8f,0xfe,0xbd,0xa6,0x33,0x1e,0x56,0x8a,0xea,0x12, + 0xb2,0xac,0x7d,0xdc,0x9e,0x1,0x65,0x88,0xea,0x65,0xa1,0xc8,0x5e,0xb8,0x89,0x61, + 0xcf,0x18,0x77,0xc1,0xae,0x7e,0xfd,0xcc,0x7a,0xe1,0x7d,0x37,0x16,0x99,0x7f,0x77, + 0x69,0x4a,0xb,0x33,0x55,0x62,0x33,0xc8,0xdc,0xdc,0xc9,0xb5,0x2e,0x57,0x7e,0xdd, + 0xce,0x91,0xdb,0x54,0x9e,0xbd,0xa6,0xdd,0x98,0xd1,0x10,0x55,0xbe,0xdc,0xae,0x7c, + 0xfd,0x68,0xbd,0xf2,0xf5,0xa3,0x35,0xfb,0x60,0x7b,0xaa,0x30,0x50,0x32,0xf0,0x8b, + 0xf9,0xd8,0x43,0xc1,0x30,0xce,0x1e,0x5d,0x90,0xea,0x1e,0x29,0x9d,0x54,0x29,0xba, + 0x9b,0x9d,0x7f,0xdf,0x8d,0xe5,0xca,0xd7,0x8f,0x56,0x4b,0x5c,0x7f,0x4,0x6,0x1, + 0x3d,0x5b,0xd6,0x7b,0x2a,0x10,0x46,0xc3,0x95,0xaf,0x1f,0xad,0xe7,0xdf,0x77,0x63, + 0x69,0xef,0xd1,0xde,0x7f,0xd6,0xb1,0x69,0xf7,0xfb,0xc2,0xfb,0x6e,0x2c,0x57,0x9e, + 0x3e,0x5a,0x85,0x65,0x30,0x59,0xeb,0xbc,0x86,0xbb,0xa7,0x76,0x74,0x76,0xe3,0xce, + 0x45,0x58,0xdf,0x40,0xc6,0xcb,0x78,0x30,0x9b,0xe0,0x59,0xc1,0xd5,0xa7,0x8f,0xd6, + 0xab,0x4f,0x1f,0xad,0xfd,0x59,0xa5,0x75,0x3f,0x96,0xf4,0xd5,0xaf,0x1f,0xad,0xe7, + 0xdf,0x7b,0xa3,0x8b,0x30,0xc1,0x61,0x17,0xde,0x7b,0x63,0x39,0xff,0xbe,0x1b,0xb, + 0xe3,0x71,0x2f,0xbc,0xef,0xc6,0x72,0xf5,0xe9,0xb3,0xab,0xa8,0xc2,0x19,0xf6,0x7b, + 0xd0,0x9f,0x3,0x9,0xb6,0x72,0xb1,0xcf,0x37,0x7a,0x86,0x45,0xc1,0x18,0x3f,0xca, + 0x3e,0x74,0xe5,0x1d,0xb3,0xa8,0xca,0xd5,0xa7,0xeb,0x75,0x1b,0x39,0x29,0xb6,0xbd, + 0x1,0xed,0x1c,0xd,0x7e,0xf4,0xf0,0x20,0x38,0xff,0xbe,0xeb,0xcb,0xd5,0xaf,0x9f, + 0x5d,0xaf,0x7e,0xfd,0x68,0xec,0xc3,0xfa,0xe5,0x3c,0x3a,0x92,0x41,0xcf,0x23,0x46, + 0x39,0x9d,0x7f,0xef,0xf5,0xe5,0xca,0xd7,0x8f,0x56,0x84,0xbd,0xd0,0xaa,0xcd,0x2b, + 0x4f,0x9f,0x5d,0xcf,0xbf,0xf7,0xfa,0x22,0x3a,0x19,0xd4,0xd5,0xc8,0x9d,0x1,0xad, + 0x46,0x79,0xee,0x1d,0xf7,0x13,0x3b,0xc7,0xf9,0x84,0xf5,0x30,0xe,0x3f,0xf,0x7c, + 0x70,0xad,0x66,0x93,0x16,0x4a,0x54,0x8,0x9d,0xe1,0xa0,0x8,0xa1,0x1f,0xb9,0x75, + 0x33,0x26,0xc6,0xa1,0x4e,0xa5,0x4d,0x3a,0x2b,0x66,0x99,0xa1,0xf0,0xd6,0x5e,0x6a, + 0x25,0x55,0xf6,0x57,0x9f,0x3e,0xb7,0xdf,0xf7,0x49,0x1f,0xd3,0x42,0x47,0xa6,0x5d, + 0xff,0xd5,0xa7,0xcf,0xae,0x17,0xea,0x9a,0x3a,0xb9,0xd5,0xc,0x61,0x23,0x85,0x36, + 0x87,0xd9,0xb6,0x69,0x39,0xbf,0x31,0x3f,0xae,0xbe,0xfb,0xc6,0x73,0x52,0x9e,0x61, + 0x74,0x51,0x2,0x6,0xd7,0xf9,0x58,0x9b,0xfd,0xfd,0x4c,0xad,0x42,0x6b,0xdb,0xf0, + 0xea,0xd3,0x67,0xd6,0x61,0x86,0x32,0xe8,0x6f,0xdb,0x16,0x9f,0xdf,0xbe,0xc8,0xda, + 0xcf,0xdb,0x7b,0x5e,0x7d,0xfa,0xcc,0xa,0xf6,0xa0,0xed,0x9b,0x64,0xf0,0x78,0xb7, + 0x2d,0xd3,0x24,0x44,0x85,0xbd,0xdf,0x13,0xfe,0xae,0x90,0x3f,0x77,0x27,0xb6,0xfe, + 0x7e,0xae,0xf7,0xa5,0x5e,0xe3,0x46,0x1c,0xdd,0x6d,0x53,0x9a,0xd4,0x90,0x30,0xac, + 0xaf,0x73,0xb,0x42,0x2f,0xfb,0x7b,0x9f,0x7d,0xcf,0xcd,0xe5,0xda,0xd3,0xfb,0x1, + 0x74,0xee,0xbd,0x37,0x96,0x8d,0x78,0xb8,0xdb,0x96,0x1a,0xd1,0x41,0xc0,0x87,0x94, + 0x95,0xd8,0x7b,0x7b,0x32,0x18,0xed,0x46,0x66,0x51,0xcf,0x99,0x7a,0x61,0xdb,0x16, + 0x71,0x73,0xfb,0xf5,0xf2,0xf3,0xd9,0xba,0x62,0x54,0xfb,0xfe,0xfb,0x35,0xf1,0x7d, + 0x4,0x87,0x43,0xa,0xae,0x1b,0xb1,0x1f,0xda,0x72,0x93,0xb5,0xd6,0x4d,0x6b,0xf4, + 0xf9,0x5b,0x62,0x89,0x1e,0xf0,0x4f,0x71,0xbe,0xa6,0xb2,0xff,0xbe,0xfa,0xc5,0xe8, + 0xf7,0xe4,0xf5,0xef,0x7c,0xbf,0x8b,0xe8,0x95,0x6f,0x1b,0x77,0x3d,0xdc,0xa2,0x21, + 0xd0,0x35,0xa,0xa2,0x9d,0x6d,0x1e,0xf6,0xc4,0xd9,0xf7,0xdc,0x58,0xae,0x3d,0x7d, + 0xb4,0xb6,0xdb,0xbd,0x6d,0x39,0xd1,0xe6,0xfb,0x29,0x9f,0x5b,0xaf,0x19,0x30,0xbb, + 0xf6,0xe7,0x47,0xeb,0xb9,0xf7,0xec,0x9b,0xbc,0x7d,0xee,0xb9,0xf7,0x5c,0x5f,0x5e, + 0xff,0xe6,0xd1,0xba,0x6d,0x62,0xd4,0x34,0xf6,0x3f,0x60,0xe7,0xde,0x7d,0xbd,0xaf, + 0xb3,0xfd,0x75,0xaa,0xaf,0xde,0xee,0x79,0x5b,0x4b,0x7c,0x7e,0xb4,0xb8,0xb3,0xb1, + 0x46,0x35,0x9d,0x15,0xde,0x5e,0x67,0xea,0x84,0x6,0x52,0x1e,0x13,0xda,0xab,0x85, + 0xfb,0xdd,0x82,0xa3,0xeb,0x1a,0x33,0xc0,0xce,0xbe,0xfb,0xfa,0x72,0xed,0xe9,0xb3, + 0xab,0xc3,0xec,0xdc,0x7b,0xae,0x2f,0xd7,0xbf,0x79,0x76,0xb5,0x70,0x36,0x80,0x9c, + 0xa9,0xf4,0x59,0x8d,0x56,0xf5,0xb6,0xa9,0xa7,0xc5,0xb9,0x77,0x5f,0x5f,0x5a,0xb2, + 0xbd,0xbf,0x27,0xaf,0x7f,0x95,0x9c,0xe6,0xeb,0x94,0xbf,0x1b,0x44,0xff,0x7c,0xdb, + 0xe6,0x8d,0xc3,0x76,0x56,0x18,0xf2,0x59,0xd1,0xf6,0x33,0xff,0xec,0xda,0x9f,0x9f, + 0x5d,0xf9,0x3d,0xb6,0x6d,0x4e,0xfc,0xde,0xb6,0x8c,0x9,0xd8,0xa8,0xe3,0xb9,0x6d, + 0x26,0x95,0x68,0xbb,0x37,0x7a,0xae,0x8c,0x9f,0x95,0xfe,0xfb,0x63,0x3d,0x42,0x79, + 0xca,0x61,0x4f,0x82,0x62,0xc,0xff,0xb4,0xd8,0xd9,0x77,0xbf,0xbe,0x5c,0xfb,0xf3, + 0x73,0xab,0xb5,0x67,0xc2,0x2d,0x7f,0x7,0x3d,0x37,0x13,0xbd,0xfe,0x2d,0xfa,0xd, + 0x84,0x3d,0xdb,0xe2,0xc7,0x46,0x9d,0x1d,0xf9,0xfc,0x34,0xde,0x1c,0x31,0x1,0xfd, + 0x73,0xa9,0x2b,0xe8,0x3e,0xcc,0xb4,0x90,0x83,0xeb,0x46,0x1e,0x24,0xed,0x7e,0x74, + 0xed,0x75,0xf,0xbe,0x2,0x74,0xd1,0x1c,0x57,0xdb,0xe7,0x8f,0x7b,0x8b,0x2e,0x9c, + 0xd5,0xf6,0xcb,0x46,0xba,0xfd,0xe,0xfd,0x5d,0x0,0x56,0x18,0x71,0x3a,0xe6,0x4b, + 0x34,0xef,0x41,0xe6,0x19,0x1b,0xbf,0xc6,0x95,0xd6,0xa4,0x7a,0xe5,0xec,0x86,0x45, + 0xdc,0x69,0xa9,0x42,0x8c,0xac,0x16,0xb3,0x9b,0x9a,0xb1,0xec,0x2c,0x55,0xee,0xc2, + 0x88,0x4f,0x8e,0x49,0xc1,0x65,0x3a,0x30,0x78,0xf8,0xfb,0x20,0xc8,0x74,0x5a,0xe4, + 0x13,0x17,0x48,0x95,0xac,0xfa,0xbd,0x3a,0x73,0x85,0x5,0xff,0xed,0x9,0xc7,0x98, + 0x3b,0xf,0x2c,0xec,0x71,0xf6,0xdd,0x37,0x96,0xd7,0xbf,0x71,0xb4,0x36,0x66,0x80, + 0x9b,0xbd,0xf5,0xcc,0x8a,0x90,0xa5,0xd7,0xbf,0x71,0xb4,0xbe,0xfe,0xcd,0xa3,0x55, + 0x2d,0x1b,0xf9,0x2f,0x85,0x2a,0xd8,0x32,0x5,0x2d,0x47,0x65,0x32,0x16,0x58,0xf1, + 0xd0,0x22,0x17,0x9e,0x79,0x98,0x7d,0xb7,0xff,0xbf,0xfe,0x8d,0xa3,0xf5,0xe8,0xdd, + 0x37,0x97,0xa3,0x77,0xdf,0x58,0xae,0x7f,0xe3,0x6c,0xf,0x50,0x8c,0xc5,0x90,0x39, + 0xb8,0x29,0x62,0xd4,0x44,0x6a,0x52,0x91,0xa3,0x7c,0x7f,0xce,0xbe,0xfb,0xc6,0x72, + 0xfd,0x1b,0x47,0xab,0x73,0xe2,0x21,0x60,0x25,0x4c,0x50,0xbc,0x34,0x67,0xb,0x15, + 0x95,0x9b,0x22,0x88,0xf3,0x8c,0x18,0xea,0x21,0x40,0x6a,0x60,0xce,0x3d,0x58,0xa1, + 0xaa,0x4,0x49,0x54,0x51,0xdc,0xc2,0x9c,0x8f,0xdb,0x40,0xa5,0xa4,0xc,0x7,0xaa, + 0x34,0x38,0xc1,0x72,0x4a,0x58,0xe3,0xba,0x8b,0xa,0x6d,0x67,0xdf,0x75,0x63,0xf, + 0x76,0xa1,0x9d,0x98,0xb8,0xbe,0xd0,0xaa,0x1b,0xc4,0x8,0x89,0x15,0x3a,0x98,0x65, + 0x11,0x79,0xb8,0xf5,0xff,0xaf,0x7f,0xf3,0xec,0x7a,0xf6,0x5d,0xd7,0x17,0xf7,0xc3, + 0x74,0xb8,0x43,0xe,0x75,0x71,0xbd,0x47,0xef,0x82,0xa3,0x77,0xd5,0x0,0x4e,0xbc, + 0xe8,0xa3,0x27,0xae,0x2f,0x47,0xed,0xf3,0xa4,0x6a,0x8a,0x8c,0x12,0x4b,0xdc,0xec, + 0xf6,0xd7,0xb3,0xef,0xba,0xbe,0x5c,0xff,0xd6,0xd9,0xf5,0xf5,0x6f,0x9c,0x9d,0x76, + 0x3c,0x10,0xd5,0xf9,0x82,0xd2,0x17,0xaf,0x19,0xee,0xc4,0x5c,0xff,0xe6,0xb9,0xf5, + 0xe8,0x5d,0x37,0x96,0x61,0xa7,0x81,0xfc,0xf9,0x36,0xab,0x12,0x3,0x93,0x3,0xb9, + 0x63,0x1a,0xef,0x63,0xbb,0x37,0x91,0xe7,0xcd,0x1d,0x26,0x27,0x4d,0xd3,0xa3,0x77, + 0x5d,0x5f,0xae,0x7f,0xeb,0xdc,0x6a,0x66,0x76,0xe3,0x5b,0xe7,0xd6,0xa3,0x77,0x5d, + 0xef,0xdd,0x9f,0xfe,0x5e,0x41,0x9b,0x61,0x9c,0xc9,0xae,0xbc,0x6e,0x62,0x5d,0x1c, + 0x3d,0xf1,0xfa,0x72,0xe3,0x5b,0xe1,0x3e,0x62,0xac,0x3b,0xb,0x5d,0x18,0x8b,0x9d, + 0x9f,0x60,0xfa,0x34,0x53,0x90,0xd4,0x9f,0xfb,0xe8,0xa,0x30,0x43,0xc7,0x10,0x18, + 0x21,0x15,0x34,0x7,0xdb,0x9f,0xcb,0x13,0xd7,0x97,0x84,0xdc,0xa7,0xa2,0x6b,0xac, + 0x1f,0x2,0x28,0xba,0x6a,0xf8,0x73,0xa7,0x4e,0x46,0x72,0x91,0x25,0xd2,0xf6,0x4a, + 0x60,0x8a,0xf0,0xd9,0xea,0x61,0xee,0x29,0xac,0x16,0xee,0x47,0xd6,0xcf,0x3f,0x79, + 0xe3,0x9b,0xb5,0xed,0xb2,0x8d,0x8a,0xe2,0xcc,0x13,0xfb,0x42,0xe6,0x42,0xd2,0xb7, + 0x1,0xe3,0xe8,0xa2,0xfd,0x9b,0x87,0xd6,0x73,0xcb,0x62,0x68,0xe5,0x14,0x3a,0x78, + 0x6a,0xf6,0x73,0xe6,0x89,0xeb,0xcb,0x8d,0x6f,0x9e,0x5d,0x59,0xb3,0xd9,0xcd,0x62, + 0x24,0x4b,0x4,0xfe,0xb6,0x20,0x9a,0xed,0x5e,0xef,0x44,0x6d,0x6e,0x47,0x4f,0xdc, + 0x58,0x6e,0x7c,0xeb,0xec,0xca,0xd9,0x3d,0xe8,0xa9,0xf4,0x36,0x32,0xfd,0xce,0x58, + 0x4,0x18,0xea,0x5f,0x3e,0xee,0xc1,0x8d,0x6f,0x9e,0x5d,0x7,0x72,0x9c,0xf4,0xc6, + 0x37,0x4f,0xe7,0xd1,0xb8,0x7f,0xfb,0xbf,0xdf,0xf8,0xf6,0xd9,0xf5,0xe8,0x89,0xeb, + 0xcb,0xcd,0x6f,0x9f,0x5d,0x7d,0xf3,0x81,0x89,0xd8,0x86,0xe4,0xfe,0xd1,0x13,0xaf, + 0x2f,0x66,0x66,0xfd,0x35,0x16,0xbc,0x94,0xea,0x8d,0xb9,0xfe,0xcd,0xa3,0x71,0x1d, + 0x70,0xbb,0xfe,0xad,0xa3,0x75,0x14,0x82,0xe4,0xf6,0x14,0x14,0x36,0x5c,0x12,0x2a, + 0x9f,0x54,0xef,0xae,0x6e,0x68,0xbd,0xcd,0x45,0x4f,0xd9,0x65,0xb0,0x50,0xf5,0x9, + 0xd4,0x7d,0x69,0xe0,0x3,0x5c,0xaa,0xab,0xf6,0x77,0xc6,0x1b,0x5c,0xff,0xd6,0xd9, + 0xf5,0xe8,0x89,0xd7,0x97,0x9b,0xdf,0x39,0xb7,0x32,0xb5,0x0,0xd4,0xe7,0x1a,0xf7, + 0x9a,0xda,0x86,0xdb,0xa8,0xe6,0xce,0x3c,0x5e,0xef,0xdb,0x77,0xce,0xad,0xfb,0x67, + 0x20,0xa1,0xaf,0xe1,0x10,0x1d,0xeb,0xd0,0x20,0xa3,0x6b,0x73,0x79,0x6f,0xf1,0x48, + 0xda,0x46,0xfb,0xa8,0x7f,0xe,0xe8,0xe7,0xf1,0x40,0xdf,0x2,0x67,0x79,0xa6,0xf8, + 0x74,0xe0,0x4f,0xbc,0xae,0x74,0x5e,0xea,0x49,0x3f,0x7d,0x5c,0x3b,0x64,0x2d,0x9f, + 0x79,0xfc,0xf5,0xe5,0x46,0x3d,0x8c,0xf5,0xfd,0xac,0xaf,0xe1,0xc0,0x5c,0xa3,0xf9, + 0xbd,0xeb,0xe7,0x39,0x3d,0x7,0x70,0x9f,0x92,0xd3,0xe2,0x32,0xd6,0xf3,0xe6,0xa4, + 0x5e,0xe6,0x52,0x3e,0xd,0x37,0x29,0xcf,0x94,0xc8,0x78,0x2d,0xd5,0xc6,0x97,0x1, + 0x3f,0xf1,0xf7,0x7a,0x72,0xbf,0xf9,0xb8,0x1f,0x54,0xf5,0xdc,0xf8,0xd6,0xd9,0x55, + 0x11,0x4c,0xfc,0x8c,0xe7,0x6b,0xb5,0x9d,0x94,0x72,0x2e,0x6c,0xc3,0xe5,0x8a,0x9f, + 0xed,0xd8,0xc3,0x34,0x2b,0x85,0xcb,0xf3,0x3b,0xf3,0xd8,0xb5,0xe5,0xc6,0xb7,0xce, + 0xaf,0x23,0x2b,0x83,0x3a,0xb9,0x6d,0x3,0xe1,0x3e,0x8c,0x6,0x61,0x7c,0xe,0xf0, + 0xb5,0x98,0xb9,0x9d,0x79,0xec,0xf5,0xe5,0xc6,0xb7,0xcf,0xaf,0xc6,0x14,0x2e,0x72, + 0x4f,0xdb,0xcf,0x19,0x75,0xbc,0xe3,0xe7,0xda,0xec,0x56,0xf9,0xe7,0xb2,0x9e,0xeb, + 0xf7,0xef,0xb4,0xb9,0xf6,0x5d,0x1d,0xb4,0x7e,0x40,0xd7,0x5f,0xbf,0x27,0x5d,0x13, + 0xaf,0x3d,0xee,0x4c,0xc8,0x75,0xb0,0xbb,0xdc,0x46,0x31,0x65,0x53,0x5b,0x9d,0xd3, + 0x8f,0x5f,0x5b,0x6e,0x7c,0xfb,0xdc,0x9a,0x19,0x84,0xba,0x7,0x3c,0xad,0xf1,0x51, + 0x68,0xdc,0xfc,0xf6,0xb9,0xf5,0xcc,0x63,0xd7,0x96,0x5b,0xdf,0x39,0x2f,0xe7,0xf0, + 0xc0,0x25,0xe8,0xf9,0xd1,0xd6,0x49,0xfb,0x7e,0x51,0x89,0x7c,0x8c,0x58,0xb4,0xc3, + 0x36,0x3b,0xe3,0x6d,0x42,0xd7,0x16,0xe6,0xad,0x9b,0xec,0xef,0xb8,0x97,0x4e,0x3f, + 0x76,0x6d,0x3f,0xe7,0x9e,0x39,0xbf,0x82,0x62,0xae,0x0,0x4,0x6d,0x9c,0x3d,0xde, + 0x71,0xef,0x9c,0x1d,0x98,0xea,0xea,0x3a,0xc9,0x8e,0x5a,0x45,0xb5,0x3,0xc1,0xb5, + 0x4a,0x0,0x5e,0xb0,0x33,0x8f,0x5f,0x5f,0xce,0x3c,0x7e,0x7d,0x39,0xfd,0xd8,0xf5, + 0x45,0xc6,0x33,0x6e,0x76,0xfa,0xf1,0xeb,0xcb,0xcd,0xef,0xd4,0xc0,0xeb,0x96,0xb5, + 0x78,0x3,0xd7,0xcc,0xdd,0x72,0x59,0x6a,0xc1,0xe0,0x85,0x50,0xcb,0xad,0xf5,0xa3, + 0x6d,0xd7,0x71,0x6d,0xed,0x56,0xdc,0xfc,0xf6,0xd9,0xf5,0xf4,0x63,0xd7,0x17,0x76, + 0xfa,0x3d,0xf3,0xd8,0xf5,0xe5,0xf4,0xe3,0x75,0x6e,0x24,0xf3,0x2f,0x97,0xea,0x2b, + 0x3a,0x99,0xf5,0x39,0x6e,0x33,0xbe,0xf7,0x10,0xec,0x68,0x7e,0x79,0xf3,0xdb,0xe7, + 0xd6,0xd3,0x8f,0x5f,0x5f,0x58,0x83,0x5c,0x54,0xaa,0x3c,0x97,0xcf,0x2c,0x19,0x18, + 0x69,0x2b,0xd1,0xc,0x2e,0x4d,0x76,0x83,0xf,0xe9,0x18,0x13,0x18,0xd1,0xfc,0xa2, + 0xc4,0x61,0x18,0xb,0xf0,0x46,0x8d,0x15,0x53,0xe0,0x8f,0x4f,0xb1,0x4,0xf1,0xec, + 0x3e,0x34,0x9f,0x42,0xa9,0xeb,0x83,0x83,0xbd,0x4d,0xbb,0x1c,0xd2,0x95,0x29,0x76, + 0xc0,0x29,0x63,0x96,0x18,0x46,0xde,0x6e,0x51,0x6d,0x0,0x20,0x75,0x1c,0x9a,0xfe, + 0x3f,0x92,0x6b,0x9d,0xfd,0x57,0xcc,0xf5,0xaa,0x7e,0xd3,0x8c,0xf3,0x15,0xbe,0xff, + 0x4c,0xcb,0xf9,0xd6,0x77,0xce,0xaf,0xa7,0x1f,0x7b,0x7d,0x61,0x36,0x82,0xfa,0x1f, + 0xec,0x9f,0x7b,0xfa,0xb1,0xd7,0x97,0x9b,0xcf,0x9c,0x5f,0xed,0x80,0x62,0xa1,0x1, + 0x76,0xf3,0x3b,0xe7,0xd7,0x5b,0xcf,0x9c,0x5f,0x95,0xf4,0xe1,0x72,0x3f,0x66,0xda, + 0xb,0xc,0xde,0x64,0xd3,0x8e,0x53,0x8f,0x5d,0x5b,0x6e,0x3e,0x73,0x6e,0x45,0xa8, + 0x68,0xa4,0xad,0x48,0x3c,0xe1,0xac,0xe9,0x3f,0xf7,0x37,0x70,0x11,0x8a,0xf1,0xa4, + 0xa0,0xe5,0x96,0xd1,0xd1,0x5d,0x9a,0x93,0xab,0xaf,0xc0,0x5f,0xee,0x1a,0xe,0xae, + 0x7b,0x98,0x7,0x40,0x8c,0x14,0x67,0xf4,0x76,0xdb,0xd3,0xa7,0x1f,0xbb,0xb6,0xdc, + 0x7c,0xe6,0x7c,0xaf,0x78,0x51,0x37,0x44,0x7b,0xe,0x37,0x9f,0x39,0xbf,0x9e,0x7e, + 0xec,0xda,0xa2,0x1c,0x77,0xd6,0x34,0xa7,0xe,0xa5,0x8f,0xaa,0xf,0xcc,0x50,0x48, + 0xba,0x8,0x66,0xa7,0x1f,0x7d,0x7d,0xe9,0xcf,0x8e,0xf9,0xcf,0x30,0x59,0x7,0x6e, + 0x21,0x51,0xab,0xd7,0x71,0xf3,0x99,0xf3,0xeb,0xa9,0x47,0xaf,0x2d,0xe2,0xfd,0x0, + 0xe5,0x91,0x9f,0x7e,0xf4,0x9a,0xae,0x21,0x1b,0xdf,0xe7,0xf4,0xa3,0xd7,0xf6,0xcf, + 0xaf,0x5d,0xbe,0x29,0xbb,0x21,0x11,0xf,0xf6,0x37,0x39,0x55,0xdf,0xd7,0xd,0x72, + 0x1d,0x6d,0x5f,0x79,0xd9,0x9f,0xd1,0xcd,0x67,0x2e,0xac,0xa7,0x1f,0xbd,0x26,0xa, + 0x8d,0x6a,0x87,0x3c,0x40,0x7d,0x37,0x9f,0x39,0xbf,0x9e,0x7e,0xf4,0xda,0x12,0x37, + 0x7c,0x2b,0xf8,0x24,0x0,0xfb,0xbe,0x56,0x6f,0x3d,0x73,0x61,0x15,0x25,0xfd,0xa2, + 0xb9,0x65,0xbb,0xbe,0xd3,0x8f,0xd6,0xe7,0x67,0x59,0xb6,0x37,0xa9,0x7c,0x3a,0x75, + 0x65,0x83,0x9e,0x8,0x2b,0x0,0x26,0x1,0x22,0x57,0x57,0x36,0xee,0x8a,0xbb,0xc7, + 0xce,0xd4,0xfe,0x7b,0xa7,0x1f,0xb9,0xb6,0xdc,0x7a,0xf6,0xc2,0xca,0x7e,0xe8,0x8, + 0x9d,0x9d,0x62,0x88,0xe8,0xd3,0xa8,0x58,0x46,0xca,0x68,0xee,0x52,0xc5,0xf8,0x66, + 0x76,0xeb,0x99,0x73,0xeb,0xa9,0x47,0xae,0x2f,0xac,0x30,0xd6,0x7e,0x7e,0xeb,0xd9, + 0x73,0xeb,0xe9,0x47,0x6a,0xd0,0x84,0xd9,0xa9,0x47,0xaf,0x2f,0xb7,0x9e,0x39,0xb7, + 0xaa,0x24,0x1e,0x5,0xd,0xe8,0x9c,0x5b,0xb4,0x7d,0xa1,0x96,0x92,0xce,0xc2,0x3, + 0x49,0xd9,0x4a,0x81,0x3,0x59,0x94,0xc1,0x93,0xba,0xda,0xa9,0x47,0xf6,0x6b,0x8b, + 0x9c,0xe6,0xf6,0x79,0xed,0x7b,0x1e,0xf2,0xc7,0x8e,0xee,0x62,0xed,0x7f,0xdb,0xfb, + 0xa,0xc0,0x2c,0x28,0x16,0x29,0x4a,0x3e,0xfc,0x6f,0xa1,0x4e,0xc7,0x5b,0x82,0x34, + 0x2c,0x20,0x30,0x67,0xad,0xcd,0x92,0xf5,0x6c,0x2,0xca,0x1f,0x81,0x33,0x39,0xe4, + 0x33,0x15,0xf1,0xaf,0x5c,0x71,0x13,0x1e,0x65,0xfe,0x7b,0x56,0x48,0x9a,0x5,0x3e, + 0x46,0x2f,0x8b,0x59,0xc2,0x5b,0x28,0xe1,0xb1,0x82,0x5c,0x46,0x3e,0x86,0xd4,0x3a, + 0xb9,0x31,0xd9,0x40,0x9a,0x72,0x12,0x5b,0x3f,0xfa,0xd6,0x33,0xe7,0xd7,0x5b,0xcf, + 0x9e,0x5f,0xe1,0xb0,0xe3,0x67,0xcf,0xaf,0x77,0x3f,0xb2,0x1f,0x20,0x82,0x66,0x26, + 0x5e,0x6d,0xf6,0x5,0x47,0xf2,0xa4,0x57,0xf1,0x9e,0x11,0xb4,0x0,0xd8,0xf1,0xb3, + 0xe7,0xf6,0xcf,0x8b,0xb6,0x9c,0x1b,0x19,0x52,0xb0,0xf2,0x5e,0xdd,0x8b,0xc7,0xcf, + 0x9c,0x5f,0x6f,0x3d,0x73,0x6e,0xb5,0x60,0x80,0x73,0xfc,0x6c,0xb,0xe0,0x4e,0xad, + 0x43,0xb7,0x24,0x64,0xe4,0x7a,0x3f,0x55,0xb7,0x9f,0xd0,0xa0,0x8d,0xf,0xdd,0x66, + 0xe9,0x84,0x66,0x3f,0x7e,0xf6,0xfc,0x7a,0xea,0x91,0xd7,0xfb,0xfd,0x41,0x72,0x48, + 0xcc,0xda,0xe1,0x71,0xc4,0x16,0xc7,0x5f,0xed,0x30,0x3b,0x7e,0xf6,0xfc,0x7a,0xfc, + 0x6c,0xd,0x26,0x81,0x3,0x7f,0xf7,0xc3,0xfb,0x21,0x67,0x16,0x3c,0xc2,0x89,0xae, + 0xe5,0xf5,0x5e,0x9c,0x7a,0xf8,0xda,0xc2,0x1a,0xe,0xc9,0x36,0x9e,0x38,0xd5,0x30, + 0x5d,0xe3,0xc7,0xcf,0x9e,0x5f,0xef,0x7e,0xf8,0xda,0x40,0xdb,0x6f,0xb5,0x43,0x41, + 0xf4,0x5d,0x61,0x29,0x6c,0xfa,0xc8,0xdd,0x54,0x85,0xee,0xd6,0xb3,0xe7,0xd7,0x53, + 0x8f,0xec,0xd7,0xc3,0x1a,0xeb,0xdd,0x35,0x8d,0xae,0x51,0x78,0xd1,0x40,0x74,0x45, + 0xcd,0xe7,0x4a,0xfd,0xe0,0x53,0xf,0x5f,0x5b,0x8e,0x9f,0x6b,0xeb,0x89,0xbf,0x33, + 0x92,0xb2,0x63,0xd2,0xd6,0x37,0x4a,0x14,0xb6,0xe0,0xdd,0x8d,0x76,0x3f,0xaf,0x2e, + 0x89,0x6d,0x20,0x6c,0x16,0x53,0xd,0x7e,0x63,0xc6,0x8,0xba,0xf3,0x21,0x4b,0xaf, + 0x25,0xe,0x79,0x13,0xb6,0x41,0x10,0xa3,0x37,0xc8,0x1e,0x64,0xed,0x14,0x77,0x15, + 0x3a,0x8b,0x4a,0x74,0xe3,0x9c,0x23,0xa6,0x14,0x8d,0xc,0xd4,0x9d,0x91,0xa9,0x7b, + 0x71,0x4c,0x8,0xf1,0xab,0x60,0xd,0x14,0x68,0x1f,0x40,0x7f,0xf,0xc3,0x3b,0x23, + 0x32,0x80,0xa2,0xa2,0xdd,0xf1,0x73,0x17,0xd6,0x53,0xf,0x5f,0x5d,0xee,0x7e,0xf8, + 0xea,0x72,0xfc,0xdc,0x85,0xd5,0x42,0x1,0xed,0xe1,0x19,0x9e,0x94,0x8a,0x25,0xba, + 0xc2,0x50,0xd7,0xea,0xf8,0xb9,0x73,0xeb,0xdd,0x8f,0xbc,0xbe,0xdc,0xfe,0xee,0xb9, + 0x35,0xce,0x86,0x5d,0x31,0x2e,0x79,0xe,0x54,0x2c,0xc8,0xf3,0xc1,0xb2,0xa,0x95, + 0x72,0xc5,0x93,0x25,0xcf,0xc1,0x70,0x16,0xb9,0xcd,0xa1,0x9f,0xc7,0x32,0x4e,0xa6, + 0x2d,0xcd,0x76,0x60,0xdc,0xfd,0xc8,0xeb,0xcb,0xf1,0x73,0x7b,0xd0,0xd5,0xac,0x5f, + 0xaf,0x35,0x71,0x9b,0xb9,0xb5,0xd5,0xf9,0xa3,0x9e,0x51,0x9b,0xd2,0x2f,0xb4,0xa9, + 0x5e,0x73,0xd2,0x6e,0x96,0x2e,0x63,0xb0,0x44,0xea,0x7d,0xba,0xc9,0x98,0x82,0x5f, + 0x1a,0xf2,0x38,0xe7,0xd1,0x83,0x79,0x50,0x5d,0x73,0x5a,0xdf,0xad,0x82,0xf7,0xc4, + 0x81,0x8f,0xdc,0x57,0xbe,0xa7,0xb7,0x9f,0x3b,0xd7,0xf,0x5d,0x24,0x24,0xf8,0x0, + 0xba,0xb1,0x1a,0x96,0xb4,0xb8,0x9,0x9f,0xe0,0x50,0xcc,0x82,0x93,0xbe,0xc5,0xb4, + 0x1a,0x24,0xa1,0x23,0xd6,0x21,0x77,0x79,0xf6,0xde,0xc7,0x2e,0xdd,0x75,0xc9,0x22, + 0x17,0xd7,0x33,0x9b,0x3,0x1,0xa1,0xed,0x66,0xb7,0xbf,0x77,0x7e,0xbd,0xfb,0xa1, + 0x6b,0xcb,0xed,0xef,0x9d,0x5f,0xe1,0xf9,0xda,0x7,0x98,0x2c,0x3b,0x4e,0x7b,0x40, + 0x80,0xd3,0xd4,0x5d,0xdb,0x68,0x88,0x7e,0x5,0x66,0x77,0x3f,0x74,0x6d,0xb9,0xfd, + 0xdd,0xf3,0xab,0x78,0xf,0x98,0x7a,0x54,0x8b,0x98,0x6a,0xc5,0x50,0xb0,0x99,0x4c, + 0x7f,0x5f,0x54,0xf4,0x63,0x31,0x3b,0xfe,0xee,0xfe,0x7d,0x98,0xab,0x2b,0x6a,0x59, + 0xce,0x3,0xa1,0xbc,0x66,0x3d,0x9c,0x7,0xd,0xb0,0x3,0xd7,0x3d,0x32,0xba,0x16, + 0x4e,0x77,0xdb,0xe5,0x1e,0x38,0x6,0xc2,0xbc,0xe3,0x1c,0xa4,0xd5,0x1f,0xbc,0xc7, + 0x65,0x4c,0x14,0xc0,0x93,0x3,0x9a,0x64,0xf9,0xbb,0x99,0xaa,0x43,0x6,0xf,0x6, + 0xa9,0xd6,0x27,0x9c,0x6f,0xa7,0xea,0x7f,0x7f,0x2e,0x17,0xa4,0x5b,0xe1,0x9d,0x31, + 0x62,0x92,0xd8,0xb1,0xe3,0x17,0x8b,0x6f,0x99,0xbb,0x74,0x12,0xda,0x9f,0xdf,0xf9, + 0xe0,0xd5,0xe5,0xf6,0xf7,0x2e,0xac,0x16,0xe0,0xac,0x8,0xe3,0xa,0xc1,0x5f,0xc8, + 0x75,0xc4,0x4e,0x6,0x75,0x34,0xad,0x5d,0xff,0xfe,0x19,0xa2,0x1b,0x52,0xbf,0xe3, + 0xed,0xef,0x5e,0x58,0xd5,0xbe,0x38,0x62,0x4,0x7c,0xea,0xd3,0xc1,0xfb,0x55,0xce, + 0x9f,0xf8,0x1c,0x90,0x9f,0x8b,0x47,0x0,0x19,0x32,0xb3,0x98,0xef,0x95,0xc1,0xec, + 0x9d,0x97,0xaf,0xed,0xdf,0x21,0x64,0x52,0x1e,0x12,0x75,0xc6,0x16,0x39,0xdb,0x7f, + 0x47,0xcc,0x13,0xe6,0x7b,0x36,0xee,0x67,0xf0,0x99,0x6,0x23,0xfc,0x99,0x1e,0xff, + 0x7d,0x8f,0x8f,0x19,0xa9,0xf0,0xdd,0x63,0xdc,0x68,0xff,0x7b,0xfb,0x7b,0x17,0xd7, + 0xe,0x2a,0x9f,0x8c,0xa9,0xbc,0x63,0xe0,0x60,0x27,0x99,0xf,0x27,0xd9,0x9b,0x59, + 0x80,0x9f,0xdb,0xd4,0xbf,0xd5,0x2c,0x3b,0x33,0x39,0x21,0xfe,0x66,0x95,0xab,0xce, + 0xef,0x74,0xde,0xa6,0xe2,0xed,0x9e,0xe3,0x3f,0xcf,0xdc,0xeb,0x7f,0xdf,0xfe,0x6e, + 0x9b,0xe1,0xf8,0x8,0x62,0x8e,0xd4,0xd5,0x94,0x20,0xe2,0x51,0x5,0x8c,0xae,0xd1, + 0x55,0xc7,0x9d,0x33,0xe0,0x77,0x5e,0x7e,0xbd,0x1e,0xa8,0x3e,0x6c,0x2,0x6d,0x28, + 0xb3,0x71,0x95,0xe9,0x9b,0xa5,0x99,0x68,0xbf,0xd7,0x98,0x54,0xf5,0xa1,0x9b,0xe0, + 0xd0,0x60,0xe3,0x93,0x7b,0x7,0xcf,0x4a,0x97,0x30,0x13,0xd0,0xc7,0x30,0xed,0x8, + 0xa,0xe,0xfc,0x3b,0xc8,0xad,0xcc,0x7e,0x98,0x72,0xb2,0x66,0x59,0xe5,0x2c,0x44, + 0xf,0xcd,0x5a,0xe9,0xbd,0xf9,0xf7,0x1d,0x50,0x94,0x7b,0x58,0x53,0x2c,0x60,0x3a, + 0x2a,0x17,0x24,0x67,0x29,0x79,0x7d,0xfb,0xe,0xa5,0x72,0x58,0xcd,0xa5,0xcb,0xc2, + 0x94,0x32,0xe6,0x6e,0xb2,0xb2,0x93,0x9a,0xde,0xf2,0xba,0x9,0x19,0x34,0x3b,0x7e, + 0xb1,0x86,0x7d,0xbb,0xe7,0x65,0x34,0x9e,0x44,0x16,0x35,0x5,0x5c,0x1a,0xeb,0xb0, + 0xfb,0x1e,0x7,0x3a,0xe2,0x23,0xf7,0xb5,0x55,0x9f,0x3d,0x83,0x4d,0x39,0x71,0x85, + 0x8c,0x58,0xa8,0x62,0x76,0xf5,0x73,0x6b,0x8,0xde,0xd4,0x5,0x71,0x88,0xf3,0x93, + 0x1e,0x68,0xb0,0x77,0x3e,0x70,0x75,0xb9,0xf3,0xbd,0xb,0x7d,0xdf,0x75,0x97,0x41, + 0xe6,0xec,0x4b,0x72,0xe4,0x53,0x25,0xc4,0xc6,0x84,0x41,0x46,0x2c,0x9a,0x84,0x53, + 0x4e,0x92,0xea,0x3d,0xba,0xf3,0xfc,0xf9,0x95,0xf5,0xfd,0x95,0x42,0x49,0xde,0xdb, + 0xee,0xaa,0x57,0xe1,0x2e,0x67,0x91,0xd0,0x4a,0x19,0x45,0x1c,0xf6,0x64,0x56,0x20, + 0x53,0xfe,0xb8,0xc7,0x75,0x3f,0xb,0x22,0x41,0x73,0xfc,0xae,0xcb,0x57,0x3b,0x8a, + 0xfe,0x8d,0x17,0x2f,0xac,0x49,0x9d,0x32,0x9c,0x13,0xe6,0xc1,0xe9,0xd3,0x2,0x87, + 0xdd,0xf4,0xf7,0x9d,0xac,0x53,0xf3,0x7b,0xef,0x9,0xdd,0x9d,0xe7,0x2f,0xae,0x8c, + 0x86,0x75,0xcb,0xd2,0x1c,0x51,0x6e,0x4a,0xcf,0x48,0x35,0xed,0x2,0xd4,0xa7,0x5b, + 0xf6,0x17,0x7b,0x85,0x5b,0xf8,0xb3,0xcd,0x78,0xfc,0xc3,0xe5,0x2c,0xea,0x3b,0xb4, + 0xcf,0xbf,0xeb,0xf2,0xd5,0xc5,0xcc,0xec,0xce,0xb,0x7b,0xe0,0x93,0x1d,0x86,0xb0, + 0xee,0x52,0x93,0x3d,0x97,0x88,0x77,0x9e,0xbf,0xb0,0xc6,0xc0,0x13,0xe4,0xb5,0xb4, + 0x8b,0xd9,0xee,0x45,0x21,0x17,0xbf,0x29,0xcc,0xd3,0x53,0x9b,0x40,0x38,0xeb,0x21, + 0x6e,0x78,0x60,0x2d,0x88,0x1d,0xb7,0x4b,0x2f,0xa5,0xbf,0xcf,0x49,0xf1,0xb0,0x6e, + 0x80,0xd,0x57,0xb5,0x24,0x9f,0x71,0xfc,0xdc,0x26,0x3a,0xc2,0x8,0x15,0x3a,0x3, + 0xb3,0x59,0xb7,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xec,0xce,0xf3,0xe7,0xd7, + 0xbb,0x2e,0x5f,0xab,0x37,0xbc,0xce,0x67,0x7c,0x0,0x21,0xac,0x3,0xc,0x40,0x6d, + 0x41,0x45,0x10,0x20,0x76,0x55,0xb9,0x85,0xea,0x5c,0xc9,0xc4,0x43,0xb,0x52,0xb5, + 0x3a,0x90,0xfc,0x80,0x79,0xfe,0xed,0xf5,0x1a,0xef,0xba,0x7c,0x6d,0xa0,0x71,0xe9, + 0x34,0x16,0xa4,0x7b,0xcf,0xb4,0x28,0x43,0x8b,0xda,0xed,0x3e,0x3,0xf3,0x42,0xb8, + 0xcd,0x6f,0xd0,0xe7,0xf1,0xb5,0xb1,0xe4,0x62,0x82,0x55,0x5,0x93,0x96,0xb8,0x74, + 0xf8,0x67,0x8e,0x60,0x7e,0x81,0x99,0x89,0x26,0x13,0xf6,0x2c,0xb5,0xde,0x61,0x46, + 0xbf,0xe7,0x1,0xf1,0x3f,0x0,0x85,0x1e,0xe,0x6b,0x45,0xf9,0xba,0x24,0xc,0x30, + 0xb3,0x77,0x3c,0x70,0x6d,0x79,0xe3,0xa5,0xba,0x79,0xdc,0x15,0x69,0x4e,0x8,0x8, + 0xae,0xc6,0x1a,0xc2,0xf6,0xfb,0x2f,0x9d,0x5f,0xef,0x7a,0xe0,0xda,0xc2,0x94,0xe, + 0x18,0x12,0x80,0xcc,0x24,0x38,0xe6,0xf7,0x63,0x2f,0xf9,0x56,0xc5,0xc2,0xe9,0x1e, + 0xb9,0x1b,0x83,0x90,0xfa,0xba,0x89,0x95,0x46,0x58,0x47,0xb0,0x3,0x11,0xdc,0x7, + 0x2d,0x92,0xf2,0xaa,0x9e,0x18,0x8e,0x69,0xd3,0x78,0x97,0x37,0x5e,0x3c,0xbf,0xbe, + 0xe3,0x81,0x6b,0xcb,0xf7,0x5f,0xba,0xb0,0xf3,0xa9,0x39,0x21,0x73,0xe,0x9e,0xd, + 0xf8,0x9,0x15,0x3e,0xe2,0x3d,0xd2,0x6c,0x77,0xe1,0x16,0xad,0x8f,0x64,0x1f,0xbb, + 0x2a,0xfc,0x21,0x38,0x85,0xd,0xbf,0x74,0xad,0x68,0xef,0xba,0xff,0xea,0x72,0xe7, + 0xc5,0xb,0x53,0x2f,0x68,0xa9,0x18,0x2d,0x69,0x4d,0x75,0x60,0x64,0x92,0xe6,0x9, + 0xa3,0x34,0xcc,0xc,0x72,0x22,0x69,0x91,0x68,0x6f,0xac,0x15,0x21,0x7e,0xd8,0x13, + 0xb0,0x7d,0xd4,0xe4,0x86,0x8f,0x4,0x2a,0x75,0x1e,0x5d,0xf5,0xe7,0x67,0x74,0x26, + 0x4c,0xe9,0x69,0xfb,0x1f,0xde,0xe0,0xfb,0x64,0x66,0xef,0xb8,0xff,0xea,0x32,0x63, + 0xc7,0xf0,0x1a,0xdf,0x83,0x6,0xf1,0xa7,0x7c,0x28,0xd6,0xb9,0x67,0xad,0x8f,0xb8, + 0x1f,0xdf,0x71,0x7f,0xd,0x7e,0x2f,0x5e,0x58,0x83,0xdf,0x1e,0xed,0xa3,0x59,0x46, + 0x1b,0x6c,0xb2,0x82,0x66,0xba,0x4d,0x54,0xf1,0xb8,0x33,0x8b,0xc4,0xd9,0x46,0xfa, + 0x6e,0xb0,0x3d,0xa9,0x69,0xd7,0x38,0xee,0x8f,0x6,0xe1,0xf6,0x9f,0x37,0x5e,0xba, + 0xb8,0xde,0x75,0xff,0x95,0xe5,0x8d,0x17,0x2f,0xae,0x6c,0xba,0xc3,0x85,0x5f,0x52, + 0x15,0xc,0x49,0x66,0x2f,0x10,0x29,0x70,0x89,0x51,0x98,0x43,0x3b,0x93,0x68,0x63, + 0x0,0xef,0xcc,0x92,0xfe,0x7d,0x1d,0xf6,0x8e,0xfb,0xaf,0x2c,0x6f,0xbc,0x74,0x71, + 0xed,0x14,0x61,0x36,0x94,0x62,0x60,0xa4,0xab,0x4b,0x61,0x8c,0x1b,0xef,0xb8,0xff, + 0xea,0xf2,0xc6,0x4b,0x17,0x57,0xc5,0xde,0xaa,0x37,0x47,0x1b,0x47,0xb0,0xf2,0xe5, + 0xc9,0xa8,0x9a,0xc4,0x59,0x52,0xbc,0xd,0xc3,0xf7,0x36,0x54,0x28,0x94,0xb9,0xfe, + 0xf2,0x7d,0xd7,0x96,0x37,0x5e,0x6c,0x73,0x1b,0x1f,0x3e,0xdf,0x13,0x5a,0x58,0x2, + 0x5,0x21,0xe6,0x51,0x31,0x3b,0xb3,0xc0,0x5f,0xa5,0xac,0xa8,0xde,0x25,0x6e,0xed, + 0x72,0xa5,0x2b,0x10,0xc3,0x8e,0xd4,0x9c,0x64,0xd4,0xa9,0xea,0x2b,0xbd,0xa5,0xa7, + 0xfe,0xcd,0xda,0x76,0x9e,0x65,0xe8,0xea,0xe8,0xe6,0x9d,0xc6,0xe7,0x9b,0xd9,0x3b, + 0xda,0x7d,0x2a,0xfa,0xbe,0xa8,0x4f,0x1a,0x95,0xd6,0x31,0xb2,0x31,0x6d,0xdd,0xd, + 0xa1,0x1a,0xa7,0xb6,0x24,0x5,0x1f,0x73,0x49,0x3a,0x42,0x36,0x62,0xce,0x22,0x94, + 0xb4,0x5a,0xd1,0xe9,0x24,0x84,0xe4,0x24,0x85,0xf,0x18,0xec,0xfb,0x2f,0x5e,0x58, + 0x77,0x93,0x82,0xc1,0x6d,0xef,0xa0,0x1e,0x4e,0xa0,0xb6,0xc9,0xd8,0x83,0x2a,0x59, + 0xdf,0xcc,0xde,0x71,0xef,0xd5,0xe5,0xfb,0x2f,0x9f,0x5f,0xfb,0xb8,0x62,0x63,0x4a, + 0x96,0x56,0xd4,0x5d,0xf4,0x66,0x33,0x55,0x91,0xa,0x15,0x9f,0x85,0xb6,0xb5,0x89, + 0xa7,0xc0,0xfe,0xbf,0xdf,0x7f,0xe9,0xc2,0xfa,0x8e,0xfb,0xae,0x2e,0x3f,0x78,0x79, + 0xaf,0x8a,0x1c,0x79,0xee,0x2e,0xf3,0xe2,0x49,0x47,0xca,0x89,0x9b,0x8e,0xc9,0x3a, + 0xc2,0x44,0x67,0x21,0x6,0xa3,0xa0,0xdf,0x34,0xe1,0x66,0x31,0x56,0x40,0x15,0xa9, + 0x62,0x96,0xd7,0x9f,0x20,0x32,0x12,0x51,0x1a,0xff,0x92,0x40,0x5b,0xf7,0xac,0x8d, + 0x73,0x46,0xee,0x84,0x68,0x2a,0x1c,0xce,0x82,0x49,0x77,0x25,0x66,0x31,0xe2,0xc1, + 0x80,0x59,0xfa,0x69,0x6f,0x19,0xa0,0x67,0xf6,0x4e,0x93,0xf6,0x9d,0x3c,0xf4,0xa8, + 0xc0,0xbb,0xab,0xc5,0x29,0x66,0x20,0xbe,0x2d,0x2b,0x2e,0x46,0xbd,0xff,0xef,0xbf, + 0x74,0x61,0x4d,0x58,0x8f,0xe4,0xa,0x37,0xab,0x5c,0xed,0x40,0x8b,0x86,0x5,0xa0, + 0xcc,0xbe,0xff,0x12,0x55,0xca,0x16,0xbd,0xce,0x83,0x47,0x2c,0x74,0xad,0x22,0xa8, + 0x30,0xfe,0xf2,0xbd,0x57,0x16,0xbe,0xde,0x7d,0xcd,0x8f,0xf7,0xef,0x3e,0x16,0x3c, + 0x5a,0x50,0xb5,0xa9,0x14,0xa4,0xe3,0x81,0xca,0xe,0x7a,0xd2,0x2a,0x74,0x76,0xf, + 0xc,0xea,0x77,0x30,0xfb,0xfe,0xcb,0x17,0xd7,0x5f,0xbe,0xf7,0xca,0xf2,0x83,0x57, + 0x2e,0xae,0x3c,0x6b,0x4f,0x78,0x24,0x1c,0x96,0xa0,0x6e,0x98,0x97,0x37,0x5e,0xba, + 0xd8,0xd9,0x52,0x82,0xfe,0xaf,0x9d,0x18,0xed,0x14,0x6a,0x4d,0xbe,0x7f,0xff,0xd1, + 0x21,0x1b,0x42,0x4e,0xa,0x42,0xf6,0xc6,0xba,0x18,0xda,0x5c,0x15,0x3f,0xa1,0x5e, + 0x16,0xda,0x75,0xd,0x1d,0x55,0x68,0x61,0xea,0xf5,0xc6,0x8b,0x47,0xca,0x24,0x9e, + 0x1a,0x3f,0xa7,0x28,0xeb,0xdb,0xe3,0xdd,0xf8,0x9d,0x93,0x5a,0x7d,0x98,0x6a,0x1c, + 0xbb,0x92,0x54,0x78,0x36,0x34,0x66,0x52,0x48,0xba,0xe5,0x60,0xad,0xef,0xe4,0xda, + 0x86,0x8e,0x83,0x23,0x22,0x48,0x82,0xf5,0xf7,0x2a,0x1b,0x71,0x2e,0xac,0xd2,0x1c, + 0x70,0x6d,0x20,0x8e,0x80,0xc5,0x95,0xa5,0xb6,0xab,0xa2,0xbf,0xb2,0x87,0x59,0x34, + 0x57,0x83,0x70,0x17,0x57,0x35,0xe1,0x26,0x62,0xa8,0xaa,0x45,0x65,0xb4,0xa8,0x4c, + 0x84,0xa4,0x7f,0x9d,0xdd,0xa9,0x74,0xc0,0x69,0x42,0x13,0x4,0xfd,0x79,0xc6,0x37, + 0xef,0x73,0x5b,0xd3,0x16,0x6b,0xb,0xbc,0xa9,0xc2,0x69,0x9b,0x92,0x2,0x92,0xfe, + 0xae,0x8b,0x9b,0x5a,0x3e,0x9f,0xa2,0xb,0x95,0x8e,0xd5,0x13,0x96,0x22,0xa8,0x1d, + 0xfd,0xf2,0xbd,0x57,0x97,0x1f,0xbc,0x72,0x61,0xfd,0xa5,0x7b,0xae,0x2e,0x20,0x77, + 0x27,0x9f,0xb5,0x23,0x26,0xca,0x6e,0x1e,0x3a,0x43,0x1e,0x2a,0x8b,0x6e,0xc4,0x41, + 0xb,0x3f,0x66,0xfb,0xca,0xa3,0x9d,0x9c,0xc1,0xa4,0xde,0xd2,0xae,0xad,0x5d,0xb7, + 0xfc,0x5e,0x70,0x1e,0x93,0x6f,0xb,0x9f,0x20,0xdc,0xf9,0xf9,0x4d,0xdc,0xb1,0x5, + 0xee,0x11,0xf4,0x9b,0x99,0x8f,0x6f,0xb9,0x2a,0x11,0xba,0x5c,0x5c,0x2c,0x6e,0xd3, + 0xf6,0x9d,0x7c,0x6,0x1,0x17,0xd4,0xbf,0x7e,0xfc,0xf9,0x97,0xee,0xd9,0xf,0x63, + 0xbd,0x51,0x11,0xa1,0x1f,0x80,0x10,0x36,0xe7,0x55,0x27,0x8b,0xae,0xe0,0xa4,0xa7, + 0xc5,0x1f,0x72,0xcb,0x33,0x7e,0x8e,0x67,0x1c,0x8a,0x85,0x2a,0x26,0xe3,0x40,0x2, + 0x8f,0x1c,0x79,0xcd,0x5,0x21,0x8b,0x70,0xaf,0x4c,0x28,0x64,0x3f,0x78,0xe5,0xe2, + 0x9a,0xf2,0x92,0x99,0xf,0x34,0x7d,0x7f,0x75,0x30,0x1f,0xd7,0xf3,0x4b,0x97,0xae, + 0x2e,0x3f,0x78,0xf5,0xe2,0x9a,0xf6,0x1a,0x8f,0x20,0x3,0x63,0x66,0xac,0x6d,0x58, + 0xe0,0xd7,0xa9,0xd8,0x96,0x45,0x3e,0x37,0x9d,0x8f,0xb0,0xf9,0xa6,0xb0,0x5c,0x51, + 0x92,0x36,0xac,0x62,0x8a,0xc2,0x73,0x17,0x91,0x96,0xc0,0x4,0x4a,0x58,0x25,0x9b, + 0x3d,0x7b,0x22,0xf5,0x62,0x74,0xde,0x58,0x89,0x2f,0xab,0x4f,0x7a,0xc2,0x32,0xf5, + 0xd3,0x42,0xa,0x16,0x2a,0xba,0x46,0x88,0x1f,0x33,0x76,0x1d,0x52,0xa5,0x74,0xf2, + 0x7,0xaf,0x5e,0x5a,0x7f,0xe9,0xd2,0x6b,0x8b,0xc6,0xc8,0xb4,0x6c,0xb4,0xe9,0x51, + 0x20,0x1a,0xf,0xd1,0xbd,0x8e,0x15,0xef,0xcc,0x75,0x9d,0x20,0xfe,0xac,0xde,0xc7, + 0x12,0xb5,0x91,0xd9,0x85,0xa8,0xa1,0xfb,0x30,0x71,0xff,0x89,0x59,0x49,0xf4,0x10, + 0xe7,0x3,0xe3,0x87,0xaf,0x5c,0x58,0x7f,0xf0,0xca,0x3e,0xef,0xe2,0x3d,0x8,0x71, + 0x93,0x19,0xe0,0x1b,0x50,0xb0,0x69,0x60,0x1f,0xb8,0xa,0x74,0x80,0x8d,0x54,0xd2, + 0xdf,0x9,0x7d,0xcc,0xb4,0x2,0xb8,0xfc,0xbb,0x6f,0x66,0xbf,0x78,0xf1,0xea,0xf2, + 0xc3,0x57,0x7,0x7a,0x10,0x30,0xfb,0xe1,0xab,0x17,0xd6,0x1f,0xbc,0x5a,0x1,0x2e, + 0x50,0x8f,0xdc,0xa4,0xe3,0x1e,0x74,0x97,0x3b,0x2a,0xd9,0x2d,0xf9,0xdb,0xba,0x2b, + 0xa,0xd6,0x91,0x5d,0x76,0x38,0x93,0x83,0x29,0xc2,0x7f,0x50,0x95,0x62,0x72,0x63, + 0x41,0x6e,0x57,0x41,0x18,0xaa,0xd7,0xa9,0x62,0x3b,0xb0,0x19,0x62,0x36,0x78,0xdf, + 0x46,0x7b,0xca,0x74,0x56,0x5,0x9e,0x58,0xc9,0xa8,0x77,0x8e,0x67,0x3f,0x7c,0xf5, + 0xc2,0xfa,0xc3,0x7a,0x48,0x4d,0xbd,0x94,0x2d,0x63,0xf,0x7e,0xf0,0xea,0x85,0xf5, + 0x17,0x2f,0x5e,0x5d,0x2c,0xac,0xbb,0x69,0x95,0x1e,0xa4,0x7e,0x93,0xc0,0x50,0x74, + 0xd7,0xa,0xee,0x6e,0xc3,0xeb,0x19,0x16,0x75,0x97,0xa7,0x98,0x90,0x30,0x7f,0x8d, + 0xa7,0x1f,0x98,0xcd,0x91,0xda,0xaf,0xe2,0x76,0x34,0xf,0x76,0x6,0xfb,0xe1,0xab, + 0x17,0xd7,0x5f,0xbc,0x78,0x65,0x49,0x55,0x30,0x58,0x9b,0x9a,0x87,0x91,0x81,0xf1, + 0x60,0x93,0x43,0x3a,0x74,0xae,0xf4,0x7e,0xa2,0xef,0xf,0x44,0x11,0xa2,0x2d,0xde, + 0xcb,0xa1,0xbb,0xcd,0x33,0xe8,0x18,0xc0,0xa2,0xd6,0xb9,0x76,0x2b,0x30,0xe5,0x6d, + 0x38,0x6c,0x2a,0xca,0x23,0x32,0x57,0x80,0x14,0xe8,0x39,0xe6,0xeb,0xbc,0xf2,0xed, + 0xf5,0x3e,0x26,0xde,0x8,0xea,0x7d,0xbe,0x70,0x65,0x31,0x2f,0xf2,0x5d,0xd8,0xa5, + 0xd3,0xc2,0x99,0xd7,0x7d,0xc,0x78,0x24,0xc6,0x67,0x1a,0x20,0x5,0x3,0x26,0x36, + 0xe5,0x2c,0x87,0xca,0xf7,0x59,0x1c,0xda,0xa2,0x24,0xb2,0x91,0xbf,0x3b,0xcc,0x7e, + 0xf8,0xda,0xa5,0xfd,0xda,0xc3,0x6c,0x7a,0xac,0x41,0x17,0x31,0xab,0xc1,0x1a,0xf2, + 0xe4,0x96,0xcc,0xfb,0x20,0x59,0x88,0x4e,0x58,0xb,0x20,0xa0,0x23,0x63,0xa,0x3c, + 0x5e,0x8b,0x91,0xf7,0xb7,0x31,0x92,0xdf,0xe7,0x6c,0x88,0x20,0x23,0xc6,0xdd,0xd7, + 0xd1,0xc5,0x85,0xae,0xa5,0xc2,0x6b,0x2c,0xa2,0xf4,0x23,0xab,0x42,0x25,0xa5,0xd9, + 0xc,0x7,0x16,0x9d,0x3a,0x33,0x85,0x98,0xa9,0xc3,0x91,0xe5,0x43,0xac,0x50,0x3d, + 0x67,0x89,0x5e,0x18,0xcf,0x13,0x66,0x15,0xe0,0x40,0xd3,0x4a,0x74,0x5b,0x28,0xe6, + 0x18,0x60,0x27,0x45,0x6f,0x3b,0xcc,0x38,0x10,0x2a,0x46,0x51,0x9d,0xa2,0xa4,0xfa, + 0x47,0x57,0x2e,0xac,0x6f,0xbf,0x70,0x75,0x79,0xf3,0xda,0x85,0x55,0xe7,0xa6,0x9c, + 0x91,0x14,0xa9,0x96,0x95,0x49,0x17,0xc0,0x71,0x36,0xc9,0x46,0x7e,0x36,0xdc,0x7d, + 0x54,0xed,0x22,0xee,0xc1,0x1,0xb2,0xd8,0xd4,0xdd,0x6c,0x82,0x5a,0x41,0xac,0x64, + 0xe0,0x21,0x73,0x72,0xd9,0x1,0x9e,0xb2,0xa5,0x3c,0xbb,0x89,0x33,0x36,0xcc,0xbc, + 0x9d,0xd3,0xf4,0xd7,0xa7,0x0,0xb,0x71,0xe1,0xb2,0x89,0x21,0x8e,0x0,0x8d,0xfc, + 0x0,0xbb,0xc0,0x42,0xfb,0xce,0x14,0x49,0x3f,0x5d,0x4e,0x9e,0x5a,0x89,0x8,0x9d, + 0x88,0xcc,0x14,0x98,0x5f,0x7f,0x67,0x3e,0x84,0xee,0x88,0x80,0xbc,0xa8,0xbe,0x97, + 0x99,0xa2,0x1f,0x60,0x6,0x48,0x2b,0x32,0xb7,0x26,0xa5,0xc7,0x12,0xd1,0xc1,0x61, + 0xfe,0x68,0x1,0x8b,0x10,0xdd,0xb8,0xf8,0xf7,0xde,0x7e,0xfe,0xca,0xf2,0xa3,0x2b, + 0x7b,0x92,0xc2,0xb3,0x2d,0x41,0x3b,0x37,0xe2,0x2b,0xaf,0x4b,0x82,0x3e,0x23,0x34, + 0x68,0x70,0x0,0x1,0x6c,0x98,0x54,0x1c,0xe0,0x79,0x6f,0xc0,0x2c,0x4e,0xd6,0x61, + 0x28,0x30,0xf5,0xfd,0xeb,0x75,0xfc,0xe8,0xea,0xa5,0x15,0xe6,0xf6,0xb6,0xf3,0x57, + 0x16,0x5e,0x42,0x3f,0xba,0x7a,0x71,0xd5,0x8a,0xc9,0xa6,0xee,0x62,0x16,0x40,0x40, + 0x1e,0xf0,0xaf,0x16,0x6a,0x1f,0xf,0x2,0x48,0xbd,0xf2,0x4f,0xa1,0xcf,0x7b,0x57, + 0xc6,0xa6,0x58,0x1c,0x5,0xd5,0xf1,0xb9,0xf6,0xf6,0xf3,0x57,0x96,0x1f,0x5d,0xbd, + 0xb4,0xc6,0x13,0x23,0x34,0x27,0xec,0xed,0x17,0x5e,0x5b,0x7e,0x74,0xf5,0xe2,0xa, + 0xaa,0xe4,0x18,0x9,0xe2,0xae,0x23,0x42,0x3f,0x58,0x41,0x91,0x10,0x56,0x57,0xbc, + 0xf0,0x9,0xcc,0xca,0xa9,0x76,0xc4,0xb4,0xb,0x30,0x1c,0xb6,0x4c,0x24,0x45,0x59, + 0x30,0xeb,0xcd,0x6b,0x97,0xd6,0xb7,0x9f,0x1f,0x95,0xe2,0xb8,0xe6,0xac,0x87,0xe, + 0x4e,0xe6,0x26,0xe4,0xa0,0xce,0x36,0x60,0x1a,0x18,0x72,0xa7,0x91,0x3,0xb5,0xf9, + 0x1,0x44,0xbd,0x88,0x5a,0x99,0xbd,0x79,0x75,0x5c,0xa7,0xa3,0x10,0x16,0xc0,0xec, + 0x47,0xd7,0x2e,0xad,0xf0,0x3,0x41,0xcc,0x14,0x6b,0x84,0x7a,0xe,0x7b,0x90,0x6d, + 0x66,0xe9,0xe5,0x99,0xca,0x20,0xb7,0xe6,0x3c,0x22,0x76,0xa0,0xf8,0x91,0x34,0xc2, + 0x7,0xc4,0x83,0xac,0x8f,0xe5,0x5c,0x41,0xc0,0x8c,0xd9,0x19,0x5d,0x1,0x4d,0xa0, + 0x98,0x21,0x16,0x75,0xf2,0x59,0x2a,0x3d,0x6,0x43,0x4,0x51,0xb0,0x37,0xaf,0xde, + 0xb3,0xbe,0xfd,0xfc,0xab,0xcb,0x49,0x93,0x79,0x59,0x70,0x80,0xe1,0x94,0x37,0xa0, + 0x60,0xdf,0x7e,0xee,0xea,0xf2,0xe6,0xd5,0xb,0x5d,0x73,0xfd,0xcd,0x6b,0x17,0xd6, + 0xb7,0x9d,0x6f,0xbc,0xc4,0x3,0x6d,0x2f,0xe1,0x1b,0xc,0x2a,0x91,0x45,0x75,0xb9, + 0xd8,0xf6,0x94,0x56,0x91,0x4f,0x1e,0xef,0x8,0xba,0xc5,0x43,0xdb,0xc8,0x43,0x7b, + 0x53,0xd4,0xb1,0xe6,0x15,0x95,0xae,0x90,0xec,0xf3,0x3b,0xde,0x2a,0xf0,0x2e,0xeb, + 0x77,0xcb,0xe8,0x54,0x1d,0x3d,0xc4,0xcf,0x7d,0xf3,0xea,0xc5,0xf5,0xf0,0xd4,0x30, + 0xb7,0xd8,0x74,0x8d,0x5,0x15,0xb7,0xd0,0x82,0x99,0xa0,0xdc,0x94,0xfd,0xc6,0x6d, + 0x7c,0xd7,0x54,0x62,0xa,0xce,0x45,0xee,0x21,0xd,0x1a,0x8b,0xcb,0xc1,0xf0,0xe6, + 0x55,0x6a,0x15,0x62,0xd2,0x6d,0xc4,0x7e,0x0,0xbd,0xed,0xec,0x6b,0xcb,0x8f,0xaf, + 0x5f,0x5c,0xdf,0x76,0xf6,0xca,0xf2,0xe6,0xb5,0xfa,0x3b,0x82,0x9c,0x2a,0xb4,0x2e, + 0x47,0x36,0xfa,0xe6,0xd5,0xa,0x3e,0x9,0x46,0x31,0x62,0x74,0xe3,0x8,0xf4,0x3a, + 0xb,0xcf,0x2c,0xb0,0x11,0x8,0x18,0x98,0xc0,0x86,0x5b,0x98,0x8a,0x90,0x3e,0xb8, + 0x78,0xbe,0x13,0xa0,0x51,0xb,0x62,0x17,0xf7,0x25,0x8f,0xb3,0xdf,0xd0,0x99,0x18, + 0xa3,0x96,0x3c,0x9b,0x25,0x6c,0x7c,0x70,0x83,0xe2,0x51,0x4d,0x6c,0xf7,0xc7,0x46, + 0x3d,0x8d,0x93,0x10,0xaa,0x73,0x2a,0x27,0x7f,0x7c,0xed,0xd2,0xea,0x14,0x0,0x15, + 0x46,0x49,0x2d,0xfa,0x2d,0x7,0x11,0xfe,0xe8,0x37,0xaf,0x5d,0xc,0x20,0x27,0xa7, + 0x71,0xc6,0xa8,0x1e,0x7d,0x8e,0xab,0x56,0x6c,0x32,0xc6,0x68,0x8,0x4e,0x26,0x29, + 0xa1,0x3f,0xc8,0xc9,0xc3,0x8f,0xaf,0xd5,0x40,0xde,0xc6,0x50,0x50,0x20,0x6d,0x6f, + 0xb3,0x6e,0xa1,0x73,0x21,0xd5,0xf5,0xe8,0x66,0x20,0xac,0x85,0x69,0xe4,0x71,0xb5, + 0xe9,0xdc,0x2f,0xa5,0x8c,0x44,0x3d,0x60,0x62,0x3a,0xef,0xda,0xd4,0xe7,0xba,0xaf, + 0x6d,0xca,0xbe,0xe,0x51,0xd8,0xde,0x7c,0xfd,0x92,0x88,0x7,0xf1,0x7b,0x76,0x84, + 0xba,0x0,0x5e,0x4d,0x30,0x3b,0xfd,0x1e,0x8b,0xc2,0x5d,0x3b,0x57,0xc6,0x5a,0xfd, + 0x71,0xfd,0x9c,0x8c,0x88,0x67,0x8c,0x5,0xa4,0x2b,0x23,0xc0,0xb9,0xcd,0x12,0xda, + 0x5c,0x4d,0xc0,0xdc,0xa6,0xf8,0x74,0x2,0xe8,0x1a,0xb5,0xc5,0x3d,0x74,0x26,0x61, + 0x2e,0x58,0x1b,0x5,0xb5,0xb8,0x30,0x80,0x83,0x60,0x4,0xbd,0x34,0x80,0xe8,0x48, + 0x85,0x93,0xd0,0x51,0x69,0x7e,0x9e,0xca,0x52,0x64,0x4e,0x8f,0x30,0xc5,0x48,0x77, + 0xe0,0xcd,0xd7,0x2f,0xad,0x60,0xaa,0xb1,0x4d,0xa7,0x51,0x19,0x8f,0xb3,0xd9,0x4e, + 0x5b,0x3,0x21,0x22,0x9d,0xfc,0xbb,0xa7,0x5e,0xd8,0x52,0x55,0x32,0xcc,0x16,0xf6, + 0xe3,0x6b,0x17,0x57,0x99,0xf5,0xf6,0x3d,0x31,0xb4,0xad,0xdd,0xe3,0x9a,0xaf,0xe0, + 0x5,0xa9,0xa6,0x7c,0x72,0xa2,0x86,0x4a,0x4b,0x10,0x83,0xe8,0x92,0xb3,0x9e,0x7, + 0x54,0x69,0x7e,0x9c,0x79,0xe2,0x8,0x15,0xa,0xa6,0x1,0x48,0x79,0xb7,0x20,0xb4, + 0xe3,0x8,0xd6,0xbf,0x70,0xf6,0xea,0xf2,0xe3,0xd7,0x2f,0xae,0xb1,0x32,0x72,0xca, + 0x2c,0x62,0x65,0x9,0xb,0x5c,0x54,0x53,0xf5,0x27,0x6,0x3a,0x39,0x22,0x62,0xa5, + 0xd4,0x77,0x1f,0x20,0xd,0xe7,0x43,0x97,0x50,0xf2,0x31,0x51,0xe7,0x83,0x1b,0x29, + 0x87,0x19,0x46,0x18,0xce,0x20,0xc4,0x3e,0x6b,0xe2,0xc,0x36,0x1c,0xce,0x50,0x99, + 0xc9,0xe,0x1c,0x8c,0x33,0xec,0xd0,0xa1,0xe0,0xb5,0x1,0x84,0xa0,0x90,0x30,0xf, + 0x71,0xa1,0x43,0xc1,0x5b,0x72,0xd,0x16,0x18,0xde,0x23,0x3b,0xfe,0x85,0xa3,0xd7, + 0x96,0x1f,0xdf,0xb8,0xb8,0x72,0x75,0x34,0xf0,0x23,0x3e,0xa9,0xe8,0xc7,0x7b,0xfd, + 0xc5,0xf5,0x4b,0xeb,0xcf,0x1f,0xbd,0xb6,0xfc,0xe4,0xc6,0xa5,0x35,0xcf,0xe9,0xb4, + 0xbf,0x12,0x84,0x5,0xc6,0xa7,0x41,0xf9,0xca,0x3d,0xcc,0x52,0x90,0x6a,0xbf,0xf3, + 0x17,0xd7,0xe9,0x0,0xe5,0xa0,0xda,0xf6,0x80,0xb0,0xd9,0x15,0x5c,0x38,0xe6,0x97, + 0x3c,0x62,0xd7,0x2e,0xc6,0x8f,0x6f,0xd4,0xca,0x88,0x5e,0x6b,0x81,0xc9,0xc1,0x4e, + 0x69,0x2e,0xaa,0x63,0x8,0x28,0x76,0xed,0xec,0x21,0x8e,0x3e,0xa8,0xb2,0x36,0x55, + 0x46,0x1d,0x18,0xe,0x5a,0xb3,0x82,0xdb,0x12,0x7c,0x58,0xb1,0x24,0xb3,0x1b,0xab, + 0xab,0x6,0xda,0xec,0x46,0x3a,0x54,0xbd,0x3,0xa4,0xcb,0x1f,0x3a,0x68,0x4e,0xf4, + 0x40,0x58,0x62,0x49,0xb4,0xc3,0xf6,0xe7,0xcf,0xbc,0xb6,0xfc,0xc5,0xf5,0x4b,0x1d, + 0x8,0xc,0x3e,0x71,0x31,0xeb,0x38,0xb8,0x24,0xfa,0x5c,0x40,0x38,0x89,0x9e,0xfc, + 0xf8,0xc6,0xa5,0x15,0x74,0xf3,0x5b,0x1b,0xbf,0x3,0x61,0xfb,0xb9,0x6a,0xa3,0x8b, + 0x20,0x81,0x3f,0xa3,0xbb,0xdb,0x99,0xc0,0x50,0x7e,0x74,0x1c,0xd,0x3a,0x32,0x1b, + 0x10,0xca,0x85,0x98,0x56,0xb9,0xf9,0x81,0x26,0x30,0x44,0x3b,0x41,0x7c,0xe7,0x15, + 0xe7,0x9e,0x31,0x49,0x53,0x79,0x7f,0x4c,0xda,0xcd,0x9e,0xd0,0xf4,0x48,0x7e,0xf5, + 0xfe,0x16,0xd8,0x8d,0x6c,0x5b,0x9b,0x19,0x8,0x36,0x5a,0xf7,0xb1,0x5b,0x89,0xd8, + 0xfd,0x9c,0x38,0xa1,0x5,0x7e,0xcd,0x60,0x6b,0xe5,0xb1,0x67,0xea,0xec,0xb6,0xf6, + 0xbf,0xe7,0xee,0x67,0x1c,0xf,0x85,0x4a,0xcc,0xdc,0x2b,0x6d,0xcd,0xcc,0xec,0x2f, + 0x6e,0x5c,0x5c,0x7f,0xfe,0xcc,0x95,0xe5,0x27,0xb7,0x2e,0xae,0x8c,0x96,0xe4,0xf6, + 0x5c,0x9c,0xaf,0xf5,0xd,0x5,0xed,0xa5,0x71,0xd2,0xeb,0xe,0x51,0xc8,0x61,0xac, + 0x4e,0x3b,0xb4,0xe2,0x40,0xa9,0x7,0x23,0x2,0xa7,0xa5,0x80,0xef,0x83,0x36,0xe5, + 0x98,0x88,0xa2,0x20,0x42,0xf4,0x83,0xfe,0xae,0xc1,0x7e,0x72,0xe3,0xe2,0xea,0xb4, + 0x90,0x19,0xf1,0xc8,0xc0,0x23,0x37,0xad,0xd0,0xc7,0x5b,0x8e,0xa0,0xa1,0xc8,0xe7, + 0x76,0x4f,0x2f,0xad,0xdc,0x72,0x6b,0x3f,0xff,0xc9,0x8d,0x8b,0xab,0x4f,0xbb,0xc, + 0x44,0x7d,0x6b,0x4d,0x3a,0xca,0x54,0x95,0xda,0x17,0x2,0x23,0xe9,0x66,0x3b,0xa2, + 0x99,0x4e,0x4c,0xae,0x22,0x59,0x4d,0x5b,0xdc,0xde,0xab,0x98,0x31,0x34,0xf4,0x90, + 0xe0,0x81,0x10,0x34,0x1e,0xb3,0xda,0x8e,0xde,0x86,0x64,0x92,0x7c,0x10,0x8f,0xcd, + 0xbe,0xdf,0xb3,0x9f,0x3f,0x7d,0x65,0xf,0x8c,0x16,0x44,0x4d,0x66,0x15,0xf2,0xf6, + 0x16,0xe2,0x16,0x24,0xf8,0x21,0x88,0x5c,0xcb,0x74,0x25,0x5e,0xcf,0x51,0x2e,0x94, + 0x87,0xce,0xce,0xdc,0xda,0xd0,0xa9,0x10,0x5f,0xea,0x34,0x8e,0x99,0xf9,0xce,0x7, + 0x40,0x9f,0xd,0x73,0x86,0xc1,0x34,0xe0,0xea,0x9a,0xf,0xcb,0x11,0x90,0x98,0xa5, + 0x20,0x15,0x71,0x1c,0x41,0x61,0xf8,0x13,0x8c,0xbd,0xe9,0x2a,0x4d,0xc9,0x35,0x3b, + 0x8d,0x72,0xfb,0xed,0x73,0x48,0x87,0x6b,0x50,0x45,0x79,0x94,0x84,0xe0,0xff,0x3d, + 0x2a,0x3c,0xb8,0x4f,0xb8,0x4d,0xba,0x57,0x99,0x1e,0x86,0x28,0xa0,0x64,0x79,0xac, + 0x23,0x9d,0x16,0x2e,0x21,0x62,0x29,0xda,0xf1,0x10,0x9e,0xe6,0x77,0x48,0x4d,0x27, + 0x4c,0x7d,0xcc,0x53,0xab,0x1a,0x9e,0x71,0x43,0xa4,0x15,0x81,0xf4,0xf9,0xb9,0xc0, + 0x40,0x1c,0x61,0x61,0xd2,0x4e,0x8e,0xed,0x6f,0xb3,0xd4,0xf6,0xee,0xda,0x1f,0xd1, + 0x89,0x0,0xd4,0xb2,0x2d,0x3,0x30,0x8b,0x8,0xce,0x44,0x2e,0x9c,0x80,0x3,0x1, + 0xd0,0x73,0xa2,0x18,0x6f,0x22,0x3c,0xec,0xd1,0xc9,0xc,0xbd,0xfd,0xed,0x27,0x37, + 0xef,0x59,0xa3,0x34,0xf5,0x74,0x32,0x18,0xc1,0x77,0xc6,0x4e,0x8c,0x3e,0xe9,0xc7, + 0x2b,0x18,0x50,0xf5,0x40,0x5c,0x5b,0xe7,0x12,0x4b,0x2c,0x77,0xcc,0x30,0xab,0xc2, + 0x3c,0x77,0x75,0xa9,0x43,0x25,0x9a,0x27,0x50,0x30,0x22,0x42,0x17,0x73,0xb0,0x2d, + 0x5c,0x98,0x66,0x71,0x5c,0x65,0xd1,0xe4,0x6c,0x64,0x9d,0x72,0x3e,0x9e,0x14,0x81, + 0x12,0xae,0x94,0x10,0x17,0xa0,0x4f,0x39,0x73,0xd1,0x19,0xcc,0xd8,0xa2,0x13,0x16, + 0x9b,0x73,0xfd,0x26,0xba,0xf0,0xdc,0x3d,0xcd,0xc1,0x8d,0x2b,0x3c,0x6,0x5b,0x14, + 0x45,0xeb,0xc6,0x7e,0x8f,0x8e,0xb,0x3d,0x65,0xd6,0x96,0x2,0x53,0x6c,0x5e,0x47, + 0xec,0x7d,0xf6,0xbc,0xed,0x47,0x28,0xcf,0xb6,0xa6,0xa,0x73,0xa1,0x45,0x68,0x99, + 0xbf,0xbb,0xb7,0x6f,0xe8,0x61,0x4f,0xe,0x2d,0x17,0x5e,0xa4,0x27,0xbd,0xf1,0xd8, + 0x61,0x69,0x3c,0x6a,0xf,0xd3,0x8f,0x8,0xbb,0xc4,0x81,0x8c,0x55,0xe,0x7f,0xf, + 0x89,0xda,0xa4,0xc2,0x89,0x6a,0x4a,0xb1,0x8d,0x9f,0xfc,0xb1,0x1d,0x59,0x9,0x6d, + 0x32,0x99,0x31,0x6a,0xe5,0xb7,0x7b,0xfc,0xcf,0x4f,0xbd,0xb6,0xfc,0xe4,0xd6,0xa5, + 0xb5,0x3,0x4,0x5b,0x87,0x64,0x82,0x83,0xc8,0x15,0xac,0x1a,0xca,0x6a,0x7,0xc5, + 0xfa,0x33,0x1d,0xd5,0x33,0x37,0x72,0x7d,0xaa,0xfc,0x97,0xd1,0xba,0x79,0xa3,0x7, + 0xa1,0xc9,0x61,0x62,0xa4,0xcd,0x28,0x85,0x85,0xf5,0xaf,0xa5,0xa2,0xa1,0xd3,0xf1, + 0x81,0xbb,0x50,0xc1,0xa4,0xb1,0xee,0x8a,0xc6,0x49,0xd5,0xbd,0x71,0x7,0x48,0x2b, + 0xb1,0xbe,0xfa,0xa0,0x58,0x82,0x91,0xe6,0x68,0xdb,0x37,0xa1,0xe2,0x31,0xb8,0xd3, + 0x9e,0x12,0x11,0xde,0x49,0x66,0x56,0xd8,0xc7,0xc0,0x6c,0xcc,0xce,0x26,0xb3,0xf, + 0x4c,0xc6,0x69,0xe9,0x75,0xe1,0xbe,0xc7,0x99,0xba,0xc2,0x69,0x12,0xb,0x23,0x63, + 0x33,0xf4,0x70,0x89,0xb3,0xcf,0x4,0x1d,0x10,0xb9,0x43,0x8d,0x59,0x88,0x80,0x88, + 0x9,0xf2,0x1d,0x9e,0x13,0xfd,0xd6,0x35,0xd0,0xb9,0x1f,0xb5,0xef,0x13,0x9e,0xc5, + 0xd4,0x93,0xc1,0xf1,0x16,0x62,0x5d,0x2e,0xe3,0x13,0xcd,0xce,0xa5,0xe7,0x3e,0x19, + 0xc,0x22,0xb5,0x72,0x5a,0x6e,0x4a,0x71,0x85,0xb3,0x7e,0xe7,0x80,0xec,0xdc,0x22, + 0x4,0x25,0xa8,0x3e,0x19,0xf3,0x51,0x4c,0xf1,0x48,0x4f,0x89,0xf,0x30,0x56,0xe8, + 0x30,0xed,0x86,0x86,0x39,0xb7,0xb4,0xd5,0x7d,0x28,0x10,0xee,0xd2,0xcc,0xa1,0x7, + 0x0,0x1d,0x3d,0x25,0xcc,0x54,0x33,0x19,0x8a,0xb8,0x1d,0xe4,0x98,0x6a,0xe6,0xf6, + 0xcf,0xee,0x7e,0x75,0xf9,0xf,0xb7,0xef,0x5d,0xfb,0x68,0x2e,0x26,0x9e,0x50,0xd5, + 0x80,0x2c,0xb2,0xd6,0x2a,0x74,0xda,0xa4,0xa2,0x31,0x2e,0x99,0xd9,0x98,0x2d,0x39, + 0x57,0xe8,0x71,0x1e,0xc0,0x80,0xf,0x4,0x7,0xb5,0x9e,0xd,0x71,0x6d,0xe1,0xc9, + 0xe2,0x12,0xac,0x2f,0xdd,0xe7,0x8,0xd0,0xf5,0x12,0x1b,0xa8,0x88,0x89,0xc8,0xa8, + 0x84,0xc6,0x3a,0x41,0xa2,0x13,0xf8,0xc,0xf8,0x67,0x98,0x68,0x30,0xef,0xb,0xec, + 0x3f,0x1c,0x5f,0x5a,0x59,0xb6,0x92,0xf,0x94,0xbf,0x3c,0xbe,0x67,0xfd,0x67,0xef, + 0x7c,0x75,0x68,0x3d,0x3,0x39,0x99,0xe1,0x6a,0x2d,0x8a,0x78,0x84,0x43,0xb0,0xcd, + 0xb0,0xc0,0xe3,0xc6,0x99,0xb9,0x7,0xcf,0x66,0xc8,0x89,0xce,0xa8,0x75,0xd9,0x8f, + 0x6a,0x4e,0x70,0xfa,0xbe,0xf5,0x84,0xc,0x66,0xe0,0x4d,0x97,0x2f,0x45,0x44,0x34, + 0xd1,0xb5,0x45,0x3,0x18,0x1,0x44,0xba,0x1c,0x4e,0xa3,0x2,0x1f,0xf7,0xf9,0x2f, + 0x6f,0xf3,0x2c,0x6e,0x54,0xc4,0x31,0x1e,0xa9,0xbe,0xbe,0xa7,0x7a,0xc6,0x15,0x71, + 0x15,0x78,0xc8,0xae,0x32,0x9f,0xa6,0x3c,0x6b,0xd,0x45,0x50,0x74,0x6b,0xe8,0xd0, + 0x38,0xa2,0xaa,0xe2,0x44,0xdf,0xbf,0x85,0xe7,0x92,0xe2,0xa2,0xb6,0xe4,0xa2,0x77, + 0xba,0x22,0xf3,0x11,0x2b,0x67,0x6a,0xb2,0x9a,0xa8,0x2a,0xa5,0x8a,0x50,0x79,0xf7, + 0x87,0x2a,0xc4,0x69,0xf5,0xc8,0x33,0xe3,0x19,0x90,0x2a,0x8c,0xbc,0x84,0x2b,0x9f, + 0xe6,0xc8,0xa,0x86,0x12,0xa,0xa5,0x97,0x4,0xf0,0xc9,0xc,0x87,0x1c,0x33,0xcc, + 0xa6,0x8,0xa9,0xc9,0x78,0x2e,0x8f,0x3f,0x61,0x93,0x2a,0xcc,0xa9,0xe3,0xc4,0xca, + 0x91,0x1e,0xd8,0x9,0xdc,0xde,0x8c,0x3c,0x6b,0xb,0xb8,0xa3,0x28,0x1f,0xa,0x11, + 0x91,0xd5,0xbd,0x15,0x3,0x68,0x7,0x2e,0x46,0xed,0x56,0x93,0xa,0x13,0xc6,0xdd, + 0x49,0x1e,0x5d,0x68,0x72,0x36,0x89,0xf0,0x69,0xcf,0x38,0x41,0x51,0x9d,0x85,0x8a, + 0xb2,0xb4,0x61,0x86,0x3c,0xf1,0xa4,0xd4,0x54,0xe5,0x8d,0xbd,0x8,0x68,0xbc,0x87, + 0x6e,0x51,0x2c,0x38,0xd6,0xfd,0xb,0xa,0x50,0x16,0x33,0x28,0x90,0x8a,0x7,0x65, + 0x45,0xbe,0xac,0x4c,0x39,0xeb,0x38,0xc4,0x24,0xd5,0x2d,0xe3,0x8d,0xc,0x39,0x1, + 0xb6,0x90,0x14,0xdb,0xe4,0x73,0x18,0xa3,0x90,0x96,0x2f,0x7d,0x77,0x8d,0xb9,0x3, + 0x40,0xae,0x48,0x97,0x9,0x8,0x96,0x63,0x2c,0x57,0xe8,0x9c,0xf0,0xbb,0x9b,0xfd, + 0xd3,0xbb,0x5e,0x5b,0xfe,0xea,0xe,0x81,0x2a,0x5c,0x11,0xc9,0x8c,0xc0,0x44,0xe8, + 0x30,0x4a,0xa6,0xe2,0xb9,0xcd,0x31,0xc0,0x2c,0x9c,0x26,0xc7,0x6a,0x42,0x37,0xab, + 0xa7,0x99,0xc4,0x1c,0x95,0xee,0xce,0x52,0x92,0xa3,0xe2,0x9d,0x81,0x8,0xd0,0xab, + 0x9a,0x7c,0xba,0x8d,0xec,0x90,0x84,0x6a,0x68,0x26,0xc5,0xf,0xa,0x22,0xe6,0xe2, + 0x59,0x31,0xcf,0x46,0x4b,0xc7,0xa1,0x47,0xf4,0x44,0x99,0x36,0x67,0x6f,0x98,0xb4, + 0xc0,0x82,0xa3,0x9a,0x3e,0x6b,0xf,0xc1,0x22,0xda,0x79,0x5a,0x76,0xb,0x32,0x6d, + 0xe9,0xea,0xc8,0x22,0x58,0xb,0xfa,0xc4,0xbe,0xc,0x93,0x60,0x68,0x3a,0x36,0xf4, + 0x82,0xc0,0xd8,0x82,0xce,0x4c,0x6d,0x62,0x7e,0x10,0xda,0xd5,0xea,0x70,0x86,0x8, + 0xc5,0x9d,0xb6,0x50,0xed,0x40,0x67,0x22,0x66,0xee,0x7,0x49,0x14,0x98,0x73,0x8f, + 0xc1,0xa,0x86,0x99,0xcf,0xb,0x6d,0x23,0xe5,0x6a,0x20,0xd,0xef,0x30,0x14,0xdd, + 0xc4,0xa1,0x2c,0x82,0xa1,0x2c,0xb0,0x95,0x1c,0x5a,0x92,0x1e,0x24,0x3d,0x20,0x8c, + 0xa9,0xe6,0xc1,0x50,0x71,0x14,0x34,0x63,0x95,0x4e,0xc9,0x18,0x4d,0xa8,0xc,0xdb, + 0x84,0x19,0x30,0x7a,0xf6,0x84,0xd0,0xa2,0xd4,0xe,0x6e,0x6f,0x8d,0xc0,0x1c,0xe7, + 0xc7,0xf0,0x20,0x30,0x5,0x0,0x76,0x65,0x9e,0xc9,0x93,0x4c,0xdc,0x6d,0xf,0x87, + 0x2c,0x28,0x90,0x8c,0x4,0x69,0xce,0x26,0xd0,0x64,0x91,0xfd,0xbe,0x5d,0x88,0x22, + 0x48,0x78,0x60,0xcf,0x78,0xc7,0xf1,0x5d,0x64,0xc,0x90,0xb8,0x35,0x4,0xb2,0x74, + 0xa5,0xeb,0xc1,0xd4,0x31,0x51,0xaa,0x3a,0x25,0x93,0x47,0x97,0x2,0xd1,0xcc,0x8f, + 0x0,0x5c,0xae,0x26,0x29,0x68,0xee,0x94,0xad,0x19,0x23,0xa7,0x8c,0x74,0x94,0x46, + 0x17,0x33,0xdd,0x7b,0xe3,0x2,0xed,0xc0,0xb3,0x46,0x30,0xdd,0x9c,0x28,0xd2,0x79, + 0x62,0xb0,0x8,0x8b,0x22,0x4,0x42,0x98,0xfd,0xd5,0xf,0xee,0x5d,0x99,0xaf,0xf, + 0x8b,0xf8,0x6a,0xc8,0x28,0xb2,0xe1,0x15,0x86,0x6,0xfd,0x88,0x25,0x88,0xc0,0xd9, + 0xa9,0xc7,0xc4,0xe0,0xb4,0x9b,0x58,0x78,0xcb,0x0,0x37,0x39,0xab,0x19,0x69,0xa7, + 0xb8,0x1c,0xc1,0xaa,0x87,0xc2,0x20,0x6b,0x10,0x8,0xd7,0xbd,0xda,0x6f,0x35,0x23, + 0x85,0xc4,0x13,0xd5,0x31,0x8d,0xfd,0xef,0xdf,0xbf,0x67,0xfd,0x27,0xbf,0xfc,0xda, + 0xe2,0x89,0x77,0x39,0x40,0x14,0x3d,0x68,0x13,0xf7,0x31,0x81,0x7,0xc4,0x9c,0x3d, + 0x6a,0x30,0x92,0x13,0x13,0x5b,0x85,0xc2,0x83,0xf9,0x4,0xa4,0xa9,0x3c,0xa8,0xda, + 0x4e,0xbf,0x3,0xa,0x8a,0xc8,0x15,0x46,0x40,0x43,0x8,0xdf,0x12,0xea,0x8e,0xa4, + 0x3c,0x70,0xef,0x1b,0xd,0x65,0xb0,0x19,0x85,0x87,0xc8,0xd9,0x64,0x9,0xa8,0xe4, + 0x59,0xd0,0x11,0xda,0x77,0xb6,0xea,0x9b,0xb0,0x4e,0x32,0x97,0x77,0xda,0x97,0xe4, + 0x19,0x2e,0xe,0x44,0x2f,0x48,0xb0,0x87,0xcd,0xfc,0x58,0xb,0x7d,0x56,0x70,0xd2, + 0x8a,0x96,0x42,0xa2,0xcb,0x8f,0x80,0xb4,0x1e,0xcf,0xb8,0xc0,0xe,0x88,0x6d,0x94, + 0xf4,0x75,0x8a,0x1d,0x72,0x79,0x6b,0x37,0xcf,0xd4,0xf6,0x75,0xf2,0x45,0x67,0x5a, + 0xd4,0x52,0x5d,0x41,0x1d,0xde,0xe2,0xfa,0x18,0xfc,0x50,0x74,0x41,0x80,0xba,0x5f, + 0x50,0xe7,0x84,0xe3,0x48,0x5,0x72,0xe2,0x3,0xd7,0xca,0x19,0x48,0x9a,0x6,0xe9, + 0xbe,0x52,0x20,0x6,0x3,0xdb,0xfa,0x65,0x3a,0x31,0x59,0xc4,0x9a,0xb0,0x9e,0xf3, + 0x98,0xcc,0x17,0x99,0xbf,0xae,0x3f,0x43,0x40,0xd1,0xef,0x7b,0x28,0x63,0x5d,0x5c, + 0x78,0xcc,0xe9,0xfe,0x54,0xd,0xb,0xa8,0xb5,0xb2,0x13,0x86,0x46,0xfc,0x6a,0x67, + 0x2e,0x74,0x8,0x2d,0xce,0x3,0x9d,0x6,0x68,0xe0,0x42,0x40,0xf6,0xf3,0x5e,0xd6, + 0xb6,0x7b,0x3e,0x3d,0x10,0xdd,0x1b,0xa5,0xdb,0xc1,0xe,0x64,0xc4,0x90,0x30,0xd6, + 0x45,0x9f,0xd3,0xab,0xf4,0xca,0x4b,0x77,0xda,0x32,0xa0,0xfe,0x1a,0xd2,0x24,0x81, + 0x41,0x95,0x60,0xab,0x66,0x4c,0x72,0x35,0xc4,0x62,0x0,0x66,0x56,0xfa,0x49,0xe8, + 0x7c,0x7b,0xb8,0xab,0x8a,0x5c,0xfd,0x49,0xce,0xc,0x8,0x48,0xaf,0xaf,0xc,0x3a, + 0x4b,0xa2,0x3b,0x63,0xbb,0x93,0xac,0xf8,0x38,0x53,0x1e,0x35,0x2,0xe2,0xf1,0x5a, + 0x72,0x3a,0x3f,0xd0,0x99,0xc,0xa3,0xa3,0xe8,0xbb,0xbb,0x49,0x5b,0xf5,0x0,0x8d, + 0xf0,0x50,0x5d,0xb,0xdb,0xb3,0x6,0xd9,0xd2,0x4a,0xf7,0x9,0x11,0x1f,0xe6,0x51, + 0xd2,0x41,0xf0,0x5b,0x6d,0x4e,0xef,0xa8,0x78,0xa9,0xce,0xbb,0x27,0x3,0x26,0xd6, + 0x17,0xa9,0x1d,0x16,0x88,0x15,0xee,0x70,0x15,0x45,0x70,0x20,0x64,0x4d,0x17,0x56, + 0xb5,0xec,0x7c,0xf8,0x96,0x88,0x62,0x10,0x77,0x4c,0x8e,0x89,0xa1,0xa0,0x59,0x8c, + 0x84,0x3,0xa2,0x7f,0x32,0x7,0xd8,0x96,0xc1,0xca,0xcc,0x16,0xd9,0xbf,0x1c,0x71, + 0x76,0x23,0xc4,0x9b,0xec,0xe5,0x9d,0x2d,0x3e,0x4d,0x2b,0xc9,0x4,0xd6,0x50,0x61, + 0x84,0x14,0x48,0xc2,0xa2,0x44,0x56,0x86,0xd6,0x52,0x6e,0x76,0xf0,0x5a,0x44,0xc9, + 0xc6,0x58,0x58,0x28,0x9b,0x53,0x14,0xbc,0xfb,0xa4,0x4a,0x12,0xfe,0x20,0xe6,0xad, + 0x59,0xa7,0xc3,0x55,0xcf,0xe5,0xac,0x42,0x31,0xf3,0x65,0xa4,0x83,0x33,0x1b,0x81, + 0x23,0x97,0x9,0xe1,0x4c,0xb5,0xb0,0x31,0x27,0x42,0xdb,0xa1,0x1a,0x1a,0x41,0x2a, + 0x2a,0xd1,0x8d,0x9e,0x3d,0x42,0xcf,0x18,0x61,0x8a,0xad,0x81,0x7f,0x7c,0x77,0xf, + 0xea,0x53,0x3,0x48,0xe6,0x11,0x18,0x20,0xde,0xc7,0xc1,0xae,0x14,0x13,0xd,0xe9, + 0xa0,0x14,0x18,0x3d,0x97,0x61,0x51,0xa4,0x64,0xa8,0xbf,0xb8,0x73,0xb5,0xb1,0x1f, + 0xcb,0x8c,0xbc,0x77,0x53,0x70,0x52,0xea,0xd,0xa3,0x0,0x65,0x3f,0x69,0x1c,0xfb, + 0x7f,0xf6,0x8c,0x10,0x70,0x94,0xfe,0xe7,0xf6,0xff,0xa8,0x3f,0x43,0x29,0x70,0x0, + 0x26,0x89,0x2a,0x7a,0xa0,0x73,0xd3,0x64,0xa6,0xe5,0x9e,0x1e,0xbd,0xed,0xad,0x24, + 0x4a,0x1e,0xb8,0x6a,0x86,0x1e,0x26,0x98,0xae,0xfd,0x91,0x24,0x5b,0x90,0xd2,0xf4, + 0xe0,0x84,0x7,0x84,0x1,0x0,0xb0,0x97,0x10,0x90,0x97,0xf4,0x45,0x2f,0x69,0x1e, + 0xf8,0xe4,0xeb,0x5f,0x5e,0x8c,0xa5,0xf7,0x1c,0xa1,0x74,0x5d,0x29,0x97,0x83,0xab, + 0x74,0x33,0x66,0xf3,0xfd,0x7e,0xfb,0x50,0x55,0x11,0xe3,0xe6,0x11,0x34,0xf7,0xbb, + 0x4e,0xdf,0x3,0x1e,0xf3,0xab,0x7a,0xbe,0xfc,0xf5,0x9b,0xf7,0xae,0xff,0xe3,0xdb, + 0x5e,0x59,0x46,0xf7,0xc8,0xf,0x27,0x4d,0xc9,0xf2,0x94,0x19,0x2d,0x2a,0x60,0xc2, + 0xf3,0x7e,0x40,0x3b,0x2b,0x29,0x93,0x7,0xdd,0xa6,0x1e,0x1c,0xf7,0xef,0x59,0xf1, + 0x25,0x30,0xb4,0x75,0xa,0x49,0xc4,0x78,0x7f,0x79,0x12,0xf8,0x2a,0x30,0x2b,0x35, + 0x36,0x17,0x78,0xa9,0x6b,0xd4,0x4a,0x5d,0x97,0x36,0x59,0xc7,0xfb,0x7a,0xf5,0xba, + 0x86,0xff,0xe3,0x8f,0xef,0xff,0xbb,0x7f,0xfc,0xb6,0x97,0x7f,0xe,0xa5,0xb4,0x3d, + 0x52,0xd7,0xf1,0xfe,0x7e,0xfb,0xcb,0xcb,0xfe,0x11,0x7d,0xdd,0x17,0x40,0xa8,0x8e, + 0x3,0xc4,0x39,0x1e,0x38,0x34,0x1d,0xab,0x9f,0xde,0x9f,0xbd,0x8f,0x89,0xb7,0x5b, + 0xd8,0x13,0x5d,0x7,0x60,0xa0,0xb4,0x11,0x97,0x9a,0xd,0xb1,0x27,0x30,0x3,0xc9, + 0xa3,0x8,0x4d,0xec,0x1e,0x8f,0xf3,0x44,0x4,0x67,0x2c,0x8,0xd7,0x84,0xf0,0xf0, + 0xd7,0x6f,0xde,0xb7,0xfe,0xe3,0xb7,0xbd,0xbc,0x30,0x5d,0x4f,0xca,0x39,0xd8,0x44, + 0x88,0x25,0xf8,0x15,0x50,0xc7,0xe1,0x24,0x7,0x85,0x6d,0x9b,0xfd,0x9e,0xfa,0x42, + 0xb6,0xd7,0x6c,0x9b,0x65,0x37,0x2,0xc2,0x4d,0x60,0x62,0xb2,0xa1,0xdd,0x5f,0xe4, + 0x4d,0x30,0x13,0x2d,0x8f,0xb3,0x34,0x72,0x5e,0x72,0x96,0xe1,0x89,0x1d,0xfe,0x24, + 0xd6,0xef,0x13,0x6d,0xc3,0x9,0xc5,0xad,0xb7,0x50,0x9c,0xe6,0x5b,0x36,0x93,0x65, + 0x4b,0x63,0x82,0x6d,0x9b,0x34,0x8d,0x93,0x2,0xa5,0x87,0x1a,0xc8,0x43,0xf5,0xa1, + 0x8d,0xb1,0xec,0xa6,0x6c,0x8a,0x56,0x80,0x25,0x4,0x7a,0x44,0xfb,0x8f,0x45,0x19, + 0xdf,0x9b,0x4,0x5b,0x70,0x80,0xfb,0x49,0xf4,0x31,0x83,0x8a,0x89,0x28,0x42,0x1e, + 0x61,0x36,0x68,0x9,0xb3,0xa0,0x9d,0x16,0x64,0x56,0x3,0x82,0xac,0xf,0xd4,0x30, + 0x73,0xdb,0x66,0x9d,0xd9,0xd0,0x26,0x2c,0xaa,0x3,0x2f,0xae,0xc4,0x9d,0xfa,0x47, + 0x6b,0x98,0x2b,0x4e,0x17,0x26,0x64,0xca,0x81,0xf4,0xf3,0xf7,0xb6,0xfa,0x5f,0xbf, + 0x79,0xef,0x4f,0xff,0x87,0x5f,0x78,0xe5,0xe7,0x36,0x46,0xcc,0x97,0x31,0xd8,0x93, + 0xf9,0x9f,0x33,0xa5,0x30,0xc3,0x2f,0x87,0x79,0x90,0x8a,0x46,0x74,0x50,0x60,0xd6, + 0x85,0x35,0xb8,0x7b,0x76,0x24,0xf3,0x5e,0xe1,0x98,0x3b,0x20,0xa5,0x88,0x25,0xcb, + 0x5c,0x90,0x77,0x2d,0xcf,0x25,0x79,0x62,0xdf,0x44,0x46,0xba,0x33,0x1a,0x14,0x44, + 0x5,0x8c,0xb3,0xc1,0x65,0xe,0x17,0x2c,0xd2,0xf6,0xd6,0x27,0x44,0xfe,0x3b,0x1c, + 0xb8,0xfd,0x6c,0x80,0x62,0x19,0xc6,0x88,0xc3,0x6d,0x26,0x5,0xca,0x89,0x85,0x98, + 0x75,0xf8,0xa0,0x2,0x8e,0x4a,0xf,0x23,0xfd,0xa,0xd4,0xcc,0x4d,0x5c,0x2,0xeb, + 0x53,0x71,0x42,0xf9,0xd7,0xcf,0xdc,0xb6,0xfd,0x9e,0x6c,0xac,0xdb,0xe1,0x61,0xe4, + 0x4,0xe5,0x8a,0x3a,0xb4,0xb1,0xee,0xdc,0x4a,0x87,0x5b,0x76,0x2e,0x23,0xef,0x5, + 0x24,0x8d,0x32,0xa2,0xc7,0x1f,0xf6,0xf7,0x8a,0x9d,0x3c,0x7,0x20,0x5b,0xde,0x90, + 0xc6,0x3,0xc,0x1e,0x4b,0x2a,0x8c,0x31,0xf9,0xb5,0xb9,0xca,0xdf,0x56,0xbb,0x1c, + 0x12,0x2b,0xa2,0x80,0x13,0x88,0x33,0xbe,0x83,0x23,0x61,0xa2,0x14,0x6a,0x6c,0xe, + 0xe1,0x3,0x63,0x53,0xec,0x90,0xf,0x40,0xd4,0x1e,0x44,0x57,0x6d,0xa,0x52,0x46, + 0x25,0xa1,0xcc,0x2,0xbf,0x3b,0x62,0x5b,0x26,0x67,0x31,0x8d,0x8d,0xb6,0x4d,0xe3, + 0xc3,0x5c,0x2,0xc3,0x13,0xe8,0x71,0xdb,0x66,0x60,0xda,0xf0,0x3b,0xb3,0xfe,0x94, + 0x83,0x30,0x0,0xfb,0xfb,0x9c,0x94,0x83,0xce,0x2d,0x36,0xdc,0xd2,0x40,0x4e,0xd5, + 0xba,0x78,0xae,0xe3,0x34,0xac,0x47,0xc0,0x19,0xe7,0xd8,0xe9,0x4,0x94,0x73,0x8f, + 0x8b,0x39,0x5c,0x43,0x3,0x7b,0xd1,0x67,0x31,0x58,0x8d,0xe7,0x6b,0x89,0x16,0x85, + 0x10,0x58,0x11,0x14,0xda,0x10,0x2a,0x2a,0xb8,0x74,0x25,0x54,0x18,0x60,0x32,0xfa, + 0x99,0xcc,0x7a,0x38,0x60,0x4a,0x5,0x83,0x19,0xaa,0x3c,0xda,0x5e,0xd8,0xbc,0x7d, + 0x2e,0x8c,0x8b,0x98,0xe9,0xe5,0xc5,0xe3,0xd3,0x31,0x22,0xb2,0xe,0x1e,0xe3,0x6, + 0x84,0x4a,0xa8,0xed,0x51,0xe,0xa0,0x3e,0x49,0x5a,0x5a,0xab,0xc8,0x79,0xb1,0xc2, + 0xb3,0x4f,0x92,0x63,0xe2,0xfd,0x10,0xe5,0x14,0x7d,0xac,0xa6,0xa4,0xbd,0x9f,0xc8, + 0x6c,0x63,0x25,0x60,0x30,0x5,0xd8,0xcd,0x6c,0xac,0x5b,0x8,0x50,0x4f,0xf2,0x49, + 0x8a,0x81,0x66,0xea,0x62,0xd5,0x3b,0xa,0x91,0xb9,0x52,0x0,0x9e,0x1d,0xef,0x15, + 0x87,0xb6,0x3,0x9c,0x93,0x43,0x12,0x41,0xd9,0x8f,0xd4,0x2,0xf5,0x37,0x20,0x7f, + 0x80,0x32,0x62,0x21,0x0,0xb3,0xad,0x1e,0xeb,0x6c,0x8b,0x5b,0xdb,0x64,0xe2,0x2c, + 0x56,0x54,0xa2,0xda,0x19,0x4b,0x2,0x3,0x63,0xf6,0x59,0x6b,0x60,0x80,0x17,0x33, + 0x75,0x8a,0xe7,0xea,0x3d,0x98,0x3b,0x57,0xf0,0xca,0x2,0x68,0xc5,0x2e,0x6f,0x7d, + 0x9e,0x9b,0x7a,0xc4,0x59,0xb4,0xdb,0x55,0xa0,0x23,0x8b,0x83,0xd3,0x21,0xe8,0x7c, + 0x5d,0xa3,0xb9,0x23,0x2,0x99,0xa0,0x6b,0x1d,0x91,0xc2,0x16,0x6d,0x8b,0xa3,0xf2, + 0xa1,0xa9,0x84,0x6c,0xf,0x41,0x5e,0x83,0xa3,0x13,0xa0,0xbb,0xc8,0xf6,0xcf,0x70, + 0xfa,0x19,0x46,0xa3,0xaf,0xe2,0x92,0x2d,0x36,0xb9,0x7f,0xe1,0xa1,0xc5,0xed,0x7e, + 0xe0,0x2e,0x69,0xba,0xbb,0xa7,0x74,0x90,0x84,0x24,0x25,0xf6,0x7e,0x60,0x9c,0xe1, + 0xd4,0xe6,0xec,0xc5,0x50,0xd1,0x8a,0x2d,0xd7,0x8e,0xe2,0xf7,0xd4,0x96,0xa9,0xcc, + 0x88,0x1d,0x66,0xb6,0xf9,0x48,0xa8,0x20,0x4c,0x2a,0x44,0xbc,0xe,0xed,0x17,0x78, + 0xe2,0x24,0xfb,0xd0,0x4c,0x98,0x14,0x61,0xe,0x16,0xaf,0xf0,0xdc,0xb1,0xe4,0xa3, + 0x1,0x22,0xd3,0x8,0x1a,0x7b,0xa9,0x10,0x42,0x3e,0x9f,0xa3,0x97,0xc1,0x4c,0xf8, + 0xd0,0x93,0xa3,0x11,0xa6,0x71,0x43,0x41,0x81,0x14,0x4f,0x3d,0xe5,0xf4,0xe3,0xfc, + 0xda,0x51,0xee,0xae,0x2e,0x6b,0x66,0x53,0xd5,0xaa,0x76,0x5f,0xff,0xe6,0x27,0xf7, + 0xae,0xff,0xfd,0x3f,0x7f,0x65,0x11,0x3f,0x60,0x98,0x54,0x1c,0x33,0x81,0x57,0x31, + 0x0,0x88,0xd5,0x17,0x6d,0x38,0x1,0x90,0x7,0x68,0xa0,0x80,0xb3,0xfa,0xef,0xb3, + 0xeb,0x8d,0x4f,0xb7,0x4e,0xac,0x75,0x95,0x26,0x13,0x90,0xd4,0xfc,0xde,0xce,0x82, + 0x1c,0xd0,0x2c,0x39,0x64,0x7b,0xe2,0x2e,0x56,0x37,0xb1,0x47,0xe,0x78,0x0,0x8a, + 0x20,0xd7,0x19,0x79,0xdc,0xe9,0x3a,0xc7,0x51,0x9e,0x37,0xf9,0x71,0x4,0x99,0xd0, + 0xee,0x6c,0xc6,0xb4,0x29,0x42,0x3d,0x75,0xd3,0x92,0xe0,0x52,0xe4,0x54,0x15,0x74, + 0x57,0xae,0x83,0xa6,0x34,0x1,0x9b,0x66,0x84,0x56,0x75,0xcd,0xde,0xa2,0xd0,0x4c, + 0xc5,0xb3,0x8a,0xea,0x97,0xf3,0x90,0xb5,0x49,0x3a,0xfa,0xdc,0x7,0x1d,0x41,0xea, + 0x94,0x35,0x3,0x10,0xaa,0x23,0xa5,0x61,0x8d,0x3,0x82,0xde,0xf,0x88,0x5a,0xe2, + 0x93,0x36,0xd7,0xdf,0xfe,0xe5,0x7d,0x3f,0xf5,0x36,0x40,0x2f,0xe3,0x33,0x58,0xf1, + 0xaa,0xad,0x21,0xe,0xee,0xe,0x4c,0x64,0x24,0x91,0x7c,0xad,0x7,0xde,0x60,0x52, + 0xcd,0x94,0x38,0x40,0xe8,0x22,0x23,0x9e,0xa8,0x89,0x2d,0xc8,0xbb,0x9a,0x6a,0x6a, + 0x4e,0x8d,0x80,0xc3,0x2c,0xa,0xc6,0xb1,0xb1,0xe6,0x90,0xdb,0x5f,0x13,0x39,0xe6, + 0xa2,0xf7,0x33,0x63,0x62,0x19,0xfd,0x1b,0x74,0xa,0x61,0x28,0x22,0x50,0x61,0xa1, + 0xbd,0x94,0xfa,0x31,0x4e,0x36,0xb7,0x5a,0x5d,0xd1,0x47,0x83,0xed,0x58,0x5d,0x19, + 0x26,0x25,0x98,0xf2,0xc,0xb0,0xaf,0xff,0xcd,0x5f,0xde,0xf7,0x53,0x81,0xce,0xc9, + 0xa1,0x6e,0x3a,0xff,0x64,0x17,0x39,0xe5,0xaf,0x7a,0xd4,0xe,0x8,0x3,0x41,0x9, + 0x3e,0x8,0x9d,0x87,0x34,0xae,0x63,0x61,0x7,0xb,0x3c,0x49,0xcc,0xa4,0x9f,0xbb, + 0xf3,0xc7,0x34,0x58,0x8f,0xe0,0x80,0x89,0x92,0xc9,0xc4,0xf7,0xc1,0x2,0x4f,0x79, + 0x18,0x37,0xc1,0xe,0xa8,0xaa,0xf9,0x66,0xb6,0xfc,0x93,0x17,0xff,0xdb,0xbf,0xfd, + 0xab,0xcb,0xff,0x29,0x76,0x7d,0x61,0xd6,0x3,0x74,0xef,0x44,0xf0,0xc8,0xac,0xa4, + 0xb1,0xa5,0x4f,0xe8,0xa,0x3,0x40,0xd0,0x96,0xc1,0xe6,0x9e,0x19,0x18,0xd2,0x51, + 0x45,0x12,0x6a,0x9c,0x51,0xdf,0xa2,0xba,0x26,0x66,0x26,0x41,0xfa,0xe7,0xa9,0x52, + 0x1c,0x54,0xda,0x78,0xa6,0x93,0xa6,0xa,0x90,0x2d,0x6,0x29,0x98,0x1c,0xe6,0x3a, + 0xe6,0x82,0xa7,0x4e,0x49,0xe7,0xa1,0x7b,0xca,0x4c,0x9b,0x72,0x9a,0xa7,0x4a,0x4d, + 0x94,0xbd,0x64,0xb6,0x4a,0x19,0x16,0x5,0xde,0x11,0x0,0x7d,0xa2,0x6a,0x15,0x9a, + 0xdf,0x9e,0xc1,0xb7,0x16,0x2a,0x40,0x26,0x35,0x3a,0xa9,0xea,0x38,0x57,0x68,0x84, + 0x7e,0x86,0x78,0x22,0x7,0xd2,0x30,0x3c,0x49,0x99,0xcf,0x4,0x16,0xba,0x7d,0x9e, + 0xe4,0xa0,0x4e,0x8,0x49,0xad,0xe0,0x54,0xab,0x9a,0xc1,0x7c,0x2e,0x49,0xa3,0xf9, + 0xe0,0xb2,0x23,0x88,0x4b,0xf8,0xa4,0xe,0x6f,0x95,0x1d,0x88,0xa2,0x2b,0x88,0x58, + 0x12,0x2f,0x6e,0xad,0xf8,0x81,0x86,0xd4,0x60,0x2a,0x15,0x7a,0xf0,0x37,0x37,0x7e, + 0x7e,0x36,0x3,0x89,0x4c,0xf6,0x7e,0xa4,0x56,0x40,0x67,0xe9,0xdc,0x49,0x98,0xd2, + 0x45,0xb8,0xf2,0xc4,0x1c,0xb4,0xec,0x87,0x4c,0xb6,0xb8,0x3d,0x38,0x6d,0x8d,0x61, + 0x7a,0x8d,0x82,0x5a,0x8f,0xc9,0x9f,0xa8,0x78,0xb0,0x68,0xab,0x6e,0x26,0x45,0xf4, + 0x16,0xc8,0xec,0x73,0xc4,0x56,0x7d,0xef,0x62,0x59,0xbb,0x42,0xb0,0xaf,0xf1,0x3c, + 0xf,0x7c,0x76,0xdf,0x46,0xc9,0x5d,0x3a,0x91,0x62,0x27,0xfc,0x30,0x6d,0xaf,0x55, + 0x35,0xb5,0x55,0x9,0xd7,0xce,0xb,0xba,0xb,0xf4,0x58,0x25,0x20,0x35,0x33,0x78, + 0x2c,0x5,0x3c,0x8,0x4c,0x2b,0xbc,0x7f,0xfd,0xab,0xfb,0x7e,0x9a,0x80,0x52,0xd, + 0x6c,0x23,0xc2,0x23,0x2a,0x29,0x1a,0xdb,0x9e,0x49,0xae,0x18,0x89,0xde,0x11,0xb8, + 0xe7,0xac,0x98,0xc6,0x3c,0x22,0x2a,0x24,0x3c,0x50,0xbc,0x4c,0xd,0x41,0x68,0x7b, + 0x40,0xf4,0xff,0x47,0xfb,0x80,0xe,0x31,0xea,0x68,0x7a,0x98,0xe6,0x45,0xfd,0xc2, + 0x21,0xd5,0xec,0x6e,0x39,0x48,0x43,0x46,0x61,0x76,0x0,0x5e,0x1f,0x9c,0xa0,0x42, + 0x74,0x80,0xc3,0xbc,0x20,0x73,0x7f,0x10,0xc1,0x12,0x76,0xd0,0x3d,0xe,0xa5,0xc0, + 0x52,0xc7,0x92,0xd7,0x3,0xb2,0x58,0xd7,0x21,0xcb,0xdf,0xa8,0x4b,0x50,0x80,0x19, + 0x79,0xa1,0x27,0x5,0xc5,0xc7,0xf9,0x5f,0x34,0x1a,0xba,0x6f,0xde,0xba,0xc,0x9c, + 0x64,0xd6,0x73,0xd9,0xd3,0x58,0xb0,0x8c,0x47,0xb8,0x67,0xbb,0x3e,0xe9,0xa8,0xb2, + 0x2a,0x52,0x10,0x82,0xe7,0x7c,0xaa,0x9f,0x81,0x91,0x2d,0xa4,0xe2,0xc6,0x29,0x7e, + 0xf2,0xe8,0x2b,0xc2,0xf4,0xdd,0x3,0x6a,0x3e,0xe8,0x37,0xc0,0x85,0x2a,0x3e,0xa6, + 0x61,0x3c,0x60,0x19,0x5d,0x69,0xa6,0x17,0x7a,0xf3,0x43,0x6f,0x87,0xfc,0xa8,0xd0, + 0x23,0x77,0x39,0x7c,0xa5,0xe8,0x57,0xb,0xe7,0xe9,0xd7,0x98,0x4f,0x4d,0x6c,0x3e, + 0x29,0x93,0x16,0x60,0x14,0x2,0xa9,0xbf,0x1f,0x97,0xe0,0x76,0xf0,0x98,0x37,0xfb, + 0xc,0x58,0x96,0xaa,0x1b,0xe8,0x48,0x5e,0x2a,0xa0,0x20,0x3c,0x11,0x32,0x3a,0xef, + 0xed,0x1f,0x4,0xb1,0xfd,0x40,0xf4,0x4f,0x9c,0x64,0x9b,0x4b,0xba,0x6,0xa0,0x11, + 0x2c,0x53,0xd9,0x74,0x4b,0x60,0x7a,0x98,0x79,0xad,0xa4,0x70,0xa0,0x98,0x54,0x3a, + 0xca,0x5c,0x1d,0xea,0xe0,0x3e,0x4c,0xe8,0xfb,0xac,0x7,0x8e,0x89,0xaa,0xd8,0xc, + 0xd1,0xeb,0x31,0xb0,0x4d,0x14,0x4,0x9a,0xc6,0xc4,0xcc,0xf5,0x2a,0x11,0x60,0xa5, + 0x12,0x9e,0x85,0xe9,0xcc,0x1f,0x89,0xc9,0x13,0xa0,0x43,0x7d,0xdf,0x2c,0x7d,0x97, + 0x3d,0x6,0x96,0xd1,0xaf,0x9f,0x16,0x41,0x35,0xc8,0x93,0xeb,0x60,0x1f,0x64,0xf6, + 0x4b,0x2e,0xdc,0xa6,0x3,0xcf,0x43,0xad,0x1e,0x62,0xc9,0x79,0xc8,0xb3,0x69,0x7, + 0x98,0xde,0xd5,0xf7,0x58,0x99,0x1c,0xcc,0xee,0x7b,0xc7,0x16,0xfb,0xa1,0xb8,0x51, + 0x79,0x86,0x7a,0x58,0xef,0x54,0x1,0xf,0xc6,0x1c,0x40,0xec,0x94,0xb9,0xa5,0x76, + 0xba,0x4,0x1d,0x4f,0x2,0xfa,0x81,0xd9,0x30,0xd9,0x98,0x9,0xcc,0x8,0xa4,0x45, + 0xec,0x93,0x4e,0x9e,0xcd,0xf4,0x14,0xa9,0xa9,0x40,0x5d,0xb5,0xb4,0x10,0xd3,0x25, + 0x23,0x19,0x5d,0x8c,0x25,0xb1,0xb9,0x8e,0x17,0x6c,0x42,0x29,0x29,0x60,0xfa,0x98, + 0x6f,0xfb,0x5a,0x19,0xce,0x89,0x9e,0x5a,0x83,0xbd,0xa0,0x35,0x5,0xb5,0x10,0xe6, + 0x6b,0xdf,0xd3,0x8a,0x38,0x22,0x50,0xd7,0xcc,0x40,0x74,0x4,0xe9,0xac,0x5d,0xe0, + 0xfc,0x9a,0xac,0xa6,0x0,0x55,0x71,0x70,0xd9,0xdc,0xaa,0x48,0x68,0x14,0x48,0x60, + 0x6a,0x15,0xe6,0x60,0x70,0x58,0x3a,0x3c,0xa3,0x2e,0x1,0x3c,0x6,0x38,0x40,0x64, + 0xa9,0xd3,0x77,0xf3,0x9a,0x2a,0xd7,0x44,0x63,0x40,0xab,0x4b,0xd,0xe4,0xde,0xd7, + 0x90,0x37,0x14,0xe0,0xd6,0x1c,0x1,0xea,0x3d,0xa8,0xf3,0xf8,0xfd,0x53,0x37,0x77, + 0xf,0xb2,0xd0,0xbe,0xe3,0x6,0x1b,0x53,0x6d,0xe0,0x45,0x54,0x98,0xcb,0x65,0x2f, + 0x92,0x38,0x18,0x20,0xff,0xf6,0xd3,0xff,0xf8,0xc0,0xda,0x35,0x4,0xda,0x78,0xd, + 0x3a,0x82,0x60,0xbd,0x11,0x4,0x1d,0x83,0xa1,0x97,0xe2,0x13,0x4c,0x98,0x5,0x96, + 0x97,0xa9,0x6e,0x8,0x60,0x7f,0xf7,0xd7,0xf,0xac,0x27,0x65,0x3,0xb9,0x4a,0x8c, + 0xa6,0x20,0xd6,0xb9,0x73,0x3e,0xdb,0xa5,0xbd,0x82,0x33,0x9b,0x88,0xbf,0x84,0x80, + 0x23,0x4b,0x10,0x73,0xb5,0x27,0x44,0xfa,0x91,0xb4,0x6b,0xc8,0x58,0x22,0x98,0x51, + 0xa4,0xd6,0xa9,0x4f,0xcc,0x2f,0x8,0x41,0xd8,0x67,0x97,0xb4,0x81,0x60,0x87,0xdc, + 0xe1,0x92,0x84,0x6e,0xba,0x7f,0x73,0xca,0x4a,0x6b,0x2b,0x86,0x20,0x57,0x3b,0x21, + 0x5a,0xcb,0x7,0xb4,0xab,0xc7,0x5c,0x70,0x2a,0x57,0xa0,0x80,0xb,0xc4,0x59,0x9e, + 0x85,0xf9,0x8c,0x67,0xc5,0x86,0xd0,0x26,0x81,0x7,0x4d,0xfd,0x80,0x12,0x47,0x9a, + 0x11,0x28,0x98,0x6b,0x48,0x7f,0xc6,0xb6,0xcb,0xc4,0xaf,0x3b,0x72,0x8b,0x63,0xb, + 0xc0,0x19,0x44,0xc9,0xc6,0x11,0x2e,0xec,0x9,0xd6,0x27,0xef,0x7a,0x3,0x1e,0x2a, + 0x14,0xee,0x8a,0xf6,0x4a,0x4,0xb0,0x83,0x2d,0x77,0x3a,0xbd,0x7a,0xcb,0x19,0x74, + 0x18,0x84,0x52,0x7f,0x56,0x59,0xb6,0xa0,0x4a,0x23,0x11,0xc7,0x1,0x10,0xaa,0x80, + 0x20,0x26,0x9e,0x6,0xd8,0x42,0x75,0x65,0x66,0x5b,0xa5,0xef,0x15,0xdf,0xf,0xbc, + 0xd2,0x79,0x75,0xce,0x55,0x83,0xef,0x41,0xc9,0xf3,0x56,0xd8,0x8f,0x57,0x1e,0xf3, + 0x71,0xc5,0x39,0x10,0xb5,0xa3,0x9d,0x24,0x9d,0x11,0x6,0xa2,0x36,0xd0,0x55,0x68, + 0xf5,0x3,0x80,0x87,0xe3,0x1b,0x0,0xa2,0xb0,0xda,0x80,0x1d,0xfa,0xb4,0x10,0x94, + 0x6b,0x61,0x34,0x7d,0x71,0x55,0xa4,0x83,0xf2,0x8b,0x77,0x1e,0xb2,0x3b,0x77,0x77, + 0x48,0xf5,0x31,0xc,0xee,0x28,0xf1,0x6c,0xc9,0x57,0xb7,0xb0,0x68,0xe,0x95,0x5e, + 0xe7,0xc1,0x7d,0x48,0xcc,0xdd,0x38,0xef,0x52,0x1,0xc,0x1a,0xa6,0x71,0x42,0x10, + 0x62,0xec,0x87,0x39,0xb,0x61,0x45,0x76,0x41,0xcd,0xcc,0x46,0xf0,0x35,0xa9,0x28, + 0xe1,0x3d,0x91,0x34,0xc9,0xd4,0x24,0xb1,0x38,0x78,0x72,0x14,0x53,0xc8,0x50,0x93, + 0x54,0xe0,0xce,0x5a,0x1,0x8a,0x6a,0x1a,0xf5,0xbb,0xdc,0x4,0x51,0x40,0x18,0xf, + 0x33,0x2b,0x38,0x51,0xbc,0x25,0x93,0xcd,0x5d,0x2d,0x60,0x20,0x64,0xd,0xc,0x21, + 0x38,0xa4,0xce,0x87,0xf,0x3e,0xc4,0x98,0xa0,0xef,0x4f,0x15,0x65,0x50,0x3e,0xe0, + 0xee,0x26,0x92,0xf5,0x5,0x49,0x42,0x3d,0x96,0x2,0xed,0x1f,0x7c,0x54,0x4c,0xec, + 0xd2,0xc9,0x8c,0x4,0x19,0x31,0x3b,0x59,0xa8,0x3a,0x48,0x82,0x9b,0x92,0x2c,0x2e, + 0x6e,0x88,0xc2,0xb6,0x2f,0xaa,0x50,0x24,0x89,0x33,0x69,0x3e,0x82,0xb5,0x79,0x54, + 0x64,0xc5,0x9e,0xe4,0xc6,0xa4,0x7a,0x2d,0x8f,0xc,0x24,0x9,0x57,0x4a,0xcf,0x5f, + 0x83,0xaa,0xc8,0x17,0xf8,0xa4,0xfd,0x66,0x41,0x95,0x29,0xcd,0xb1,0x7c,0x54,0x54, + 0x2,0x15,0x53,0x64,0xe1,0x68,0xed,0x13,0x29,0xce,0x27,0xa9,0x79,0x6c,0x93,0x26, + 0x70,0x3,0x9b,0xda,0xab,0xfd,0x1f,0x62,0x10,0xea,0x46,0xf,0x16,0x84,0x41,0x3c, + 0x74,0x2e,0x6c,0x2e,0xfb,0x38,0x5,0xae,0xa0,0x7b,0x0,0xc8,0xf7,0xf4,0xd9,0x20, + 0x26,0x2a,0x81,0x4c,0x3a,0xa2,0x9,0xb0,0x91,0xdb,0x79,0x59,0xfe,0xd0,0x6c,0x32, + 0xfd,0xc,0x41,0x9c,0x38,0x94,0x8,0xe8,0xf0,0x78,0x8f,0x1c,0x53,0xd8,0xa9,0x3a, + 0xc5,0xe5,0x68,0x6,0x8f,0x5a,0x29,0x41,0xb3,0x5b,0x14,0xbc,0x8a,0xa9,0x71,0xc4, + 0x68,0x81,0x52,0xe6,0x2c,0xc3,0xaf,0x1e,0x80,0xe3,0xf3,0x2a,0x40,0x1a,0x95,0x60, + 0x40,0xfa,0x40,0xe5,0xb7,0xb3,0x84,0x5a,0x5d,0x43,0xff,0xf0,0xd3,0x87,0xff,0xc1, + 0x7,0x8f,0x73,0x46,0x2f,0x41,0xe,0x8a,0xa0,0x34,0x21,0x2,0x28,0x83,0x3e,0xbb, + 0xbb,0xab,0x70,0x71,0xc1,0xe6,0x8c,0x64,0x6a,0xd5,0x79,0x6f,0xc3,0x93,0x86,0x3d, + 0xfb,0xb5,0xef,0x20,0x24,0xef,0x65,0xda,0x46,0xa9,0x79,0x1a,0x3a,0x39,0xeb,0x78, + 0xd4,0xf1,0xb,0xe4,0xbc,0xe0,0x6e,0x8,0x40,0x15,0xec,0x28,0x1b,0xdc,0x52,0x67, + 0x8e,0xf1,0xe5,0xd6,0x50,0x51,0x4e,0x87,0x60,0x4,0x10,0xa9,0x6b,0x1,0xeb,0xf1, + 0xf,0x97,0x41,0x4d,0xf0,0xf7,0x68,0x5e,0xc7,0xce,0x2e,0x79,0x24,0xa,0xe0,0x51, + 0xe8,0xe,0xa2,0x5f,0x3f,0x18,0x22,0x3b,0x46,0xa1,0xdf,0xcb,0x1e,0xaf,0x20,0x6a, + 0x71,0x3,0x4f,0xc4,0xb8,0x9c,0x8a,0xb3,0xd8,0xdc,0x19,0xc8,0xc5,0xdd,0x84,0x58, + 0x98,0x8c,0xa8,0xec,0x13,0x0,0xe1,0x8,0x56,0x81,0x2e,0x25,0x75,0xf,0x42,0xd5, + 0x6e,0xd3,0x52,0x66,0xb4,0xaf,0xbd,0x32,0xce,0x7a,0xc8,0x6a,0x53,0x1a,0x1f,0xad, + 0xf2,0x80,0xf3,0xcc,0xa3,0xfd,0x5e,0xdc,0x23,0x69,0x8b,0x5b,0x7,0xe5,0x99,0x59, + 0x39,0x89,0xb4,0xf3,0x9,0x3,0xe2,0xd8,0x93,0x38,0x6b,0x8d,0x23,0x67,0x41,0x6b, + 0xa3,0x21,0x39,0xa5,0xbe,0xbe,0x37,0xd4,0x44,0x61,0x6f,0x73,0x77,0xea,0x96,0x41, + 0x24,0x37,0x7,0x62,0xd3,0x6d,0xf3,0xd4,0x85,0x87,0x71,0x3f,0xc7,0x6c,0x2a,0x13, + 0x1b,0xd0,0xf2,0xc8,0x66,0x3b,0xc2,0x14,0x41,0x80,0x32,0x63,0x3e,0x7b,0x47,0x88, + 0x49,0x59,0x7e,0x4f,0x4d,0xa6,0x82,0xa0,0x9e,0x99,0xc1,0x4e,0x86,0x8e,0x9f,0x5, + 0x8,0x36,0xf3,0xfd,0x7a,0xdb,0xf2,0xef,0xff,0xe6,0x81,0x35,0x7d,0x55,0x4e,0xeb, + 0xe1,0x73,0x34,0x8c,0xa4,0x60,0x5a,0xe5,0xc5,0x18,0x18,0x65,0xa,0x15,0x34,0x8f, + 0x24,0x7a,0xe3,0x52,0xe1,0x21,0xa6,0x90,0x7,0xfa,0xc3,0xa9,0x77,0x30,0xe,0x91, + 0x83,0x96,0xae,0xc8,0xf6,0xe1,0x13,0x2d,0x6b,0x46,0x9d,0x32,0xf,0xff,0x16,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xfb,0x44,0x4a,0xd0,0x66,0x12,0xb7,0x1e,0xf8, + 0xe1,0x2c,0xab,0x9a,0x6d,0x80,0x42,0x1a,0x9e,0xf5,0xcc,0x59,0xe5,0x29,0x51,0x1f, + 0xa6,0x36,0xe1,0x59,0xb8,0x67,0xc4,0xe6,0x22,0x46,0x35,0xa9,0x11,0xca,0x98,0x81, + 0x30,0xef,0x53,0x5a,0x9a,0x7,0x8d,0xf5,0xb1,0x7d,0xfc,0x60,0x8d,0xa4,0xb3,0x6a, + 0x0,0xd2,0x95,0xc9,0xf3,0x7c,0x25,0xcf,0xf5,0x4d,0x6,0xea,0x54,0x2,0xf6,0xf7, + 0xeb,0xe5,0xbf,0x93,0x24,0xa7,0xa0,0xb7,0xf7,0xda,0x41,0x47,0x17,0x9,0xb6,0x14, + 0xad,0x3f,0xda,0x69,0xd3,0xee,0x15,0x4,0x47,0x6b,0x88,0xa4,0x9c,0xa0,0xd5,0x36, + 0xd8,0x8c,0x44,0x9c,0xb,0x67,0x92,0x24,0xed,0x34,0xdf,0xd1,0xb0,0x3,0x67,0x5c, + 0xb9,0x5d,0xc3,0x72,0x7b,0x6f,0x45,0xec,0xaf,0x19,0xcd,0x83,0xc6,0xab,0xde,0x3b, + 0xbb,0xa5,0x7a,0xdc,0x36,0x2c,0xd1,0x9e,0xc9,0xf8,0xb6,0x8d,0xa9,0x34,0x8,0x6d, + 0x12,0x30,0x5a,0x1e,0x93,0x7c,0xb9,0xa1,0x1,0x9b,0x50,0xd0,0x23,0x69,0xa1,0xca, + 0xc9,0x89,0xd9,0xe5,0x34,0xe2,0xf0,0x19,0xcd,0x2f,0x36,0x2b,0x68,0x3f,0x4f,0x45, + 0x6c,0x41,0xa,0xdf,0xde,0x45,0x38,0x10,0xf5,0x73,0x99,0x2a,0xe5,0x11,0xbf,0x40, + 0x6b,0x8b,0xaa,0x14,0x9a,0x16,0x70,0xc7,0xc8,0xec,0x1f,0xfd,0xdc,0xb,0xff,0xdd, + 0xdf,0xff,0xdd,0x43,0xff,0xa9,0xe6,0x80,0xca,0xa7,0xf0,0x96,0x4,0x94,0x9d,0x7d, + 0x60,0xde,0x2b,0x47,0x99,0x7f,0x23,0x4a,0x59,0x93,0x7e,0x22,0x2c,0x94,0xab,0xa3, + 0xdd,0x4e,0xaf,0xd7,0xd9,0x6,0x2,0xef,0xa9,0x26,0x5a,0xe8,0x9d,0x28,0x1a,0x6e, + 0xdb,0xc4,0x8b,0x3,0x89,0xfb,0xa3,0xa3,0x2,0x2,0x99,0x82,0x48,0xd,0x56,0x5d, + 0x1f,0x25,0xf1,0x6a,0x47,0x87,0x94,0x67,0xce,0x76,0xb1,0xe0,0xc0,0xde,0xb4,0x15, + 0x50,0x33,0xa,0x6b,0xd8,0x90,0x7e,0xcd,0x27,0xea,0xcd,0xf0,0xa0,0x8b,0x3f,0x2, + 0x41,0x4f,0x44,0xf6,0x31,0xdd,0xb8,0x58,0xef,0x83,0x75,0xc2,0xd,0xf8,0x20,0x8c, + 0x90,0x61,0xb1,0xa2,0x8b,0x38,0xfd,0xa,0x3c,0x79,0x8b,0x85,0x9f,0x82,0x3d,0xd, + 0x38,0x3c,0x33,0x22,0xe0,0x6f,0xca,0x92,0x3c,0xc8,0x9c,0x4b,0x81,0x49,0x3e,0x29, + 0xe,0x49,0x14,0x4e,0x4a,0x55,0xba,0x85,0x71,0x56,0x44,0xa4,0xcf,0x48,0x12,0xc8, + 0x5d,0x5d,0xa5,0x47,0x5,0x94,0x1,0xe2,0xe2,0x88,0x63,0xf3,0x20,0x54,0xe3,0x18, + 0xa8,0x3e,0xf9,0x42,0x63,0x6,0x99,0x58,0x7a,0x3d,0x98,0x53,0x68,0xa,0x49,0x86, + 0x36,0xbe,0x7d,0xcc,0xa7,0x29,0xff,0x43,0x0,0x3f,0xb1,0xfe,0xfc,0x30,0x98,0x71, + 0x8b,0xfe,0xea,0x49,0x44,0x7f,0x96,0xcb,0x94,0x9,0xfd,0xa1,0x78,0x32,0x9e,0x41, + 0x60,0xae,0x7b,0xd8,0x16,0x46,0x1d,0xb,0xb,0x57,0xdb,0x9c,0xb6,0x92,0xcc,0x25, + 0x4b,0x10,0x12,0x10,0xae,0x7f,0x27,0xfe,0x79,0xa4,0xa7,0x10,0xa7,0xbf,0x83,0x6e, + 0xa3,0x91,0x4c,0x18,0x20,0x7a,0x43,0xbd,0x7a,0x18,0xe5,0xf4,0x4,0x77,0xb4,0x19, + 0x1d,0xd9,0xbc,0xa5,0xbd,0xdd,0x3f,0xfc,0xf4,0xf2,0x6a,0xb2,0xf1,0x18,0xcb,0xe0, + 0xed,0xff,0x74,0xf4,0xcb,0x5e,0x2,0x4c,0xdb,0xea,0x3f,0x83,0x6a,0xd1,0x0,0x88, + 0x92,0x32,0x4e,0x33,0xd4,0x7e,0x3b,0xca,0x88,0x62,0xd,0x50,0xd4,0xc1,0x2b,0xc5, + 0x85,0x9b,0xd8,0xb,0x62,0xaf,0x8f,0x9d,0xf3,0xec,0x50,0x6,0x9,0xc6,0xd8,0x1b, + 0x86,0xa6,0xcb,0x66,0x74,0xb5,0x6b,0x6f,0x8d,0xd4,0x3a,0xf0,0x4,0xd7,0x1a,0x2d, + 0xf0,0xef,0x43,0x5e,0xab,0xfc,0x26,0xf8,0x56,0xf1,0x6f,0x80,0xd9,0x36,0x66,0xc6, + 0x40,0x41,0xff,0x1c,0x47,0xe0,0xb3,0x33,0xc8,0x5a,0xf1,0x4,0x28,0x10,0x14,0xa3, + 0x1b,0xb,0x2e,0xd6,0xe0,0x1,0xef,0x2c,0x2,0xa2,0x7f,0xc1,0x87,0xd6,0x7d,0x17, + 0x94,0xf4,0xa2,0xa3,0x2d,0x1b,0x53,0xd3,0x74,0xde,0xd8,0x6c,0x34,0xc5,0xf5,0x60, + 0xa7,0xe2,0x35,0x62,0xac,0x27,0x1c,0x88,0x8b,0xf4,0x34,0x57,0xce,0x45,0x56,0xb3, + 0x7,0xa8,0x75,0x8f,0xb1,0x5b,0xdb,0xca,0x5,0xd,0xa4,0xe5,0x0,0x3d,0x4,0x90, + 0x20,0x69,0x1f,0xeb,0x29,0x90,0x66,0xdb,0x74,0x87,0xd6,0xf7,0x92,0x7d,0x4a,0x64, + 0xc3,0x3d,0x3b,0xea,0xac,0x49,0xc,0x3b,0x54,0xce,0x76,0xc0,0xc5,0x3b,0xe9,0x2c, + 0x83,0x7b,0xc3,0x3,0xdb,0xd1,0xe5,0x55,0x26,0x8,0xe1,0x46,0xcd,0xac,0xd0,0x8c, + 0x50,0x47,0x4c,0x4c,0x65,0x90,0xdc,0xc7,0x50,0x4e,0x14,0x1d,0x37,0xa5,0xee,0x9f, + 0x5b,0x1,0xe2,0xb1,0x41,0x73,0x65,0x95,0xa5,0x2f,0x0,0x86,0x2f,0xb2,0x52,0x52, + 0xcd,0x64,0x9c,0x47,0x4c,0xe7,0x81,0x8a,0xea,0x18,0x13,0x93,0x74,0xc4,0xb8,0x2e, + 0x14,0x7e,0x68,0x92,0x3a,0xa0,0xf7,0xcf,0xe6,0x63,0x41,0xb,0x78,0x8a,0x45,0xec, + 0x94,0x46,0xc6,0x6,0xc5,0xf1,0xb0,0x5b,0xf0,0x96,0x8,0x37,0xd1,0x61,0xd1,0xf5, + 0x6b,0xca,0x43,0x8f,0x88,0x40,0x9f,0x60,0xf1,0xb9,0xd,0x16,0x47,0xb5,0x9e,0x44, + 0x50,0xb4,0xbd,0xee,0x82,0xf9,0x8e,0xb3,0x75,0xed,0x21,0x6b,0x55,0xe4,0x4,0xd9, + 0xcf,0x3e,0x8f,0xe0,0xd1,0x6c,0xb1,0xe4,0x84,0xa6,0x9e,0xb4,0x41,0xd3,0x4b,0xdc, + 0xd9,0x4c,0xdc,0xd4,0x10,0x38,0xf6,0xa3,0xaa,0x74,0xb9,0xf3,0x3e,0xf3,0xc8,0x5, + 0xb9,0xea,0x90,0x9e,0x70,0xb4,0xe7,0x92,0x81,0x4f,0x3d,0xc9,0xc1,0x7c,0x78,0x36, + 0x99,0x41,0x64,0xd,0x58,0x4e,0x3c,0xc2,0xb3,0xeb,0x89,0x80,0xab,0xcc,0x2b,0x3f, + 0x13,0xd1,0xca,0xe6,0x83,0xdd,0x54,0x45,0x6c,0xa,0x46,0x4e,0x92,0x3,0x8,0x5d, + 0x17,0x74,0xfd,0x7e,0x49,0x3,0x3c,0x9a,0xe8,0x98,0xf9,0x84,0x26,0x2a,0x6a,0xb3, + 0x86,0x9,0xe7,0x3e,0x6b,0x53,0x77,0x51,0x8e,0x82,0xd0,0xda,0x1e,0x6d,0x76,0x77, + 0x58,0x29,0xf4,0x76,0xdd,0x3a,0x9b,0xad,0xb1,0xc6,0xe1,0x59,0xcf,0xb8,0x2c,0x98, + 0x50,0xcc,0xa,0xcd,0x36,0xb9,0x95,0x4f,0x18,0xa,0x24,0x7d,0x6f,0xea,0x68,0xf9, + 0x84,0xd6,0xd4,0x27,0xa7,0xb4,0x39,0x5a,0x38,0x74,0xdf,0xbc,0x5e,0x17,0x29,0xd0, + 0x44,0x1e,0x39,0x71,0x74,0xea,0x17,0x75,0x3a,0x40,0x77,0x4a,0xb0,0x53,0x22,0xd3, + 0x6,0x9f,0x1e,0xcb,0x5b,0xed,0x16,0xa1,0x20,0x98,0x4d,0xec,0x32,0x5d,0x3d,0x20, + 0xb5,0xe9,0x14,0xa8,0x8a,0x1c,0xf,0xa5,0xa0,0x65,0xb5,0x4,0x70,0x6b,0x78,0x8, + 0x46,0xee,0x93,0xc5,0xa2,0x47,0xdd,0xbf,0x19,0x1a,0x19,0x85,0x44,0x62,0x1a,0x80, + 0xb4,0xa0,0x8d,0xf2,0x8a,0xb3,0x54,0x6c,0x8b,0xb5,0xb1,0xfa,0x72,0x63,0x3d,0x55, + 0x27,0xf6,0x40,0x6b,0xe9,0x76,0x68,0xb,0xc5,0x20,0x61,0x34,0xf4,0x46,0x55,0x19, + 0x2b,0xd6,0xe5,0x80,0xa9,0x6b,0xbf,0x40,0xfd,0x24,0xb5,0xb0,0xe9,0x53,0xdb,0x42, + 0x7a,0x5,0x4,0x46,0xc0,0x0,0x85,0x81,0xa,0xf2,0xa,0x8e,0x24,0x9,0xd0,0x13, + 0x85,0x3a,0xc0,0xc0,0x18,0x29,0x17,0x84,0x60,0x2,0xe9,0x60,0xee,0x2,0xe1,0x35, + 0x79,0xec,0x31,0x48,0x3b,0x89,0x8a,0x70,0x18,0xb4,0xb5,0xd1,0x99,0x2a,0xda,0x52, + 0xe5,0xfe,0xbe,0xf5,0xa4,0x61,0x8,0x93,0x7b,0x17,0xb9,0x45,0xcf,0xf8,0xd,0xd, + 0x1f,0x52,0xf1,0x12,0x64,0x10,0x27,0xce,0x2f,0x30,0xaf,0x6a,0x14,0x95,0xaa,0x51, + 0x8b,0x1b,0xa7,0xc4,0xba,0xae,0x7f,0x36,0xe3,0xf0,0xc9,0x5c,0x58,0x5a,0x43,0x2e, + 0xe0,0xd5,0xa8,0xa5,0xcf,0xb6,0xe1,0x48,0x88,0xfa,0xb0,0xeb,0x41,0x40,0xf2,0x30, + 0xd0,0x27,0x31,0xb7,0x68,0xf7,0x1c,0xcb,0x3a,0x6,0xe5,0xb5,0xdf,0x3b,0xc9,0xcf, + 0x51,0xfc,0xbe,0x63,0xac,0x53,0x7f,0x3,0x55,0x98,0xe2,0x56,0x6c,0x74,0xea,0x3, + 0x8b,0xf0,0xc6,0xee,0xae,0xfa,0x9e,0xb,0xad,0xd,0x1,0x34,0xe7,0x6c,0x43,0xa, + 0xe1,0x3d,0xf6,0x76,0x9,0xdb,0xef,0xa5,0xf1,0x46,0x16,0x78,0x1,0x45,0x24,0xf, + 0x8d,0x5a,0x31,0x98,0x89,0x22,0x25,0x51,0x9a,0xd6,0xc7,0x2c,0x2d,0x66,0xaf,0x48, + 0xc6,0x2c,0x38,0x60,0x10,0x45,0xde,0xdb,0xe4,0xe1,0x1d,0x49,0xbd,0x9e,0x44,0x17, + 0x4c,0x54,0x9c,0x34,0x2f,0xd1,0x56,0xb3,0x4d,0xa4,0x49,0x33,0x4c,0x69,0xb4,0x8a, + 0x98,0x22,0x12,0x7b,0x33,0x1e,0x67,0xe1,0x4d,0x1,0xce,0x4d,0xb2,0xc9,0x9c,0xe8, + 0x79,0x0,0xfa,0x50,0xfb,0x4d,0x78,0xcf,0xc1,0x6b,0x5d,0x12,0x47,0xae,0xe0,0x3d, + 0x89,0x31,0x52,0x2,0x1,0x91,0x47,0xec,0x1,0xa7,0x7d,0xaf,0x12,0x20,0x59,0x30, + 0x52,0x7d,0x34,0xc3,0x89,0xe1,0x34,0xdd,0x3,0x52,0x4f,0xd1,0x6a,0x71,0x39,0xa8, + 0x32,0x6a,0x58,0xcd,0xf3,0x81,0xf1,0x7c,0xf6,0xf6,0x73,0x10,0x90,0x90,0xa4,0xc5, + 0x67,0x1c,0xca,0xbd,0xa8,0xb6,0xcd,0x87,0x73,0x85,0x7b,0xd,0x9e,0x8e,0x1,0xe3, + 0xdf,0xd3,0xc5,0x6d,0x7f,0x1e,0xc5,0xb,0xd3,0xfa,0x3b,0xf9,0xb2,0xd4,0xb5,0xb6, + 0xb9,0x3b,0x8a,0x61,0x17,0xad,0xe1,0x13,0x63,0x7f,0x29,0xef,0x9,0x38,0x82,0x4e, + 0x2c,0x45,0xb1,0x1e,0x58,0x4b,0x74,0x19,0x19,0x1a,0x70,0x60,0x24,0x81,0x66,0xd7, + 0x5c,0xbe,0x7b,0x72,0x44,0x46,0x50,0x81,0xe,0xb2,0x94,0xed,0xf0,0x2b,0x31,0x8, + 0xb6,0x9e,0x50,0xe1,0xa3,0xc3,0x32,0x25,0xad,0xc6,0xfb,0x1e,0xa1,0x6b,0x4,0xa3, + 0xb6,0x68,0xe9,0x43,0xe5,0xfa,0x9b,0x5,0x70,0x77,0x1f,0x15,0x68,0x17,0x71,0x18, + 0x5d,0x41,0xa6,0x42,0xb6,0x84,0x40,0x47,0x38,0x66,0xd8,0x1c,0xa9,0xe2,0x6d,0x95, + 0x38,0xe1,0x3a,0x6a,0xc0,0x6,0x3c,0x2,0x61,0x46,0x4f,0xa9,0xd3,0xce,0xaa,0x7c, + 0xd0,0xc0,0x66,0xd,0x4d,0x4,0xc,0xf1,0x8d,0xda,0xb0,0xaa,0xbb,0xaa,0xb0,0x55, + 0x9b,0x95,0x52,0x30,0xd4,0x7,0x89,0xad,0x71,0x82,0x51,0x20,0x7,0x9d,0x80,0x3a, + 0xff,0x8c,0xee,0x4f,0xa1,0xef,0x42,0xd1,0x28,0x5,0x13,0x73,0x42,0xf6,0x8e,0x39, + 0x77,0xef,0x4,0xb9,0x20,0x51,0x3b,0xfe,0x82,0x39,0x96,0xa2,0xe5,0x0,0xf7,0xad, + 0x6a,0xd8,0x60,0x82,0x77,0xf5,0x21,0x1f,0x35,0x0,0x8f,0xad,0xdd,0xea,0x59,0x91, + 0xa1,0x4d,0x7,0x61,0xda,0x85,0xb1,0xc1,0x78,0xa1,0xab,0xe0,0x89,0xa9,0x76,0x49, + 0x4d,0x0,0x8d,0x73,0x37,0xb8,0xa8,0x9e,0xc9,0xc7,0xa,0x2c,0xb9,0xf4,0xd6,0xb5, + 0x7f,0x92,0x41,0x44,0xe2,0xf7,0xed,0x1a,0xe4,0x84,0x10,0x1f,0xfd,0x7f,0x6d,0x62, + 0xf7,0x16,0xe6,0x6e,0x19,0x69,0x65,0x53,0x3a,0xaa,0x99,0xae,0x79,0x91,0xe4,0x84, + 0x25,0xa1,0x9a,0x88,0xc,0xd8,0xd1,0x41,0xd6,0x29,0x11,0xd3,0xd1,0x1,0xcd,0x38, + 0x1a,0xa0,0x51,0x67,0xf2,0x10,0x91,0xd,0x67,0x9f,0x5f,0x44,0xcf,0x68,0xef,0xf4, + 0x2e,0x2e,0xd8,0xbb,0xe1,0x0,0xb,0x5a,0xa4,0xbe,0xd3,0x84,0x8a,0x30,0x21,0x78, + 0x77,0xb1,0xff,0x89,0xf5,0xeb,0xa4,0x19,0x18,0x86,0x9f,0x91,0x47,0x19,0x1b,0xe3, + 0xec,0x52,0x9d,0x67,0xb8,0x6a,0x76,0x8b,0x38,0x49,0x4a,0xd4,0xb1,0x91,0xa8,0x81, + 0x13,0x6e,0x53,0xaa,0xd4,0x90,0xad,0xc5,0x4c,0x63,0xde,0x66,0x9d,0xe,0x64,0xb3, + 0x3d,0x4b,0xe4,0x7d,0x4e,0x62,0x20,0xcc,0x81,0xaa,0xc9,0xda,0x5a,0xe4,0x6e,0xa6, + 0x42,0xa,0xb5,0xf5,0x8d,0xb4,0x58,0xb,0x79,0x7c,0x20,0xd8,0x7c,0x34,0x64,0x31, + 0xcd,0x2,0xb,0x74,0x4,0x59,0xc,0xa9,0x3f,0x8c,0xe8,0xae,0xe0,0xed,0xc,0xaf, + 0x71,0x77,0x8e,0x9f,0x2c,0x9d,0xb0,0x4b,0x69,0xd3,0xe6,0xbe,0x97,0x9d,0x80,0x6d, + 0xd5,0x42,0x7,0xee,0xbd,0x7e,0xc1,0x48,0x48,0xf6,0x1b,0xb3,0xf5,0x96,0x59,0x31, + 0xc0,0x7d,0xf3,0x1a,0x90,0xbc,0x83,0xd,0xd1,0xb0,0xbd,0x1e,0xd6,0x64,0x40,0xdf, + 0xd7,0x8e,0x23,0xb5,0xde,0xc1,0x6,0x5f,0x3d,0x52,0x16,0x6,0x8d,0x34,0x6c,0x82, + 0xd3,0xc8,0x63,0xe0,0x8c,0xc1,0x23,0x3b,0x9f,0x61,0xb2,0xb9,0x1c,0xe3,0x43,0x89, + 0xf9,0x95,0xaa,0x7a,0xb0,0xdf,0x82,0x32,0x1,0x88,0x9a,0x99,0x6d,0x9e,0xbd,0x34, + 0x35,0xb8,0xc0,0x9c,0x24,0x85,0x3b,0x38,0xb4,0x57,0xe8,0x5,0x5,0x9b,0x6d,0xe3, + 0xca,0x14,0xd0,0x53,0xf3,0x1c,0x41,0xfb,0xd5,0x86,0x4b,0x1,0xa3,0xbc,0xd5,0x51, + 0x6d,0xc,0x30,0xca,0x90,0xd9,0x25,0x2d,0x63,0xd0,0x6c,0xda,0x69,0x9d,0x55,0x60, + 0x47,0xeb,0x4c,0x74,0xe4,0x18,0x86,0xf1,0x3c,0x5,0xf4,0x51,0x80,0x21,0x59,0x79, + 0x1,0x85,0x4e,0xa9,0x13,0x50,0xea,0xe4,0x8c,0xdd,0xa2,0x74,0xcb,0x31,0x43,0xa7, + 0x96,0x7b,0xe9,0xd0,0x36,0x9,0x98,0x6c,0x4a,0x49,0x63,0x40,0x87,0x9f,0xa0,0xfa, + 0xb6,0x95,0xc6,0x5e,0xd7,0x2c,0x6f,0x74,0xef,0x8a,0xe3,0x7b,0x86,0xdb,0x3a,0x38, + 0x27,0xfa,0xd8,0xa2,0xe6,0x50,0x54,0x43,0x96,0xf6,0x76,0xfb,0xa8,0x84,0x4c,0xd8, + 0xf7,0x31,0x94,0x3b,0xd3,0x5e,0x19,0xab,0xe9,0x7d,0xe3,0x13,0x4b,0xa9,0x7,0xf3, + 0xb1,0x73,0x32,0xc1,0x2a,0x14,0x28,0x41,0x61,0xae,0x39,0x78,0x8e,0xae,0xa9,0x36, + 0xc7,0xd2,0x7e,0x34,0xb2,0xd1,0xb5,0xa6,0xe5,0xde,0x16,0xed,0xa6,0xd5,0x73,0x6c, + 0x7c,0xba,0xb7,0x1d,0x1c,0xe5,0x47,0x27,0x5c,0xe3,0x24,0x7f,0xea,0xa1,0x46,0xb4, + 0xe8,0xeb,0xa2,0xc8,0x4f,0x46,0xb1,0x4e,0x6,0x2f,0xb4,0xae,0x93,0x7e,0xb8,0x25, + 0xca,0xbf,0xce,0xf7,0x19,0xd1,0x16,0xab,0xc1,0x1,0x7d,0x82,0x28,0x81,0xf,0xa0, + 0x8e,0xcb,0x1c,0x71,0x38,0xfd,0x40,0x66,0x21,0x98,0x79,0x3b,0xbb,0x22,0xf9,0xa4, + 0x55,0xce,0x1a,0xf4,0x3e,0x3,0x25,0xea,0xc8,0x1d,0xd3,0xd9,0x55,0x2c,0x9f,0xf, + 0xb9,0x5e,0x23,0xd1,0x53,0xe0,0x39,0x54,0xa,0xbe,0x46,0xae,0x17,0x13,0xde,0xb, + 0x72,0xce,0x62,0x33,0x93,0x1d,0x9e,0x9,0x4d,0x3e,0x33,0x80,0x1f,0x59,0x48,0xc8, + 0x54,0x60,0x5,0x92,0xb8,0x70,0x8b,0xd1,0x46,0xcf,0x76,0x37,0x7e,0x18,0x94,0x9b, + 0xf6,0x45,0x21,0xe2,0x4,0xe0,0x8e,0xb0,0x8,0xe3,0xd,0x91,0xec,0xce,0xe5,0xee, + 0x7d,0xfc,0xbd,0x12,0xea,0x48,0x3a,0xfe,0xb2,0x90,0x32,0xa8,0x7d,0xa7,0x13,0x81, + 0x38,0xc3,0xb3,0xb0,0x62,0x83,0x77,0xe3,0x41,0xa5,0x68,0x7c,0x77,0xef,0x9c,0xd9, + 0xba,0xf3,0x71,0x62,0xdf,0xcd,0x30,0xb3,0xad,0x78,0x3d,0xcf,0x6a,0x41,0x54,0x36, + 0x27,0x99,0xf2,0x7a,0x20,0x94,0xda,0xfa,0xdd,0xeb,0xb7,0x32,0xc2,0x45,0x3b,0xb8, + 0xdc,0x4,0x7d,0xed,0x99,0xf2,0x8,0x12,0x77,0x5,0x97,0x8a,0xd,0x91,0x14,0x9c, + 0x88,0x0,0x94,0x1a,0x48,0x6,0xe2,0xd9,0xc8,0xb7,0xb0,0x60,0x78,0x11,0x95,0xe1, + 0xab,0x28,0xe,0x66,0x2e,0x53,0x75,0x5e,0xe,0x7b,0x5,0xec,0x48,0x48,0xcf,0xa0, + 0x68,0xa8,0xb3,0xb5,0x5e,0x81,0xe,0x37,0xf0,0x31,0x33,0xf2,0x96,0x96,0xf5,0x82, + 0xb9,0xf7,0x7a,0x7,0x21,0x8b,0xf8,0xc3,0xfb,0x32,0xd8,0xaa,0x93,0x75,0x23,0x26, + 0xec,0xc,0xc3,0x91,0x96,0xa0,0x47,0x1b,0x64,0x9c,0x0,0xe1,0x41,0x42,0xf5,0xc1, + 0xed,0x5,0x14,0x42,0xf7,0xf4,0x44,0xb3,0xa0,0x2b,0xe7,0xf6,0xb9,0x3a,0x4b,0xd2, + 0x62,0xf,0x5d,0xc3,0x84,0xa5,0x1e,0x2b,0x6d,0xed,0x8e,0xf9,0xb,0x8,0xf,0x86, + 0xa1,0xbd,0xbf,0x3f,0x5d,0xe7,0x13,0x84,0x11,0xdf,0xa5,0x16,0x30,0xea,0xd,0xc0, + 0x15,0x7a,0xb4,0x5d,0x2d,0x6,0xc2,0x0,0xd3,0xd8,0x74,0xa8,0x0,0xdb,0xb6,0xb9, + 0x77,0x3d,0x1f,0xc6,0x19,0x6f,0x7b,0xe6,0xb7,0x35,0xc1,0x24,0xdb,0xbc,0x65,0xc3, + 0x3b,0xdb,0x76,0xef,0xf1,0x6e,0x6d,0x80,0xd6,0x9f,0xe7,0xfe,0x53,0xd2,0x1d,0x68, + 0xa3,0x89,0x26,0xd6,0xb4,0x27,0x7e,0x75,0xdb,0x58,0xeb,0x6c,0x6c,0x9b,0x58,0x1a, + 0x72,0xdf,0x1d,0x1e,0x83,0xb4,0xe2,0xaa,0x2c,0xc6,0x10,0x57,0x69,0x71,0x41,0xb9, + 0x9b,0x65,0xa1,0x36,0x8a,0xa5,0x5d,0xd9,0x93,0x35,0x56,0x48,0xa2,0x1a,0xd6,0x66, + 0xe8,0xf5,0x3f,0xff,0xe7,0xff,0xf1,0xe0,0x6a,0xd4,0x46,0x90,0x16,0x90,0xb8,0x9d, + 0x99,0x98,0xac,0x73,0x30,0xf0,0xf4,0x3a,0x48,0x47,0x93,0x55,0xcd,0x52,0x8d,0x2a, + 0x65,0x8f,0xf2,0x31,0xe3,0x42,0xca,0x75,0x27,0xd3,0x4,0xd4,0xbb,0x7d,0x3a,0xc6, + 0xe0,0x76,0xaf,0xf0,0xaa,0xe5,0x8c,0xa,0xc2,0x22,0xea,0x13,0x1c,0x93,0x11,0xd5, + 0xfa,0xe,0x6,0x3,0x16,0x69,0x5d,0x13,0x91,0x5c,0xc4,0x60,0xab,0xa6,0xca,0xb0, + 0x43,0x68,0xe8,0x3,0x7e,0xd0,0x11,0x1d,0x1f,0x87,0xd4,0x98,0x18,0x58,0x23,0xcc, + 0x5a,0xe2,0xbf,0xb9,0x1f,0x50,0xf0,0x9a,0x91,0xdf,0xa3,0x2a,0x8b,0x2b,0x6e,0x71, + 0xfa,0xfa,0xfc,0x5a,0x99,0x1c,0x21,0x7e,0x32,0xcf,0xc4,0xf9,0x66,0xb1,0xac,0x64, + 0xc1,0x40,0x9,0x8c,0x98,0xbf,0xd7,0x3e,0x10,0xd1,0x74,0xa9,0xe1,0x86,0x90,0x48, + 0xb5,0xe9,0x28,0x43,0x39,0xbd,0x10,0x1e,0xbc,0x5,0xa1,0x16,0x1c,0xa4,0x39,0x8a, + 0x90,0xe7,0x40,0x62,0x4e,0x41,0x68,0x52,0xd0,0xa2,0x72,0xd7,0x58,0xe4,0xed,0x48, + 0xed,0xed,0xc0,0x1a,0xc8,0xf7,0xf2,0x7a,0xaf,0x5a,0x36,0xf3,0xbd,0xea,0xec,0x65, + 0x5b,0x8d,0xd2,0x3e,0x46,0xed,0xdb,0x48,0x2a,0xba,0xc6,0x5a,0x87,0xa8,0x80,0xcb, + 0x8e,0x51,0x98,0x33,0x0,0x4e,0xe9,0x51,0xbb,0x78,0x47,0x41,0xf,0x2a,0xc3,0x9f, + 0x4,0xc3,0xf7,0xcb,0x46,0xb7,0xc2,0x2b,0x6a,0x9f,0x26,0x1e,0x30,0x39,0x2e,0x8b, + 0x9c,0x6d,0x1e,0xf6,0x1e,0x17,0x86,0x28,0x7b,0xdb,0x4c,0xe6,0x8d,0x4c,0xff,0x6a, + 0xdc,0xef,0xad,0x2a,0x9f,0xbb,0x52,0xc0,0xb8,0xb,0x50,0xdc,0xf7,0xca,0xb1,0xd4, + 0x60,0xd8,0x15,0xb9,0x84,0x6,0xd5,0x43,0xf2,0x68,0xfe,0x97,0x1d,0x71,0x50,0xbc, + 0xab,0x94,0xb7,0x8e,0x49,0xef,0x7e,0xd0,0x45,0xb3,0xbe,0xbe,0x5b,0x98,0x23,0x10, + 0xee,0x87,0x5a,0xba,0x74,0x6f,0xc7,0x7a,0xad,0x9d,0x87,0xaa,0xbf,0x32,0xea,0xf8, + 0xb6,0x6e,0x4b,0x75,0x3a,0xab,0x13,0x6c,0x10,0x7c,0xdd,0x50,0x8,0x6a,0x7,0x72, + 0x6b,0xf1,0x86,0x9,0x2c,0x84,0x50,0x37,0x41,0xa6,0x33,0x87,0xad,0xf7,0xac,0x7c, + 0xd8,0xa0,0xee,0x23,0x10,0xc8,0xc,0x1d,0x1,0x77,0x45,0xe3,0x41,0x57,0x2a,0xd8, + 0xd6,0x7,0x27,0x3b,0xcb,0x8d,0x5c,0xce,0xbd,0xe,0xce,0xf7,0x8e,0x94,0x95,0x13, + 0x15,0x11,0xe1,0xc5,0x5b,0x90,0xb6,0x21,0xa0,0x56,0x61,0x1d,0x3b,0x6f,0xb0,0xe5, + 0xa,0x38,0x51,0x6a,0x65,0x5f,0x48,0xa8,0xb9,0xb6,0x3b,0xd0,0x92,0x43,0xe8,0xd4, + 0x39,0x28,0x52,0x4e,0x4c,0x34,0xc7,0x1d,0x2a,0xa3,0xc8,0xe3,0xe8,0xc6,0x22,0x57, + 0x49,0x84,0x2b,0x78,0x92,0x71,0x23,0xa6,0x61,0x48,0x3c,0xdc,0x7f,0x11,0xcd,0xa2, + 0xf7,0x3a,0x99,0xe,0x66,0x87,0xf0,0x31,0x1b,0x90,0x89,0x45,0x43,0x46,0xf6,0x9b, + 0x11,0x7d,0x29,0x18,0x6,0x31,0x90,0xa4,0x6c,0x84,0x59,0x5f,0xdc,0x95,0x9a,0x96, + 0x76,0x72,0xe0,0x6a,0x4f,0xee,0x70,0x61,0xce,0xef,0x44,0x9e,0x98,0x0,0x27,0x13, + 0x5a,0xdc,0x4,0x8e,0x9,0x95,0xda,0x81,0x43,0xbc,0x74,0xa3,0xf2,0x58,0x9f,0xa5, + 0x39,0x32,0xad,0xe,0x71,0x35,0x44,0x66,0xa3,0xbe,0x56,0x5a,0x72,0x36,0xd0,0x95, + 0x4e,0xf4,0x10,0xa6,0xca,0x79,0x44,0xa9,0x49,0xab,0x11,0x73,0x66,0xaa,0x5,0x7a, + 0xdd,0x4,0x94,0x16,0x79,0xdf,0x16,0x68,0x8b,0xd1,0xfd,0x4c,0xc7,0x8,0xb9,0x43, + 0xa1,0xcc,0x58,0x88,0xa1,0x49,0x4c,0x5f,0x9c,0xa8,0x16,0xc2,0x36,0x40,0xee,0x7, + 0x38,0x55,0xdb,0x4a,0xab,0x18,0xd5,0xb,0xd9,0x31,0x57,0x84,0xc,0x24,0x52,0xf9, + 0x30,0xf5,0xd6,0xe0,0xd5,0x3,0x7d,0xf7,0xe0,0x44,0x2b,0xdc,0x7d,0xa0,0x88,0xb1, + 0x77,0x39,0x83,0x32,0x76,0xa6,0x8,0xc3,0x93,0x76,0x37,0x68,0x74,0x31,0xc0,0x5f, + 0x6,0x32,0x5d,0xb1,0x13,0xe6,0x1b,0xdc,0xb0,0x79,0x87,0x2f,0xb4,0x71,0x61,0x31, + 0xb8,0x97,0x7d,0x67,0x6e,0xee,0xa8,0x8d,0xc3,0xd2,0xad,0x5f,0xdd,0xca,0x89,0xb2, + 0x23,0xde,0x2b,0xb0,0xae,0xc6,0x86,0xe,0xea,0xda,0xab,0x95,0xd1,0x65,0x10,0x21, + 0xa8,0x71,0x34,0x93,0x2d,0x66,0xbf,0x6d,0x35,0xff,0xde,0x4f,0xf0,0x3e,0x28,0x62, + 0xb,0xf7,0x66,0x77,0x59,0x6b,0x26,0x2f,0x4,0xc8,0xdb,0x83,0x28,0x3c,0xa0,0x87, + 0x19,0xbb,0xe3,0x41,0xe2,0xb5,0x1f,0x74,0xdb,0xb0,0x60,0xb7,0x38,0xd0,0x2,0xcc, + 0x4f,0xc,0x8a,0x80,0x80,0x58,0xb,0x11,0xd8,0x76,0x40,0x81,0x37,0xc4,0x7d,0xd, + 0x9a,0x3e,0x1a,0x9a,0xf5,0x7e,0x95,0xbd,0x2a,0x64,0x1d,0x83,0x62,0x7b,0x49,0xb9, + 0x57,0xb2,0x1d,0xb8,0x35,0xd2,0x52,0x6f,0x65,0xf,0xb9,0xd4,0x55,0x1a,0x1b,0x1b, + 0xe2,0x39,0x6,0xde,0xc0,0xfb,0xda,0x63,0x8d,0x3,0x5a,0x93,0xa5,0x1f,0x76,0x95, + 0xb9,0x5c,0x58,0xe0,0xa6,0x12,0xcc,0x41,0x4d,0x38,0x42,0xd1,0xd3,0xd8,0xa8,0x60, + 0x20,0x43,0xac,0x25,0x1,0x35,0x41,0xe5,0x91,0x1b,0x83,0x22,0x5d,0x11,0x9f,0x73, + 0x9c,0x4d,0xef,0x58,0xa,0x22,0xcf,0x50,0x83,0x29,0x86,0x78,0x95,0xa3,0x2b,0x19, + 0x9e,0x30,0x91,0xe8,0xaa,0x2d,0x53,0x50,0xcb,0xbd,0x74,0x5,0xb4,0x9e,0x6e,0x36, + 0x0,0x62,0xb3,0xaf,0xb3,0xd,0x9b,0xef,0x74,0xb7,0x42,0x78,0x6a,0x17,0xe0,0xa8, + 0xf8,0x68,0x34,0xe9,0x7d,0x3,0xb6,0x66,0x51,0xb8,0x55,0x24,0xc9,0xbe,0xdf,0xcd, + 0x7c,0x73,0x88,0xae,0xae,0x9a,0xc,0xc0,0xd5,0x71,0x92,0x79,0xe3,0x98,0x30,0xd7, + 0x30,0xad,0xd0,0xfb,0x3e,0x20,0x20,0x9a,0xfa,0x6b,0x88,0x56,0x41,0xe8,0x9e,0x9d, + 0x4c,0xc3,0xf1,0x18,0x45,0x69,0xe,0x97,0x5b,0x9,0x16,0x2,0x4f,0x60,0x9e,0x45, + 0x73,0x18,0x64,0x4a,0x93,0xcd,0xf8,0x0,0x81,0x13,0x1,0x6a,0x37,0x48,0x60,0x9b, + 0x71,0xc5,0x7d,0xcc,0xb4,0xf3,0xcc,0xec,0x80,0xf8,0x38,0x66,0x0,0x8f,0x59,0x16, + 0x30,0xa3,0xab,0x8d,0xf7,0xfb,0xcf,0xff,0xf9,0xa1,0x35,0x5f,0x77,0x80,0x87,0xc5, + 0x7,0x13,0xe7,0xd8,0xa2,0xdb,0xb,0x53,0x9,0xc2,0x51,0xa9,0x3a,0xb3,0x0,0xe8, + 0x14,0x73,0xba,0x2f,0x6a,0x80,0xa3,0xc2,0x39,0x46,0x59,0x35,0xe3,0x25,0x7c,0x32, + 0x6d,0x11,0xb5,0x26,0xf,0xda,0xee,0xc2,0xe1,0xb5,0xe0,0x61,0x81,0xae,0xdd,0xad, + 0xf8,0x6b,0xa1,0x77,0xf7,0x32,0xcc,0xc3,0x6c,0xae,0x3,0x82,0x8,0xdf,0x4d,0xe8, + 0x95,0x2e,0x40,0x1,0x16,0x32,0x81,0x2a,0xc3,0x69,0xfb,0x17,0x18,0x44,0x5,0x8a, + 0x2f,0x3,0x9,0x4f,0x41,0x9d,0x82,0xf8,0x3e,0x4f,0x23,0xf4,0xb0,0xf7,0xcc,0x80, + 0xa2,0x74,0xfd,0x59,0x85,0x9c,0x95,0x36,0x98,0xac,0xf7,0xa6,0xb5,0x98,0x39,0xb2, + 0x89,0xe6,0x70,0x90,0xa5,0xac,0xe7,0xdb,0xd6,0x6f,0x3d,0x8,0x60,0x5,0x43,0xd9, + 0x7c,0x3f,0x8,0x1b,0xf9,0xda,0xbd,0x9c,0xa8,0x95,0xfb,0x56,0xd,0x19,0x5b,0xa1, + 0xeb,0xff,0x65,0x33,0x14,0xb3,0x13,0xd6,0xd0,0x5c,0x8e,0x4a,0x49,0xc7,0x86,0x21, + 0xab,0x4c,0x87,0x9a,0x95,0xf9,0xf1,0xc3,0x9a,0x61,0x28,0x9d,0x9b,0xd6,0x79,0x6a, + 0x5,0xad,0x42,0xac,0x73,0xd,0x6f,0x41,0xa5,0x95,0x4c,0x68,0xaf,0x1b,0x6d,0xb1, + 0x70,0xb,0x67,0xff,0x41,0xd2,0x28,0x72,0xb5,0xdd,0x3c,0xb1,0x2f,0x21,0x17,0xd8, + 0x1d,0xb8,0x98,0x64,0x6e,0xaf,0x8f,0x1a,0x54,0xfb,0x7b,0xb0,0x13,0x7d,0xe2,0xb7, + 0xef,0xb3,0xad,0xf,0xa8,0xdd,0xdc,0x4b,0x8f,0x4d,0x27,0x9c,0x2b,0x74,0x33,0xf7, + 0x8a,0x24,0xdf,0x75,0xbe,0x36,0x6f,0x7d,0xea,0x61,0xd2,0xd2,0x12,0xa2,0xad,0xd7, + 0xdf,0xdd,0x61,0xa7,0x39,0xbb,0xb7,0x25,0xa1,0x75,0xb,0xc6,0x28,0xa2,0xd9,0xbf, + 0x77,0xa0,0x7e,0x8b,0xec,0xd,0xa1,0xde,0x92,0xc9,0x3e,0x8d,0x6e,0xbc,0x88,0x56, + 0xeb,0x57,0x84,0x5a,0x43,0xad,0xb7,0x79,0xf9,0xd0,0x40,0xdb,0x61,0x23,0x75,0x1d, + 0x7b,0x9,0x14,0xd4,0x2,0x98,0x72,0xe2,0x93,0x74,0x76,0x80,0x2f,0x96,0x82,0x13, + 0xa3,0xf3,0x6a,0x2e,0xb8,0x1e,0x78,0x4f,0xd,0x59,0x4d,0x18,0x5d,0xba,0xb8,0xe, + 0xdc,0x1,0x2b,0xd,0xe0,0xe6,0xc5,0x87,0xbb,0x53,0x75,0x54,0xad,0x22,0x40,0xbb, + 0x7c,0xfb,0xe,0x18,0x85,0xbb,0x6f,0x35,0xa9,0x6d,0xd4,0x37,0x67,0x68,0x1a,0xda, + 0x47,0x57,0x16,0x49,0x23,0x78,0x14,0xec,0xda,0xc,0xd2,0xad,0x6a,0x12,0xca,0xad, + 0xd3,0x65,0x3a,0xee,0x23,0xcf,0x70,0x87,0x4d,0xbb,0xce,0x71,0x14,0x2c,0x14,0x5a, + 0x29,0xd1,0xc3,0x3c,0xda,0x27,0x19,0x53,0x64,0xfb,0xd4,0xd,0x72,0x12,0xe4,0xc4, + 0x35,0x13,0x5e,0x6e,0xdd,0x61,0x57,0x25,0x95,0xec,0xb0,0x25,0xdc,0x60,0x27,0xb9, + 0xc0,0xcc,0x2c,0xf5,0x58,0xf5,0x1d,0x74,0xd,0xd2,0xc0,0xee,0x13,0xff,0xde,0x84, + 0x6f,0x6,0x2,0xbb,0x3c,0xa0,0xe7,0xe3,0x31,0x25,0x2a,0xa8,0xf9,0xb3,0x19,0xb4, + 0x90,0x73,0x2d,0x6d,0x44,0x44,0x99,0x42,0x77,0xe,0xae,0xa3,0xd5,0xed,0x44,0xc5, + 0x19,0x1f,0x50,0x14,0x7a,0x16,0xa8,0x61,0x1d,0xbf,0x50,0xb9,0xf2,0x90,0x79,0x9b, + 0x36,0x4a,0x64,0xbe,0x1f,0x24,0x22,0xb3,0x65,0xad,0xc0,0x58,0x68,0x96,0xe5,0xda, + 0x73,0xf2,0x80,0x40,0x87,0x93,0x29,0x1a,0x4b,0xbd,0x9a,0x64,0x90,0x2d,0x11,0x53, + 0x53,0x85,0xac,0x4,0x16,0xf9,0x95,0xe8,0x9f,0x87,0x8e,0x7c,0x11,0xca,0x47,0xaf, + 0x34,0xfa,0xc,0x9a,0x6a,0x43,0xe2,0x22,0x75,0x1d,0xf5,0x82,0xee,0xd5,0x58,0x8f, + 0xbb,0x16,0x78,0xbc,0xf8,0xe,0x24,0xf2,0xf1,0xba,0x1e,0xa7,0x80,0xe1,0x47,0x85, + 0xa6,0x24,0x63,0x2,0x42,0xea,0x19,0xc4,0xc0,0x6c,0xe9,0xec,0x9e,0x7b,0x65,0x25, + 0x5a,0xc1,0x94,0xa4,0xde,0x2e,0xb3,0x46,0x6f,0x14,0xb2,0xfe,0xc8,0x6a,0xf3,0xa0, + 0x78,0xf,0xf0,0x7b,0x67,0x76,0xef,0x45,0xba,0x39,0x4a,0x29,0x15,0xa7,0xbe,0xcf, + 0xd4,0xcb,0x89,0x3a,0x2,0x6e,0xbd,0x9c,0x32,0x4c,0xa9,0x4a,0x75,0x6c,0xe3,0xa6, + 0x35,0x44,0xc4,0x57,0x34,0xf0,0x9d,0x62,0x78,0xd,0x2c,0xe8,0xee,0x19,0x2d,0x88, + 0xa0,0x96,0xfb,0xed,0xcb,0xa2,0x91,0xfd,0xfa,0x6f,0x12,0xf8,0x9d,0x21,0x20,0x41, + 0x6a,0xaf,0x4f,0x3b,0x46,0x0,0x1c,0x58,0x32,0x56,0xb0,0xab,0x17,0x58,0x4,0x21, + 0x3a,0x30,0x30,0x83,0x43,0x46,0xd8,0xa,0x33,0xdf,0xa4,0x9b,0xcf,0x88,0xde,0xd1, + 0xbd,0x2f,0x27,0xfa,0xa0,0xb2,0x2a,0x31,0x7a,0xff,0xdd,0x5e,0xa1,0x97,0xd2,0xba, + 0xb5,0xbd,0x2,0x2c,0x55,0x13,0xb6,0x0,0xbe,0xb9,0x17,0x14,0x6c,0x55,0xfa,0xd4, + 0x5a,0x8f,0xc2,0x3b,0x68,0xe,0x6c,0x95,0x19,0x7d,0x33,0xc7,0x5d,0x2b,0x20,0xb9, + 0x19,0x5a,0x99,0x35,0x53,0xe8,0x71,0xb8,0xee,0xc8,0x5a,0xc6,0x57,0x99,0x7f,0x78, + 0x4f,0x5,0xea,0x28,0xa9,0xd0,0x60,0xbe,0xef,0x97,0x22,0x4,0x83,0xd8,0x16,0x95, + 0x51,0x6c,0xc9,0xad,0x78,0x9e,0xf3,0xf2,0xfd,0xd1,0xfb,0xcb,0x2d,0xa8,0x21,0xd1, + 0x2c,0x94,0xb1,0x42,0x2e,0x81,0x65,0xdb,0x9b,0x5f,0x5b,0xf1,0x21,0x5a,0xb0,0xb7, + 0x5a,0x8a,0xb5,0xae,0x3a,0x6a,0x58,0xde,0x23,0x7a,0xcb,0x85,0xca,0x9,0x77,0x11, + 0x7f,0xdf,0x17,0x83,0xef,0x73,0xf2,0x6d,0xa6,0x46,0x58,0xa7,0x67,0x85,0x13,0x68, + 0x4,0x14,0xbc,0x6b,0xd5,0xc2,0x12,0x87,0x99,0x73,0x8e,0xa4,0x79,0xaa,0xe8,0xac, + 0xe8,0x8d,0x12,0x5b,0xfd,0x73,0xd3,0x1e,0x4c,0x21,0x5a,0x27,0x3d,0xcd,0x7c,0x47, + 0x25,0x16,0x98,0xa9,0xc6,0xf2,0x9c,0xb1,0xef,0xef,0xd5,0xc6,0x14,0x33,0xde,0xba, + 0x40,0xf5,0x5d,0xde,0xbf,0xcd,0x7,0x4,0x28,0x15,0x6c,0x4d,0x9b,0x5e,0xad,0x6, + 0xf5,0x31,0xbb,0x1f,0x42,0xf8,0x72,0x9b,0xd4,0x5e,0x96,0x1a,0x67,0x82,0xc2,0xf7, + 0x70,0xe3,0x9d,0x38,0xc,0x33,0x43,0x28,0xd9,0x78,0x9c,0xfb,0xb8,0xe2,0xd,0x7c, + 0x50,0xea,0xba,0xd,0x29,0xdb,0x53,0x82,0x51,0x90,0x8,0x15,0xbb,0xc9,0x7c,0x6a, + 0xf0,0xc0,0xf7,0xa4,0x54,0x84,0x34,0x90,0x25,0x0,0x7,0x15,0xac,0x65,0x8c,0x2e, + 0x4a,0x72,0xce,0x5a,0x13,0x61,0xe,0xe3,0xb1,0xb2,0xa7,0x1a,0xc1,0xa8,0x9d,0xf, + 0xe2,0xec,0x2a,0x16,0xcc,0x95,0x76,0x11,0x3a,0x3b,0x88,0x28,0x7c,0xf6,0xa9,0x26, + 0xf9,0x48,0xa2,0xc3,0x65,0x9c,0x3e,0x71,0xa0,0xbd,0x6,0x4e,0x44,0x40,0x5b,0x3d, + 0x5,0xab,0xe4,0x3a,0x29,0xb0,0x17,0x2,0xe,0xb5,0x63,0xb2,0xa2,0xde,0xf7,0x33, + 0xb1,0x75,0x95,0xfb,0xef,0x38,0x81,0xc0,0x80,0x80,0x9e,0xe8,0x27,0x2c,0xea,0x48, + 0xb3,0x25,0xfd,0x5,0x62,0xe9,0xc9,0xe7,0xa5,0x47,0xf3,0x1c,0x84,0x95,0x5b,0x41, + 0x58,0x7d,0xda,0x45,0x3a,0x82,0x50,0x2a,0x7b,0xf1,0xbd,0xe6,0x6e,0x50,0xde,0x8a, + 0x5b,0xaf,0x1,0x7e,0xdb,0xed,0xa6,0x6c,0xdb,0x60,0x65,0x8f,0x40,0x8d,0x5f,0xee, + 0x7b,0xf9,0x8f,0xd0,0x29,0xf2,0xda,0x6,0x6,0x1f,0x4d,0x4e,0x72,0x9c,0xf5,0xe, + 0x99,0x7b,0x3d,0x4d,0x6b,0x92,0x73,0xc2,0xa8,0xd3,0x51,0xb1,0x5b,0xa5,0x29,0x93, + 0xa0,0xfe,0xb9,0x85,0x77,0x40,0x44,0x54,0x5a,0xac,0x22,0x43,0x24,0x73,0x8a,0x64, + 0x55,0xa3,0xbd,0x58,0x21,0x8c,0x8c,0xbb,0x98,0x14,0x79,0xac,0x68,0xba,0xcd,0xaf, + 0xbb,0x45,0xc0,0x66,0xfd,0xb6,0x27,0x5a,0x1f,0x3a,0x14,0x12,0xc5,0x65,0x9,0x3a, + 0x23,0xb2,0x51,0x83,0xfd,0x89,0x21,0xd3,0x57,0xa,0x8a,0x6f,0x6d,0x29,0xee,0x83, + 0x78,0x3,0xb0,0x2b,0xf0,0x35,0x6a,0x3c,0xbc,0x94,0x13,0x5d,0x4,0x7e,0x67,0xe2, + 0x33,0xc2,0x1e,0x92,0xe4,0xd5,0x8,0xbc,0x3,0x29,0x9d,0x35,0xd,0x7a,0x5a,0x44, + 0x68,0xd5,0x66,0x53,0x52,0xe7,0x7,0x56,0x6,0xc1,0xb0,0xf5,0x9a,0x50,0xc7,0x2, + 0x9d,0x7a,0x59,0x88,0xa2,0x15,0xa8,0x48,0x60,0xca,0x9c,0x49,0xc2,0x31,0x6d,0x62, + 0x6,0x7b,0x88,0x3e,0xa1,0x1d,0x4e,0x6e,0x45,0x15,0x81,0x87,0x6,0x7b,0x1a,0xd9, + 0x31,0xb2,0xbc,0xc7,0xb5,0x9a,0x54,0x9d,0x0,0xf9,0x79,0x55,0x58,0xc3,0xe6,0xbe, + 0x63,0x2,0x61,0xbe,0xb,0x22,0xfb,0xbe,0x5,0xbd,0x42,0x15,0xe0,0xfb,0x7f,0xef, + 0x7b,0xa4,0x17,0x3e,0xc5,0xcd,0xac,0xaa,0xce,0xf5,0xb5,0x24,0x82,0x72,0x1d,0xc3, + 0xb9,0xb7,0xbf,0x80,0x61,0x78,0x94,0x54,0x47,0xe0,0x18,0xb2,0x90,0xac,0x7e,0x19, + 0xe1,0x9c,0x21,0x1b,0x98,0x99,0xb1,0x4d,0xfc,0x28,0x8c,0x3a,0xce,0x23,0x36,0x38, + 0x53,0xb7,0x6b,0xc,0x3c,0xa9,0x73,0x11,0x65,0x4e,0xb4,0xa,0x6f,0x24,0xc9,0x98, + 0xf2,0xd4,0x99,0x2a,0xe5,0x91,0x63,0xc6,0xdc,0x5a,0x4c,0x60,0xf7,0x33,0x19,0xc7, + 0x80,0x96,0x94,0x6b,0x71,0x55,0x7d,0x53,0xa7,0x85,0xac,0xdf,0xee,0xc1,0xcf,0x98, + 0x84,0x30,0xfa,0x77,0xc2,0xac,0x4b,0x80,0x44,0x1c,0x1b,0x34,0x2c,0x6e,0xb5,0xc0, + 0x53,0xe,0xcb,0xed,0x73,0xcc,0xd1,0x65,0x93,0x44,0x2b,0x0,0x21,0x66,0xd0,0x1, + 0x31,0x68,0x80,0x74,0x11,0xd4,0x28,0x26,0x0,0x12,0x2d,0xc7,0x5b,0x7d,0x9d,0xa6, + 0x7a,0xa4,0x30,0xcf,0x6e,0x18,0x33,0xf8,0xa1,0x2c,0xae,0x68,0x56,0x1a,0x6d,0x9c, + 0xa3,0x23,0x5e,0x45,0x63,0xcb,0x8,0xa5,0x7f,0x36,0x5a,0x37,0xd,0x2a,0xa8,0x50, + 0xc0,0x7a,0xda,0x34,0xf8,0xb6,0xde,0x7f,0xaf,0xd4,0xdb,0x8e,0x4a,0xdf,0xd1,0xed, + 0x14,0x88,0xcb,0xae,0xac,0x81,0x32,0x88,0xfd,0x18,0xe1,0xba,0xbe,0xb6,0xbe,0x41, + 0xb1,0x8e,0xd0,0x66,0x5c,0xf1,0xc8,0x41,0x58,0xa0,0xb3,0x16,0x49,0x65,0x60,0x8c, + 0xa8,0x55,0x3a,0x24,0xad,0xa,0xeb,0xb4,0x77,0xf6,0x4c,0xb8,0xbb,0x65,0x3f,0xac, + 0x6,0x76,0xc1,0x79,0xaa,0xde,0xad,0x52,0xf7,0x76,0xa2,0xef,0xa0,0xaf,0xbd,0x44, + 0xdc,0x1b,0x92,0xee,0xee,0xc5,0xb1,0xf9,0xe6,0x28,0x7b,0x48,0xd9,0x87,0xba,0xee, + 0xf6,0x5f,0xb6,0xc6,0xe2,0x1b,0x5d,0x1c,0x6b,0x41,0xde,0x5b,0x1b,0xd6,0x2,0xa0, + 0xb3,0xe8,0xe3,0xa8,0x46,0x1d,0xa3,0x2a,0xe7,0x64,0x68,0x4,0x9a,0xe6,0xa4,0x41, + 0xd5,0x79,0x87,0x76,0xb3,0xaf,0x2a,0xb1,0xd6,0x93,0x9f,0x2d,0xcf,0xcd,0xc1,0xf, + 0x62,0x14,0xd4,0x89,0xbd,0x8,0x85,0x8c,0xc,0xa1,0x72,0x9d,0xfa,0xb5,0xae,0xee, + 0x10,0x5e,0x96,0x48,0x4e,0x4d,0x1e,0x57,0xaf,0x19,0x66,0xb5,0x94,0x82,0x13,0x4d, + 0x43,0xd4,0xdc,0x76,0x8c,0x9c,0xe1,0x44,0x45,0xc9,0xd,0x71,0xbf,0xae,0x33,0xdf, + 0x66,0x38,0x26,0x9c,0x2c,0x23,0x0,0x27,0x31,0x24,0x6b,0x12,0x38,0x0,0x87,0x6d, + 0x52,0xe4,0xad,0x30,0x1f,0xf7,0xbb,0x4f,0xc4,0xdb,0xb6,0x28,0xc3,0xa7,0x75,0x32, + 0x87,0x1f,0xb5,0x3c,0xd9,0x53,0x43,0x1a,0x71,0x3,0x57,0x42,0xc1,0x3a,0x62,0x7c, + 0xbb,0xc1,0x20,0x75,0xf7,0x48,0xa3,0xbc,0x74,0xdb,0x72,0xd6,0x72,0xc1,0x80,0xc5, + 0x8d,0xdc,0x15,0x4e,0x55,0x3b,0xf9,0x6e,0x6e,0xac,0x1f,0xd5,0x13,0x35,0x2b,0x2d, + 0x99,0x75,0xc3,0xe,0x9a,0xf3,0x6,0x9a,0xdb,0x69,0x9c,0xbd,0x3a,0xdf,0xa9,0x1d, + 0xd8,0xf6,0xfd,0xd2,0xe4,0xf5,0xb6,0x26,0x2b,0xbd,0x8d,0xeb,0x77,0xb2,0x73,0x35, + 0xf7,0x3a,0x25,0xa9,0x48,0xbf,0x4d,0xb,0x75,0x17,0xb8,0xae,0xf7,0xd3,0xdf,0x83, + 0x94,0xaf,0x67,0x8,0x51,0x23,0x67,0xb0,0xc2,0xe8,0xb0,0xec,0x26,0xa7,0x53,0x2, + 0x49,0xf,0x54,0x7b,0x0,0xeb,0xd5,0x8e,0xf8,0x49,0x75,0x7c,0x37,0x55,0xfb,0x82, + 0x6a,0xd7,0x32,0x9,0x4d,0xb4,0xc3,0xa1,0x9c,0xe5,0xe,0xca,0x82,0xf2,0xb8,0x91, + 0xda,0xf,0x6e,0xea,0xca,0x34,0xd8,0xd5,0x82,0xce,0x87,0x6,0x77,0x46,0xce,0x47, + 0xca,0x5a,0xc4,0x8e,0x23,0xba,0x83,0x99,0x52,0x4e,0xdb,0x52,0xf2,0xe0,0x80,0x16, + 0x55,0xc8,0x24,0x58,0xd5,0xae,0x1,0x57,0xd5,0x33,0x34,0xfc,0x8c,0x4c,0xac,0x48, + 0xd1,0x20,0x3c,0x40,0xbe,0xef,0x59,0x54,0x15,0x1,0x1c,0x41,0x48,0x65,0x86,0xa, + 0x78,0x4,0x59,0xb1,0xce,0xbe,0x49,0x12,0xc4,0x62,0x2d,0xea,0x33,0x13,0x2a,0xed, + 0xa1,0xa9,0x21,0xb3,0x33,0x38,0x32,0xc8,0x3e,0xba,0xa0,0xb1,0x9e,0x39,0xc8,0x7b, + 0x90,0x69,0x18,0x36,0xe3,0xe2,0xf1,0xb9,0x3e,0xb8,0xa1,0xc3,0xd6,0x94,0x66,0xe4, + 0xae,0xe2,0x52,0xa5,0x1d,0x6a,0xfd,0x15,0x85,0xe4,0x62,0x6a,0x10,0x39,0x51,0xf9, + 0x2a,0x2d,0xb0,0xcc,0x2,0x4f,0x6f,0x1d,0x34,0x78,0x71,0x7d,0xdc,0xa3,0x62,0x21, + 0x60,0xdc,0xde,0x60,0x76,0x8f,0xac,0xbc,0xe1,0x57,0xd9,0x4,0x3e,0x7c,0xb0,0xb6, + 0x60,0xd3,0xa7,0x3c,0x72,0xbc,0xa1,0x67,0x40,0x67,0x42,0xb7,0xf9,0x6a,0xa7,0x9e, + 0xbb,0x9d,0x30,0xaf,0x90,0x8a,0x76,0xc6,0x38,0x76,0xc8,0x70,0x29,0xad,0x44,0xd9, + 0x6c,0xdb,0xaf,0xf4,0x44,0x71,0xdb,0xb6,0x48,0xe2,0x32,0x8c,0x18,0x23,0x2a,0x54, + 0x83,0x2f,0x4f,0x80,0xab,0x42,0x18,0x83,0x1a,0xcc,0xb,0xe0,0x7b,0x2a,0x35,0xee, + 0x75,0x4b,0x91,0xac,0x6,0xa3,0xa,0xd5,0xee,0xdb,0x77,0xb0,0x0,0x8,0x70,0x48, + 0x43,0xb5,0x20,0xe6,0x24,0x6e,0x2,0x3c,0x82,0xdb,0xdc,0xe3,0x19,0x96,0xb0,0xad, + 0x1,0x4a,0xe4,0x33,0xec,0x72,0x6d,0xa9,0x47,0xef,0xd2,0xde,0x48,0x6c,0x7a,0xec, + 0x2c,0xc4,0x75,0x2,0xc5,0xb6,0xea,0x10,0x5a,0x67,0xb6,0x6,0xd8,0xe6,0xe6,0xbe, + 0x91,0x42,0x71,0x9b,0x1d,0x79,0x97,0xcb,0xa8,0x7e,0xdf,0xa0,0xa1,0x52,0xbb,0x96, + 0xa2,0x59,0xf9,0x9,0x87,0xd7,0x75,0x5d,0x7a,0xf9,0x54,0xe8,0x1e,0x87,0xf5,0xdd, + 0xd2,0xa3,0x1d,0x24,0xb9,0x9f,0x76,0x63,0xd4,0x3e,0x28,0x84,0x34,0xf,0x1a,0x73, + 0xf4,0x36,0x65,0x60,0x19,0x59,0x57,0xb5,0x11,0x72,0x67,0x64,0x5a,0x71,0x61,0xf2, + 0xf1,0x0,0xd,0x16,0x2e,0xb2,0x40,0xb3,0xdf,0xcd,0xeb,0x50,0x9f,0x6c,0x4b,0xfb, + 0xc8,0x64,0x63,0xc1,0x92,0xd2,0x3,0xfd,0x66,0x4e,0x16,0x65,0x3b,0xa0,0xae,0xf2, + 0xce,0xdd,0x6d,0xbf,0x9f,0x95,0x6e,0xe0,0x5e,0x46,0x75,0xde,0x92,0xdc,0x3a,0x81, + 0x71,0x73,0xf3,0xd,0xb6,0xa1,0xb,0xe8,0x54,0x99,0xdd,0xa,0xf8,0x6e,0xec,0x35, + 0xef,0x7d,0xcb,0x36,0xa7,0x70,0x8e,0xd9,0xaa,0x4a,0xb1,0x43,0x45,0x86,0x68,0x4c, + 0x4c,0x2c,0x63,0xbe,0x8a,0x0,0x8a,0x13,0xdf,0xb,0x48,0x52,0xa0,0x8d,0x14,0x24, + 0xa9,0xee,0x7d,0x86,0xe,0xa4,0x92,0x7f,0x5a,0xcd,0x1,0x2,0xc7,0x17,0x4,0xb2, + 0x71,0xb0,0x46,0x2,0x70,0x25,0x5d,0xa,0x31,0x70,0x67,0x29,0xbb,0x32,0x40,0xbd, + 0x5c,0xf5,0x91,0xd2,0x4e,0xea,0xf9,0x23,0x8c,0xe3,0x2d,0x3a,0x65,0xbb,0xf8,0xa1, + 0xf3,0xb0,0x39,0x29,0xa1,0xb9,0x5,0x31,0x0,0x4a,0x8,0x10,0x9c,0x7b,0x23,0xc4, + 0xde,0x7,0x8a,0x80,0x34,0xab,0x35,0xa3,0x8a,0xda,0xa4,0x36,0xb0,0x6,0x60,0xff, + 0x75,0xb,0x80,0x8b,0xa8,0x22,0x65,0x91,0xcf,0xee,0x91,0xcc,0x6e,0xea,0xe7,0xcd, + 0xf,0xb5,0x5,0xd9,0x20,0x10,0xe1,0x36,0xd,0xaa,0x23,0x89,0x88,0xb3,0x8e,0xf8, + 0x59,0xd4,0x4f,0xb3,0xc0,0xeb,0xf3,0x60,0x6f,0x35,0xed,0x20,0x90,0x9a,0x20,0xe2, + 0xa0,0x63,0x28,0xbe,0x38,0x2b,0x42,0xe,0xcd,0x6a,0x48,0x80,0xa7,0x99,0x6d,0x6b, + 0xe7,0x7a,0x6c,0x57,0x7a,0xd9,0x4b,0xce,0x32,0x2,0x79,0xb,0x3c,0x5c,0xcd,0xf4, + 0xbf,0x8f,0xd9,0xf7,0x1e,0x8f,0x8a,0x88,0x72,0x77,0x5a,0x9b,0x81,0xd2,0x51,0x88, + 0xcb,0x51,0x98,0x4a,0xf6,0x4e,0x53,0x30,0x3,0x24,0xcb,0xd3,0x42,0x50,0x25,0x6f, + 0x36,0x1e,0xb5,0x9b,0xd9,0xe0,0x2a,0x5b,0xb3,0x3c,0xeb,0x68,0x9d,0xbd,0x4a,0xd9, + 0x6c,0x77,0xeb,0x2e,0x3b,0x19,0xb,0x6e,0x9b,0x15,0x2b,0x12,0xd4,0xe1,0x6e,0xdb, + 0xb6,0x9,0xbe,0x27,0xf0,0x29,0x4c,0x6c,0x3d,0x51,0x55,0xe1,0x6d,0x4,0x91,0x2a, + 0xc9,0xe3,0x4d,0x9f,0x6c,0x0,0xe5,0x8a,0x8d,0x9,0x3a,0xbc,0x94,0x5e,0x16,0xd6, + 0x19,0xfb,0x28,0x15,0x79,0x25,0x74,0x1,0x14,0xf4,0x2a,0xc6,0xaa,0xb,0x57,0x25, + 0x2b,0x8d,0xe4,0x83,0x5b,0xbe,0x27,0x2a,0xbf,0x3e,0x24,0xd4,0xf0,0x2a,0xa,0x43, + 0xa9,0xbb,0x55,0xb0,0xa1,0x91,0x8b,0xb,0x5,0xf4,0x5a,0x65,0x87,0xe0,0xe2,0x3e, + 0x66,0xbf,0xdb,0x7e,0x9c,0xff,0xdf,0xff,0xdf,0x53,0xff,0xd7,0xfe,0x25,0xb6,0x52, + 0x99,0x7b,0x3b,0x56,0x6e,0x38,0x88,0xf9,0x68,0xcd,0x57,0xdf,0xb6,0x46,0x2e,0xa8, + 0x3f,0x2a,0xe5,0x4,0x5a,0x7c,0x77,0xb7,0xe0,0x67,0xc7,0x14,0x10,0x74,0x68,0x7b, + 0xd7,0x6f,0x6d,0x89,0xaa,0x39,0x7a,0x97,0x9d,0x6,0xeb,0x55,0x73,0x5,0xad,0x63, + 0xd4,0xdb,0xf4,0x28,0x90,0x3a,0x24,0xa8,0x29,0xb9,0x60,0x49,0x6d,0xb0,0x37,0xda, + 0x36,0x2f,0xb3,0xa9,0x3a,0x26,0x55,0x23,0x75,0x30,0x2c,0xcb,0xdb,0x7a,0x5d,0x4d, + 0x61,0xe4,0x38,0xa6,0x2e,0x27,0xa,0x2b,0xb6,0xf5,0x4,0xb6,0x39,0x22,0x75,0xf3, + 0xd1,0xb1,0x3f,0x7c,0x27,0x1f,0xd6,0xd1,0xc7,0x9,0xf7,0xce,0x0,0xd9,0xcb,0x6e, + 0x2f,0x66,0xdb,0x46,0xe7,0x6a,0x29,0x56,0xf6,0x9a,0x7d,0x7,0x99,0x60,0xc3,0xe6, + 0xb6,0xed,0x50,0xc3,0x5d,0xa9,0x8e,0x4,0x49,0x1d,0xc,0xb0,0xe0,0xde,0xa4,0xf3, + 0x34,0x4c,0x3a,0x4a,0x7e,0x60,0x4a,0x41,0xf8,0x26,0x8f,0x8c,0x23,0x37,0x1d,0x52, + 0x6a,0xf,0x57,0x4b,0x56,0xad,0xfc,0x4f,0x9a,0xc7,0xf1,0x89,0x67,0x44,0x76,0x2f, + 0x47,0x7c,0x72,0x28,0x9b,0xb4,0x9f,0x59,0xe5,0x50,0x51,0x78,0x1,0x6e,0x3f,0x8e, + 0x26,0x63,0x86,0xe,0x17,0x2e,0xaa,0x6c,0xea,0x61,0x56,0x66,0xca,0xa7,0xf6,0xe8, + 0xda,0x10,0xed,0x96,0x7c,0x2,0x97,0xc5,0x54,0xe,0x6f,0x6,0xe6,0x97,0x36,0x5d, + 0xfc,0x2c,0xb9,0x4e,0x88,0x8f,0x38,0x66,0xbc,0xee,0x80,0x4c,0xc7,0xa4,0x3d,0x2e, + 0xb3,0x92,0x80,0x43,0xc8,0xa8,0xb,0xd5,0x6f,0x9f,0x3,0xfc,0x22,0x1b,0x3a,0xd1, + 0xf2,0x2d,0x93,0xcf,0x2d,0x0,0x2f,0xba,0x54,0x64,0x0,0x33,0xe2,0x20,0xdb,0x6d, + 0x76,0xcf,0x93,0xc3,0x53,0x7b,0xaf,0xc2,0x74,0x8,0xe6,0xe3,0xef,0x6d,0x6b,0xaf, + 0xe1,0xa3,0x33,0x8c,0x7c,0x54,0x75,0xa5,0x29,0x8e,0x15,0xae,0x52,0x7a,0x85,0x2, + 0xa9,0x1a,0x9b,0xf6,0x69,0x3d,0xd8,0xd0,0x28,0x6a,0x0,0x87,0xaa,0xbd,0x22,0xea, + 0x87,0x27,0x5a,0x3c,0xad,0x94,0x55,0xaa,0xaa,0x9c,0xc0,0x49,0x3d,0xf9,0xe8,0xc8, + 0x2c,0xb4,0x2e,0x44,0xb5,0x5a,0x26,0xc9,0x88,0x62,0xca,0x4f,0x6e,0x33,0xc8,0x2, + 0xf1,0x6c,0x7,0xaa,0x40,0x9,0xba,0xe,0x7b,0xa9,0x35,0xc2,0x86,0x36,0x3d,0xaa, + 0x73,0xf3,0x9d,0x4e,0xb5,0xa1,0x66,0xc7,0x5e,0xcc,0xb1,0x95,0xcd,0xe1,0x5,0x9b, + 0x6f,0x28,0x5b,0xd9,0x36,0x6c,0x23,0x20,0x56,0xab,0xa,0xaa,0x52,0xc6,0x9a,0xf3, + 0x2e,0xb6,0xc9,0xf9,0x10,0xd1,0xd0,0xd1,0xbc,0x2b,0x1,0x2b,0xbb,0xae,0xed,0x48, + 0x88,0x0,0x14,0x6f,0xb3,0xdb,0x1a,0xf0,0xd1,0x1,0x73,0xa6,0x70,0xb8,0xe1,0x10, + 0x7,0x5,0xcb,0xe,0x7d,0x8,0x1a,0xa1,0x13,0x28,0x4b,0xb7,0xb1,0xf,0xe8,0x42, + 0x14,0x7e,0xeb,0xba,0x10,0x15,0xc8,0xdd,0xa3,0x2b,0x22,0x4f,0xd8,0x9b,0x67,0x1d, + 0xc6,0x11,0x5e,0xc8,0xdc,0xee,0xc4,0x2e,0xe5,0x33,0x8c,0x57,0x8a,0xa3,0x8c,0xa6, + 0x23,0xa9,0x17,0xf9,0x48,0x8,0x76,0x7c,0x83,0x77,0x10,0xd7,0xb0,0x76,0x55,0x80, + 0xad,0x48,0xee,0x12,0xdc,0x12,0x4,0x7a,0xeb,0xe3,0xf,0x78,0x13,0xed,0xa1,0x31, + 0x7,0x97,0xda,0xe8,0xd,0x91,0xba,0xc8,0xa5,0x4b,0xd4,0x2f,0x14,0x11,0x64,0x9e, + 0xd8,0xae,0xed,0x77,0x44,0x88,0x27,0x50,0xb,0x43,0xc7,0xe3,0xff,0xc1,0x27,0xff, + 0xdf,0x1a,0xdc,0x4a,0xec,0x82,0x98,0x5,0x61,0x22,0x2f,0xd,0x38,0xec,0xcd,0x7f, + 0xbe,0xcd,0x14,0x6a,0xc2,0xe3,0x32,0x50,0x1e,0x58,0x6e,0xb6,0x3c,0x77,0xdb,0xbc, + 0x63,0xb1,0x6b,0x5b,0xbe,0x16,0xb1,0x9b,0x63,0xdb,0x29,0xb,0x95,0xc,0xb3,0xa7, + 0x6e,0xdb,0xb6,0xd,0x98,0xa,0xc,0x27,0xbc,0xd8,0x56,0xbc,0x65,0x12,0xb0,0xb2, + 0x4b,0x3b,0x78,0x6f,0xcc,0x77,0x8c,0x9c,0x77,0x98,0xdd,0xb0,0xb7,0x6a,0xd4,0x38, + 0xe2,0xf8,0x5b,0x32,0x8b,0x89,0x78,0xa5,0x2d,0xb3,0xbc,0x10,0x63,0x4f,0xb4,0xcc, + 0x96,0xb0,0x32,0xa,0x2c,0xfc,0x37,0xff,0xe8,0xd1,0xbf,0x15,0xb8,0x3a,0x26,0x6f, + 0x32,0x99,0xe6,0xda,0xa1,0x97,0xd9,0xcf,0xa0,0x88,0x1d,0xfc,0xf9,0x1,0x24,0xfc, + 0xcf,0xf8,0xcf,0x5b,0xbd,0xf6,0x67,0xbd,0xcf,0xe4,0xde,0xfc,0x57,0xbf,0x47,0xd4, + 0xd2,0x85,0x5b,0x50,0xd6,0x9a,0xfc,0x46,0x74,0x2e,0xb3,0x9,0x35,0xcc,0x7f,0xd6, + 0x5,0xaa,0x2d,0x69,0x7,0x0,0x5,0xed,0x26,0x34,0xfc,0x80,0x33,0xf8,0xc2,0x63, + 0xf,0x52,0xbd,0xa6,0x5d,0xd5,0x14,0x20,0xa2,0x8b,0xa1,0x23,0x80,0x6c,0x30,0x2, + 0x12,0x2b,0x99,0xad,0x15,0xc8,0x7e,0x46,0x66,0x4d,0xf4,0xb4,0xd7,0x7b,0xd2,0x34, + 0x0,0x63,0xde,0xa0,0xc3,0xd,0x64,0xd6,0x51,0xe5,0xad,0x32,0x71,0xaa,0xd6,0x4b, + 0xaf,0x6,0x4b,0xab,0x19,0xe1,0xf0,0x1d,0x0,0xe7,0x90,0x0,0xdf,0x18,0x3a,0x52, + 0xdd,0xf,0xe6,0x4e,0xb,0x36,0xac,0xd2,0x2d,0x82,0xd1,0x46,0x28,0xf8,0x19,0x19, + 0x92,0x51,0xee,0x2e,0x55,0x8f,0x49,0x26,0x3f,0x4c,0x42,0x9c,0xee,0x15,0x93,0x48, + 0x9c,0x1c,0xa2,0x6d,0xc0,0xe1,0xba,0x4d,0xb4,0x6f,0xd6,0x7e,0xd6,0x2a,0xf6,0x6d, + 0xdb,0x6a,0x65,0xb8,0xd5,0x8e,0xe4,0x66,0xe6,0xbe,0x6d,0xbe,0xb5,0x36,0xe5,0xd6, + 0x10,0xf0,0xed,0x37,0x6d,0x22,0xb1,0x68,0xd,0xe8,0xdd,0xee,0xfb,0x1e,0xbd,0x5b, + 0x90,0xae,0x8e,0x6d,0xc0,0x89,0xee,0x23,0xdb,0x12,0xa4,0x32,0x2,0xd,0x55,0xe9, + 0xc6,0x4e,0xde,0xb0,0xcc,0x58,0x84,0x26,0x39,0x6e,0x41,0xd,0xf2,0x2d,0x78,0xbd, + 0x62,0xc4,0x8a,0xe4,0x34,0xcf,0xaf,0xdd,0x7c,0xf3,0x43,0xc2,0x98,0xf9,0xbf,0x87, + 0x6d,0x67,0xbd,0xc1,0xcd,0xcb,0xad,0x8f,0x69,0xf7,0xc4,0xab,0xcd,0xb6,0x36,0x6f, + 0xda,0xc7,0x9b,0x99,0xa3,0x75,0x5e,0x88,0x3f,0xed,0xdc,0x6d,0xe0,0xeb,0x6b,0x3e, + 0x6a,0xcd,0xc,0x97,0x1,0x84,0x3d,0x68,0x43,0xfe,0xcc,0x63,0xe,0x1f,0xa6,0x34, + 0x0,0x71,0x9,0x82,0x91,0xb,0xdd,0xa6,0xa1,0x68,0x42,0x96,0x40,0x63,0xdd,0x4e, + 0xe8,0xad,0x9,0x67,0xd,0x8b,0x34,0x9b,0x4e,0xe2,0x4f,0xd6,0x3a,0x54,0xc,0xba, + 0x8f,0x9c,0xb1,0xb7,0xdd,0x37,0x8f,0x39,0xbf,0x6a,0xf0,0xf4,0x1,0x48,0x4d,0xaa, + 0xf6,0x40,0xee,0xbd,0x4d,0x53,0x81,0x71,0xa8,0x50,0xb8,0x5d,0x79,0xbf,0x22,0xde, + 0x6b,0x30,0x87,0xfb,0x56,0x47,0x35,0x6e,0xbe,0x6d,0xde,0x22,0x77,0x87,0x99,0x56, + 0x2b,0xbc,0x7d,0x6f,0x39,0x41,0x24,0xab,0x54,0xe0,0xc0,0x5d,0x30,0x8e,0x23,0x58, + 0x62,0xea,0x29,0x8b,0x9f,0x15,0xfd,0xec,0xb0,0x3c,0x3e,0xe,0xd8,0x89,0xd3,0xeb, + 0x4f,0x6a,0x73,0xdf,0x26,0xcd,0x81,0xb9,0x7c,0x0,0xfa,0xc2,0xc6,0xb0,0xfd,0x94, + 0x0,0x54,0x2c,0x9a,0xb3,0xab,0xcc,0x17,0x68,0xc,0x62,0xa2,0xfd,0x1e,0xb7,0x6a, + 0x34,0xe,0x61,0x7a,0x57,0x6a,0x67,0x90,0x95,0x68,0xa4,0xa6,0x25,0x85,0xb2,0x4e, + 0xa7,0x1a,0x5e,0xef,0xc3,0xba,0xd3,0x6d,0xb8,0x2b,0x77,0x51,0x8a,0xa4,0xcd,0xdb, + 0x25,0xb6,0xe4,0x43,0x6c,0xfe,0xb3,0xe0,0xb2,0xcb,0xdc,0x7a,0xe1,0xf8,0xcb,0x9c, + 0x1,0x42,0x53,0xeb,0x78,0x67,0xfc,0xff,0xdc,0xbd,0x57,0x93,0x65,0x57,0x76,0x26, + 0xf6,0xad,0x7d,0x6d,0x7a,0x6f,0x2b,0xb3,0xbc,0x41,0xa1,0x50,0x28,0xb8,0x46,0x77, + 0xb3,0xd9,0x6c,0xb2,0x87,0x43,0xce,0xc,0x29,0xf2,0x41,0x13,0x13,0xa,0xc5,0x88, + 0x8a,0xd0,0x1f,0xd3,0x8b,0xa4,0x27,0x29,0x82,0x31,0x33,0x9a,0xa1,0x46,0x24,0x41, + 0xb6,0x41,0x37,0xba,0xe1,0xb,0x28,0xa0,0x50,0xde,0x64,0x65,0x56,0x7a,0x9f,0x37, + 0x6f,0xde,0xbb,0x97,0x1e,0xb6,0x5b,0x6b,0x9f,0x73,0xab,0x6a,0x28,0x2a,0x44,0xa9, + 0x9a,0x20,0x50,0x69,0xaf,0x39,0x67,0xaf,0xb5,0xbe,0xf5,0x19,0xb9,0x77,0xca,0x2f, + 0x4,0x2e,0xa6,0x9f,0x49,0x7,0x22,0x96,0x8c,0xf7,0x0,0x50,0x65,0x47,0x5e,0x26, + 0x29,0x94,0x31,0xab,0x9c,0x67,0x97,0x9,0x84,0x84,0xb3,0x2e,0x92,0x4a,0x2e,0x50, + 0x12,0x21,0x50,0xc9,0x5b,0x40,0x1e,0x20,0x1,0x99,0x10,0x6c,0x5b,0x32,0xb2,0x7e, + 0x53,0x8,0x6,0xf1,0xda,0xdd,0x50,0x53,0xa4,0x2c,0x8a,0xa2,0x5d,0xbc,0x43,0x2a, + 0xd,0xe0,0x25,0x69,0x26,0x1d,0x86,0x52,0x1b,0x1d,0x89,0x6e,0xfe,0x63,0xb2,0x88, + 0x23,0x70,0xc0,0x14,0xf5,0x21,0xce,0xa9,0x24,0x24,0x82,0x84,0xac,0x68,0xeb,0xe0, + 0x5e,0x7d,0x55,0xe7,0x69,0x74,0x25,0xb1,0xc3,0x69,0x7b,0x93,0xf2,0xe3,0x52,0x7a, + 0xb7,0x97,0xdf,0x92,0x31,0x6e,0x1e,0x8f,0x8c,0x5e,0x62,0xb0,0xb5,0x30,0xc6,0x90, + 0x65,0x47,0x73,0xb7,0xe,0x76,0x87,0x25,0x4b,0xc6,0x1a,0x37,0xc9,0xfb,0xad,0xa0, + 0x85,0x38,0xbb,0x93,0x5e,0x85,0xf5,0x1e,0x2e,0x41,0xba,0x62,0xd2,0xf6,0x53,0xa0, + 0xf1,0x20,0xbb,0x2e,0xe2,0x20,0x22,0x27,0xeb,0xa,0xce,0x35,0x8a,0xad,0xcd,0x5a, + 0xbc,0x40,0xf9,0xe9,0xa5,0x73,0xd7,0x19,0x65,0x9e,0x49,0x62,0x85,0xc9,0x85,0x8, + 0x7a,0x81,0xf7,0xc9,0x38,0xe1,0x60,0x14,0x12,0xdc,0xd7,0xc8,0x67,0xdb,0xca,0xdb, + 0x3c,0xd1,0x54,0x7c,0xb,0x1a,0x93,0x44,0xd9,0x73,0xbc,0xe2,0x94,0xc6,0x89,0x79, + 0x1f,0x62,0x68,0xc1,0xc,0xc3,0x61,0xaf,0xe7,0x49,0x70,0x4c,0x4c,0xb0,0xc6,0xb7, + 0xc7,0x36,0x1a,0x47,0xab,0xa0,0xb2,0xc0,0x9d,0xe4,0xa4,0xfa,0x4b,0x45,0x5b,0x15, + 0x75,0x7f,0x3d,0xeb,0xe9,0x3d,0xd,0xd9,0x46,0x70,0x3f,0xbc,0x87,0x42,0x72,0x8a, + 0x8b,0x7c,0x8f,0xa4,0x54,0x4b,0xd6,0x9,0x5,0x57,0x34,0x12,0xef,0x91,0x5a,0x23, + 0x96,0x8e,0x3d,0x2,0x39,0x4c,0xf6,0xb4,0xe9,0x5c,0x62,0x41,0x5f,0xca,0x56,0x53, + 0x2e,0x56,0xce,0x72,0x4a,0x48,0x4c,0x9e,0x74,0x2a,0xa8,0x85,0xa2,0xa5,0xb1,0x3, + 0xef,0x2a,0x14,0xb4,0xff,0xae,0x39,0xd,0xc1,0x96,0xe,0x35,0xb7,0x3e,0x68,0xcf, + 0xad,0xa4,0x9c,0x9b,0xa2,0xf5,0x80,0x83,0x2f,0xf6,0xc6,0x90,0xb1,0xd6,0xf1,0xd, + 0xac,0xfb,0x66,0x1b,0x6d,0x8a,0x3d,0x49,0xcd,0xb2,0x32,0x90,0x88,0xfc,0x3f,0xce, + 0x82,0xad,0x38,0x1b,0xbe,0xf2,0x11,0xa7,0xc4,0x25,0x54,0x22,0x1e,0x85,0xf5,0x2e, + 0x65,0x2c,0x77,0x14,0xb8,0x6a,0xe1,0xa3,0x55,0xc5,0x20,0x16,0x1d,0x96,0xb6,0xa5, + 0xcb,0x8b,0x9d,0x88,0x2b,0x14,0x93,0x45,0x64,0x30,0xb2,0x94,0xe8,0x72,0x26,0x5f, + 0x82,0x28,0x94,0x50,0x52,0x2f,0xd9,0xa9,0x92,0x0,0x76,0x24,0x43,0x2e,0xad,0x71, + 0x29,0x8b,0xeb,0x2c,0x81,0xa9,0x59,0x13,0x36,0x62,0xfc,0x6a,0xee,0x8f,0xce,0x89, + 0xb5,0x42,0x99,0x8c,0x4f,0x5a,0x4a,0x32,0x93,0x2e,0x76,0x4c,0x2a,0x66,0xb5,0x90, + 0xf1,0xa0,0x62,0x9e,0x50,0x94,0x2a,0xb0,0x8e,0x17,0x55,0xb7,0x4,0x4b,0xd2,0xa1, + 0x8e,0x41,0x95,0xae,0x52,0x4a,0x2,0x58,0x6,0x69,0x53,0x81,0xc3,0x22,0x1a,0x3, + 0x48,0x43,0xb0,0xe0,0xab,0x5d,0x70,0x9a,0xcb,0xed,0x4a,0xb,0x6b,0x1,0x59,0xb9, + 0xb,0x96,0xb8,0x8a,0x66,0x9c,0x41,0x4b,0xc8,0xa8,0x86,0x5a,0xbc,0x29,0x5d,0xc2, + 0x3,0xf1,0x9b,0x38,0x4d,0xe2,0x9a,0x51,0x1d,0x90,0x34,0x23,0xd,0x4e,0x8c,0x9b, + 0xca,0x3d,0x6b,0xdd,0x90,0x98,0x1e,0xd,0x9,0xca,0x9b,0x82,0x2b,0x4d,0x74,0xaf, + 0x8e,0x9,0xea,0x59,0xcc,0xb7,0x1c,0xa2,0x4c,0x6c,0x3d,0x48,0xb8,0x70,0x15,0xf6, + 0x5c,0x52,0x7e,0xa7,0x1a,0x5c,0x22,0xa8,0x0,0x9b,0x78,0x73,0x73,0x16,0xbd,0xe3, + 0xea,0x87,0xf1,0x66,0x6a,0x41,0x9e,0x61,0x39,0x1c,0xce,0x7e,0x42,0x71,0x8b,0xf1, + 0x60,0x78,0xc2,0xd6,0x5a,0x97,0x46,0x63,0x63,0x31,0x67,0xc3,0x86,0xac,0xb1,0x54, + 0x61,0xc3,0x5d,0xb6,0xfe,0x50,0x7,0xdb,0x24,0xc9,0x11,0xeb,0xfd,0x94,0xd1,0x96, + 0xd2,0xeb,0x5c,0xc0,0x97,0x13,0xeb,0x6,0x35,0xa0,0x49,0x6b,0x8e,0xf0,0xdf,0x10, + 0x53,0xa4,0x27,0xcb,0xb1,0xe0,0x39,0x8,0xd,0x60,0xb8,0x2e,0x83,0x5e,0x5a,0x25, + 0x56,0x19,0xa9,0x81,0xf7,0xa8,0x5,0x17,0xc5,0x23,0xa4,0x5d,0xa7,0x75,0x39,0x12, + 0x93,0x76,0xa,0x14,0x37,0x24,0x82,0xf7,0x14,0xbf,0x37,0x5e,0xa9,0x96,0x39,0xba, + 0xe3,0x31,0x87,0x2c,0x4e,0x4,0x21,0x9d,0x9f,0xba,0x39,0xaa,0xe9,0x4c,0x1c,0xb9, + 0x1d,0x9b,0xda,0x23,0x2b,0xde,0x7e,0xcc,0x6f,0x85,0x82,0x31,0x5d,0x85,0x51,0xda, + 0xf0,0x42,0x48,0x36,0xa2,0xc7,0x82,0x54,0xee,0x8b,0x6b,0x35,0x9a,0x94,0x27,0xe, + 0x48,0x62,0x4,0x93,0x1a,0x8b,0x8d,0x34,0xfc,0x91,0x9,0x78,0xfe,0x99,0x47,0xc3, + 0x24,0x39,0x57,0x68,0x62,0x1c,0x9,0xdb,0xb2,0x5,0x30,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x2e,0x8e,0x2e,0x30,0x6,0x8c,0x12,0x63,0xb2,0x2,0xb1,0x52,0x1e, + 0xde,0xc,0x42,0x9e,0xb4,0xe3,0x33,0xdf,0x99,0x59,0x6b,0xe8,0xc2,0xee,0x5c,0x7a, + 0x27,0x4a,0xd0,0x3b,0xf4,0xfc,0xce,0x5a,0x6,0x6c,0x9d,0x9b,0x13,0x5b,0xb0,0x71, + 0xdd,0x2e,0x79,0x1a,0x1e,0x1b,0xb6,0x81,0x8a,0xe7,0x78,0x71,0x64,0x18,0xb0,0x2e, + 0x63,0xd6,0x5a,0x9f,0x77,0x10,0x7b,0x83,0x40,0x8,0xb4,0x30,0x91,0xdf,0x42,0x86, + 0x9,0x36,0xfa,0xb8,0x89,0x22,0xca,0xc5,0x1c,0xd,0x4a,0xb1,0xef,0x2a,0x8e,0x54, + 0x4c,0xed,0x12,0x19,0xd1,0x88,0xb9,0x8c,0x22,0x12,0xbe,0xee,0x3d,0x12,0x19,0xab, + 0x6a,0x12,0x96,0xf2,0x2f,0x41,0xe3,0xe5,0x3c,0x53,0xa2,0x68,0x33,0x20,0x26,0x41, + 0xca,0x5c,0xe3,0x92,0xa9,0x48,0x28,0x52,0xac,0x9c,0xc,0xa5,0x79,0x85,0xce,0xb4, + 0xa6,0x12,0x8c,0x82,0x45,0x1a,0x5a,0xa1,0x88,0xaa,0x41,0x95,0xa,0x8f,0x31,0x25, + 0xa5,0x91,0x92,0x50,0xa9,0x59,0x9f,0x50,0x42,0x6a,0xcb,0xed,0x38,0x49,0x91,0x1a, + 0x48,0xb1,0x70,0xc5,0xe3,0xc8,0xd7,0xfa,0x59,0x71,0xcc,0xa1,0x2b,0x95,0xca,0x46, + 0x42,0xd3,0x8,0xcd,0xf0,0xcd,0x19,0xfd,0xb1,0x83,0x93,0x64,0x43,0x82,0xea,0xf8, + 0xa4,0x46,0x94,0x95,0xb2,0x90,0x54,0x48,0x69,0x9e,0x16,0x9f,0x90,0x71,0x16,0xc1, + 0x89,0xa4,0xfd,0x21,0x62,0x7a,0x9a,0x30,0xad,0x1,0x84,0xa7,0x1d,0x15,0x1b,0x4f, + 0x79,0x51,0x46,0x0,0x24,0x4c,0xad,0x26,0xcd,0xaa,0x26,0x18,0xbe,0x80,0x54,0x52, + 0x14,0x19,0x17,0x17,0x96,0x12,0xca,0xd3,0x7e,0xdc,0xc0,0x78,0x6b,0xca,0x50,0x67, + 0x8c,0x80,0xd7,0x8d,0x84,0x2d,0x93,0x5c,0x8d,0xc5,0x64,0x2f,0x9c,0xe2,0x98,0x44, + 0x9,0xcf,0xec,0x9b,0x2a,0x81,0xd6,0x6e,0x44,0x6e,0x2d,0xe9,0x8e,0x4,0x99,0x6b, + 0x6c,0x4a,0x9d,0x12,0x7b,0x72,0xe3,0x53,0x2a,0x39,0x4e,0x32,0x14,0x36,0xb0,0x19, + 0x9b,0x84,0x92,0xd9,0x95,0xfb,0xa2,0x4a,0x16,0x76,0xea,0xcc,0x71,0xbc,0x14,0x17, + 0x96,0xc8,0x18,0xb,0xb6,0x44,0xc6,0xc0,0x5a,0xcb,0x15,0x18,0xb2,0xb0,0x5c,0x71, + 0x13,0x3b,0x55,0xfc,0xe4,0x2,0x58,0x17,0xf4,0x92,0x3c,0xb8,0x62,0x1d,0xd0,0x16, + 0xba,0x61,0x29,0x1e,0x21,0xf5,0x88,0x74,0x50,0x20,0xc2,0x85,0xa2,0x1e,0x9d,0xcb, + 0xc4,0xe,0x38,0xed,0x78,0x43,0x2e,0x8,0x47,0x66,0x5d,0xa2,0x2e,0xe6,0xe1,0x41, + 0x10,0x53,0x21,0xf5,0xc8,0xec,0x96,0xdc,0x1c,0x62,0xe6,0x7c,0xdd,0x95,0x1c,0xf0, + 0xb2,0xce,0x58,0x85,0x73,0x8b,0xbb,0x3f,0xe8,0x8f,0xa1,0x9c,0xd6,0x15,0x31,0xb, + 0x54,0xa1,0x94,0x97,0xce,0x9c,0x86,0x78,0xe2,0x64,0x6c,0xc9,0x1c,0xe3,0x49,0xe2, + 0x5e,0x3d,0xc4,0xf0,0x70,0xf4,0x79,0x29,0x18,0x4d,0x19,0x3f,0xd8,0xfb,0x3f,0xd1, + 0xf6,0x47,0x9a,0xc8,0x70,0x6c,0xa8,0x28,0xb1,0x6a,0x3d,0xe8,0x1e,0x7d,0x64,0x15, + 0xa1,0x7,0x29,0xf2,0x37,0x97,0x94,0x90,0x3e,0xd,0x24,0x1d,0x5d,0x5c,0x87,0x46, + 0x2e,0x43,0x24,0x5,0x86,0xa9,0x98,0x82,0x87,0x92,0xb9,0x2d,0x1a,0x5d,0xa9,0x45, + 0x15,0x47,0xec,0xc3,0x37,0xef,0x6e,0x60,0xf2,0x84,0x83,0x18,0x6b,0x1e,0x3e,0x27, + 0x34,0xc7,0x1e,0x46,0xf2,0xdb,0x6c,0xef,0xe7,0x66,0x1c,0x28,0x6e,0x5d,0x88,0x30, + 0x47,0x75,0x1a,0x59,0x43,0xce,0x2d,0x82,0x2d,0xfb,0xc9,0xdd,0x5a,0xc3,0x64,0xac, + 0x6f,0x7e,0xfd,0x7f,0x44,0x67,0x15,0xf6,0x6c,0x3,0xb2,0x4,0x76,0xe1,0x2d,0x49, + 0x44,0x6f,0xe0,0x34,0x6d,0x59,0x6c,0x2a,0xb2,0xa0,0x4e,0x1d,0x7b,0x6a,0x44,0xda, + 0x67,0x40,0x29,0x53,0xf2,0x27,0x17,0xec,0xc6,0x8d,0xa,0xd,0xcb,0xcd,0x64,0x64, + 0xe1,0xab,0x7a,0x2f,0x6b,0x5,0xc8,0x73,0xb1,0xbf,0x85,0xf6,0x9c,0xa6,0x12,0xf0, + 0x30,0x9f,0xc2,0xf5,0x25,0x20,0xf7,0x82,0x44,0x65,0x20,0xbe,0x28,0xfe,0x12,0x1e, + 0xb,0x14,0x27,0x96,0xbb,0x45,0xe9,0xf9,0x1d,0x8d,0x26,0x74,0x3e,0xbb,0x60,0xc1, + 0x72,0xa9,0x30,0x48,0x96,0x2e,0x4d,0x0,0x54,0x12,0xac,0x60,0x91,0x59,0x8,0x17, + 0x65,0x25,0xd5,0x2b,0x48,0xcb,0xfd,0x89,0x18,0xe1,0x3c,0x41,0x2a,0x94,0x6,0x2, + 0x54,0x80,0xcc,0xb9,0xd0,0xdc,0xe6,0x1b,0x11,0x69,0xd,0xab,0xf2,0xaa,0x73,0xde, + 0x1f,0x53,0x26,0x45,0xcb,0x3d,0x2c,0x58,0xaf,0x82,0x5,0x64,0x4f,0x65,0xa9,0x9f, + 0xa9,0xa7,0xd6,0x8d,0x91,0x42,0x74,0xa8,0xf0,0xfb,0xf3,0x8f,0x43,0xeb,0xd4,0x3, + 0x66,0x9e,0xc9,0x24,0x29,0x42,0x13,0xd1,0xd8,0x42,0x44,0x4a,0x31,0xa5,0xa2,0x62, + 0x42,0xa1,0xa9,0x78,0xa8,0x17,0x1e,0x62,0x67,0x31,0x9,0x9a,0x30,0x4d,0x82,0x9c, + 0x92,0x2b,0xd,0x9d,0xb1,0xc0,0x44,0x83,0x93,0x64,0x4e,0x23,0x22,0xfd,0x48,0x1d, + 0x73,0x9c,0xa4,0x5c,0x7a,0xfb,0x2b,0x15,0x6b,0xd0,0xfa,0x14,0x2a,0x7b,0x43,0x93, + 0x13,0xa6,0x58,0x6d,0xa,0x29,0xb5,0x96,0x53,0x3a,0x68,0xdc,0x89,0x77,0x48,0xa, + 0x5d,0xc8,0xb8,0x4d,0xad,0x63,0x61,0x87,0x43,0xd4,0xc0,0x90,0x35,0x6c,0xd,0x33, + 0x5b,0x9f,0xd6,0x61,0x3,0xd3,0xcd,0x11,0x83,0x8d,0x73,0xaf,0x6,0x99,0xb8,0x23, + 0x8e,0x7,0xe,0x67,0x90,0xa8,0x44,0x34,0x8c,0xfb,0xe9,0x9e,0x83,0xe0,0xac,0x50, + 0x4c,0x20,0xca,0x19,0x5f,0x70,0x8c,0x37,0x46,0x75,0xd0,0xba,0x49,0xc4,0x42,0x48, + 0x81,0xa0,0x84,0x89,0x88,0xa9,0x40,0x95,0xa6,0x12,0x9f,0xa,0x69,0x7a,0x63,0xa0, + 0xd7,0x53,0xd1,0x57,0x5f,0xee,0x73,0x49,0x99,0x21,0x82,0xb2,0x3,0x33,0x69,0x14, + 0xa3,0xc2,0x9,0x49,0xff,0x15,0xdc,0xd9,0xfd,0xdd,0x69,0x39,0x41,0x19,0xde,0xdc, + 0xc4,0xe9,0xcf,0x53,0xec,0x3c,0xac,0xdb,0x7f,0xc4,0xcb,0x3f,0xb4,0xab,0x96,0x61, + 0x29,0x11,0xb7,0xa4,0x2d,0x9f,0x5a,0x45,0x47,0x83,0x43,0x8,0x4,0x9,0x52,0xcb, + 0x1f,0x5e,0xfb,0x24,0x1,0x34,0x82,0x89,0xec,0x7d,0x16,0x90,0xf2,0xe6,0xa5,0x90, + 0x33,0xdb,0x90,0xaa,0xc3,0xa1,0x10,0xf7,0xc9,0xca,0x26,0x41,0x17,0x96,0x92,0x1f, + 0x94,0x1c,0x24,0x4b,0xe8,0x40,0x72,0x98,0x48,0xe2,0x9,0xff,0x42,0xfa,0x52,0x47, + 0xe9,0x4c,0x65,0x36,0xa4,0xd5,0xc3,0xe1,0x9d,0x10,0x42,0x29,0xf8,0x32,0x1e,0xb0, + 0x1b,0xf2,0xc4,0x3,0xb,0x76,0x3a,0x42,0x30,0xac,0xe3,0x91,0xa0,0x52,0x31,0x60, + 0xeb,0x60,0x78,0x3,0xc3,0xcc,0xd6,0x38,0x13,0x78,0xeb,0x24,0x21,0x6c,0xd9,0x54, + 0xc,0x71,0xd7,0x32,0x3b,0x64,0x8b,0xd9,0x80,0x6d,0x97,0x25,0x7f,0x28,0x66,0x14, + 0xd8,0x8,0xdb,0x38,0x4f,0x7d,0x66,0x56,0x83,0x19,0x4b,0x70,0x22,0x3f,0xe,0x8a, + 0xe,0x9c,0x72,0x6d,0x2c,0xd3,0xe7,0x19,0x25,0x96,0xe1,0x1,0x4d,0xf,0x88,0xad, + 0x83,0xdc,0xa9,0x64,0xd8,0xce,0xfd,0x4e,0x73,0x2,0xbd,0x74,0x30,0x84,0x12,0xa9, + 0xc5,0x6c,0xf5,0xe0,0x85,0x2f,0x4d,0xea,0xa3,0xee,0x18,0x5,0xe8,0x95,0xe5,0x3e, + 0x3b,0x3c,0xd,0xca,0x25,0x68,0x61,0xda,0xc,0x92,0x63,0x4e,0xba,0x39,0x25,0x9f, + 0x52,0xa8,0x8e,0x9a,0xe8,0x59,0x16,0xe2,0x78,0x55,0xe5,0x4e,0x13,0x9c,0x3d,0x67, + 0x2a,0xc9,0x9a,0x21,0x5,0xfd,0x13,0x6b,0xb8,0x4c,0xa5,0xac,0x11,0x21,0x6f,0xab, + 0xd4,0xb4,0xaf,0x20,0xf3,0x92,0x73,0x94,0x35,0xc2,0x50,0x64,0xb1,0xf7,0x78,0xff, + 0xa8,0x7,0xcb,0x9d,0xf3,0x5b,0xb9,0x24,0x20,0x84,0xca,0x7f,0x34,0x65,0xe6,0x8, + 0x79,0x85,0x22,0xe2,0xd2,0x6f,0xa4,0x3c,0x32,0x54,0x7e,0x5c,0x66,0xfb,0x92,0x3e, + 0x3c,0xc,0xc9,0xa8,0xc8,0xc4,0x56,0x4f,0x93,0x75,0x5c,0xad,0x9b,0x0,0x3d,0x86, + 0x7d,0x39,0x2a,0xf0,0x53,0xa2,0xf1,0x93,0x24,0x49,0xc3,0x13,0xa3,0xc,0x50,0xa0, + 0x8b,0x77,0x94,0x9,0x49,0x67,0x13,0x32,0x89,0x84,0x10,0xa7,0x18,0x13,0xfd,0xff, + 0x28,0x9f,0x7a,0x44,0x6,0x78,0x28,0xde,0xfd,0xfd,0x75,0xc,0xf6,0x35,0xa8,0xaf, + 0xaf,0x8e,0x81,0x46,0x1d,0x7d,0x8d,0x3a,0x9a,0x8d,0x1a,0xfa,0xfb,0xea,0xd4,0xdf, + 0xa8,0xa3,0x5a,0x21,0xe7,0x94,0x49,0x40,0xb7,0x6b,0xd1,0xe9,0x58,0xde,0xd9,0x3f, + 0xc2,0xfa,0xf6,0x1,0x9e,0xad,0x6e,0xf3,0xd6,0xfe,0x41,0x8a,0x41,0x2d,0xb8,0x2a, + 0xf8,0xa9,0xc4,0x58,0xeb,0x4f,0x78,0x30,0xac,0x1,0x19,0xeb,0x42,0xac,0xfc,0x4e, + 0xde,0x1a,0xa7,0xde,0x21,0x72,0x7b,0x75,0xef,0xa9,0xe0,0xea,0x50,0xb2,0xa8,0x55, + 0x4f,0x23,0x4c,0xe5,0x50,0x70,0x79,0xdc,0x9c,0x7,0x85,0x94,0xc0,0x3e,0x4c,0x80, + 0xe6,0xc3,0xae,0xdd,0x19,0x72,0x27,0x12,0x63,0x61,0x8d,0x98,0xf6,0xbc,0xd2,0x6e, + 0xc0,0xf9,0x7f,0x19,0x21,0x22,0x14,0x10,0x3a,0xe7,0x13,0x8b,0xca,0xd9,0xcc,0xec, + 0x85,0x49,0xeb,0xa2,0xd4,0xdd,0xc0,0x19,0x1a,0xe9,0x5d,0x5,0x38,0xed,0xb0,0x23, + 0xd3,0xd9,0x23,0x45,0x69,0x92,0xf0,0xaa,0xac,0x90,0xe0,0xed,0x3f,0x48,0x29,0x93, + 0x1e,0x6c,0x10,0x7c,0xca,0x8c,0x33,0xed,0x4b,0x1c,0xc7,0x18,0xc,0x28,0x91,0xb2, + 0xf8,0x7a,0x50,0xa2,0xb8,0x9a,0xa0,0xe5,0xf,0x13,0x7a,0x82,0x22,0x3,0x0,0x4f, + 0x1e,0x6b,0xf0,0xea,0x83,0x84,0x5,0x7a,0x34,0x2b,0xd3,0xb9,0xb0,0xc4,0xf1,0xc1, + 0x0,0x6a,0xb5,0xa,0x6,0x9b,0x75,0x34,0x1b,0x75,0x6a,0x36,0x6a,0xe8,0xab,0xd7, + 0xd0,0xa8,0x55,0xd1,0xec,0xab,0xa3,0x5e,0xad,0x50,0xad,0x6a,0x50,0x31,0x6,0xc6, + 0xb8,0x7f,0x93,0x21,0xd4,0x8c,0x47,0x98,0x1c,0xd5,0xc,0x96,0x2d,0x6c,0xf0,0xc7, + 0xb0,0x8c,0x2e,0x5b,0x74,0xba,0x8c,0x4e,0xa7,0x8b,0x93,0x4e,0x17,0xed,0x93,0xe, + 0x77,0x3a,0x16,0x27,0xdd,0xe,0xda,0xed,0x2e,0xb5,0x3a,0x1d,0xb4,0x5a,0x27,0x38, + 0x68,0x1d,0x73,0xeb,0xf8,0x4,0xdd,0x2e,0xcb,0xa6,0x2a,0x1a,0x1a,0x71,0xcc,0xe9, + 0xc8,0x38,0x56,0x24,0xc2,0xc3,0x4c,0x60,0xff,0xb9,0xcb,0x1a,0x20,0x22,0xb,0xeb, + 0xd4,0xf,0xd6,0x13,0xfb,0xd,0x93,0x89,0xec,0x45,0xb8,0xd9,0xdb,0x7a,0xd8,0x9d, + 0x45,0xbc,0x97,0x5,0xd8,0x90,0x31,0xc,0x8b,0xb0,0xd7,0x8a,0xc2,0x37,0x90,0xcc, + 0x2e,0x15,0x39,0x2,0x3a,0xd,0x56,0x57,0x3c,0xbd,0x88,0x83,0x34,0x9c,0x52,0x48, + 0x72,0xbe,0xd4,0x64,0xb5,0x86,0xd6,0x8,0xab,0x3c,0x97,0xab,0x2c,0xa1,0x6d,0xa5, + 0xa1,0xa3,0x82,0x23,0x90,0xca,0xe9,0x2e,0x21,0xd2,0x91,0xb2,0x74,0xa5,0x42,0x1, + 0x28,0xc5,0xa0,0x95,0x40,0x97,0x94,0x56,0x91,0x44,0x71,0x92,0x30,0x38,0x51,0x89, + 0x46,0x1b,0x72,0x9f,0xdc,0x23,0xdb,0x26,0x7b,0x1e,0xc5,0xc9,0x5d,0x1a,0xda,0xc8, + 0x6a,0xc4,0x99,0x49,0xb,0x17,0xf7,0xf,0xaa,0xe7,0x35,0x2f,0x72,0xb0,0x57,0x49, + 0x6c,0x4c,0xac,0xa5,0x6d,0x65,0xeb,0xc,0x92,0x40,0x7f,0x1e,0xc9,0xca,0xe5,0x94, + 0x78,0x42,0x76,0xe9,0x48,0xfb,0xe1,0x5e,0x54,0xfa,0x2,0xcb,0x48,0x1,0xf0,0xc5, + 0xb5,0x4d,0x4e,0x49,0xe4,0x22,0xb,0x51,0x12,0x3e,0x73,0x6d,0xba,0x9c,0xa,0x2, + 0x21,0x47,0x98,0xc8,0xb0,0x40,0xe5,0x54,0x21,0x50,0x76,0x97,0x70,0xa4,0x2b,0x7, + 0x9a,0x1b,0x27,0xcb,0xf1,0x90,0xaf,0xdf,0xdd,0x26,0x6,0x7b,0x28,0x3e,0x71,0x8f, + 0x6e,0x48,0x76,0x66,0x71,0xc2,0x49,0x1a,0x34,0x82,0x49,0x68,0x79,0xf0,0xc1,0x14, + 0x65,0x3e,0xf7,0x3d,0x20,0xe1,0xe2,0xc3,0x51,0xb0,0xb,0x6a,0x36,0xaa,0x18,0x1d, + 0x1c,0xc0,0xa9,0xe9,0x11,0x9a,0x9b,0x1c,0xc5,0xdc,0xe4,0x30,0x66,0xc6,0x87,0x69, + 0x6a,0x62,0x10,0x53,0x63,0x43,0x98,0x1e,0x1b,0xa2,0x99,0xf1,0x61,0xf4,0x35,0xaa, + 0xa8,0x54,0x2a,0x20,0x22,0x74,0x3a,0x1d,0x1c,0x1e,0x77,0x70,0xef,0xf1,0x73,0xfe, + 0xfc,0xbb,0x25,0xfc,0xf2,0xf3,0xbb,0xf6,0xeb,0x7b,0xcf,0xb0,0xb2,0xb9,0x1b,0xe8, + 0x3e,0xd1,0xe9,0x4d,0xf1,0xb8,0xc9,0x18,0x66,0x77,0xea,0x18,0xe7,0xdb,0x4e,0x64, + 0xc8,0xed,0xd3,0x3d,0x5a,0xcc,0xb6,0x42,0xc4,0xc,0x4b,0x36,0xb9,0xe4,0xf8,0x4b, + 0x97,0xc5,0x96,0x52,0xc8,0xe1,0x3,0x61,0x2a,0xc2,0xe7,0x9,0xf5,0x30,0x26,0x70, + 0xe,0x9c,0x8f,0x3c,0x87,0xa4,0x78,0x13,0xc8,0x73,0xd1,0xe7,0x2c,0x8d,0x88,0x4, + 0x4a,0xf9,0xe8,0x71,0x53,0x67,0x4,0xbc,0x1e,0x1a,0x7d,0xc3,0x14,0x77,0x45,0xa2, + 0x71,0x74,0x4f,0x8b,0x33,0xc2,0xac,0xb8,0xae,0xbc,0xe7,0xbb,0x36,0x3a,0xc,0xde, + 0x7d,0xc2,0x4d,0x25,0xf5,0x94,0xa1,0x28,0xfb,0x62,0x60,0x2,0xef,0x4d,0x49,0x6a, + 0x59,0xb0,0x7a,0xe5,0x72,0x20,0xa8,0x95,0x38,0x4c,0xde,0x3e,0xb9,0x53,0xdc,0x94, + 0xd2,0x64,0x6,0xae,0x55,0x11,0xa,0x11,0x71,0x58,0x9b,0xb4,0x9b,0xf1,0xad,0x96, + 0x91,0xec,0x38,0x9f,0xc1,0x2e,0xf8,0x23,0xfe,0xf4,0xa,0x2b,0x2a,0x8e,0xc,0x38, + 0x12,0x11,0x46,0x1c,0xd7,0xf1,0x9c,0x11,0xb2,0x4c,0xc5,0xd0,0xd8,0x50,0x1f,0xa6, + 0xc7,0x87,0x68,0x76,0x7c,0x18,0x13,0xa3,0x3,0x18,0x1f,0x19,0xc4,0xc4,0xe8,0x0, + 0x4d,0x8e,0xe,0x61,0x62,0xa4,0xf,0xc3,0x3,0x7d,0xe8,0x6b,0xd6,0xa9,0x5e,0xad, + 0xa0,0x5e,0xab,0xa2,0x5e,0x73,0xff,0x6e,0xd4,0xab,0xa8,0x57,0x2b,0xb0,0x96,0x71, + 0xd2,0xb5,0xe8,0x74,0x2d,0xd8,0x32,0x3a,0x5d,0x8b,0x4e,0xb7,0x8b,0x4e,0xd7,0xa2, + 0xd5,0x3e,0xc1,0xe1,0xd1,0x31,0xf6,0xe,0x8f,0xf9,0xe0,0xa8,0x4d,0xfb,0x47,0x2d, + 0xec,0x1f,0xb6,0xb1,0xbb,0x7f,0x84,0xed,0xfd,0x23,0xde,0xd8,0xda,0xc7,0xca,0xc6, + 0x2e,0x2d,0x6f,0xec,0xf2,0xfa,0xf6,0x3e,0xe,0x8e,0x8e,0x5d,0x78,0x1d,0x92,0xc7, + 0xf,0x89,0x70,0xa3,0xd0,0xc6,0x5b,0x4e,0x2b,0x8e,0xd0,0x26,0x86,0x28,0x17,0xcf, + 0x31,0x61,0x36,0xae,0x9c,0x93,0x35,0xce,0xea,0xc7,0x10,0x60,0x8d,0x67,0x8d,0xb0, + 0x8f,0x68,0x33,0x6e,0xd6,0x76,0x41,0x3b,0x36,0xb4,0x12,0x1c,0x49,0x3b,0x22,0xdf, + 0x8f,0xa2,0xe0,0x30,0xdc,0x19,0x2c,0xf2,0x3a,0x48,0x67,0xa5,0x27,0xf3,0x3d,0x16, + 0xab,0xe7,0x38,0x5a,0xca,0xa0,0x29,0xd6,0x0,0x14,0x67,0x41,0x5a,0x9a,0xb0,0x2c, + 0x51,0x69,0xb1,0x96,0x9a,0x7c,0xe3,0x2f,0x3e,0x2b,0xa5,0x22,0xe7,0xf4,0xf8,0xd2, + 0xf3,0xbf,0x34,0x48,0x53,0x89,0x47,0x72,0xd7,0xb2,0x34,0x81,0x53,0x4f,0xc9,0xbd, + 0x9e,0x32,0x8b,0x5f,0x5f,0xfc,0xaf,0x17,0x89,0xca,0xd0,0x43,0x76,0x97,0x6b,0x28, + 0xf3,0xe2,0x5f,0x7c,0x55,0x9,0x59,0xc,0xaa,0x5c,0xec,0x17,0x8,0x5f,0xa1,0x48, + 0xe5,0x7a,0x1b,0xd6,0x3c,0xa8,0xa2,0xb9,0xab,0x60,0x8a,0x97,0x18,0x8,0x20,0xf, + 0xc4,0xc1,0x8b,0x65,0x80,0xa5,0xa,0x82,0x7c,0xd5,0xc1,0x5,0x14,0x86,0x7b,0x91, + 0x57,0x55,0x48,0xf,0x95,0xff,0x9e,0x1e,0xf1,0xe6,0xb9,0x34,0x8f,0x4,0xe7,0x11, + 0x22,0xdf,0x4,0x46,0xe4,0x92,0x8b,0x54,0xa8,0x68,0x7d,0x49,0x26,0x4e,0xde,0x6e, + 0x63,0xee,0x77,0xb9,0x1e,0x6a,0x4f,0x66,0x96,0xa2,0xa8,0x93,0x37,0x6d,0xf,0xcc, + 0xea,0xe4,0x70,0x1d,0x68,0x3a,0xa4,0xf2,0x56,0x3,0x32,0x10,0x81,0x9c,0xf8,0xd0, + 0x62,0x56,0x76,0xa0,0x3e,0xb,0x4e,0x1b,0xa6,0x46,0x7,0x69,0x72,0x6c,0x10,0xd3, + 0x63,0x43,0x34,0x35,0x36,0x84,0xc9,0x31,0x77,0x28,0xe,0xf,0xf4,0x61,0xa8,0xbf, + 0x89,0xfe,0x66,0xd,0x3,0xcd,0x86,0x9b,0xc8,0x9b,0x75,0xf4,0x37,0xeb,0xe8,0x6b, + 0xd6,0xd1,0x57,0xaf,0xa2,0x56,0xab,0x4a,0x31,0x53,0xb4,0x7a,0x3c,0x38,0x6a,0x63, + 0x7d,0x7b,0x1f,0x6b,0x5b,0x7b,0xfc,0x78,0x65,0xb,0xf7,0x9e,0xac,0xf2,0x47,0x5f, + 0x3d,0xe0,0xcf,0x6f,0x3f,0xb1,0xdd,0xae,0xd,0xea,0xa0,0xc4,0xdd,0x74,0xa3,0x92, + 0xd,0x26,0xb1,0x96,0xd9,0x3a,0x6c,0x10,0xd6,0xa7,0x51,0x59,0x76,0x49,0x21,0x9e, + 0xbb,0x6b,0xad,0xb7,0x90,0xf0,0x74,0x2f,0xe6,0xc8,0xcb,0x90,0xf9,0xe1,0xe1,0xd5, + 0xf4,0xd3,0xb8,0xda,0x9b,0xbb,0xd5,0x87,0x71,0xaa,0x28,0x63,0xa4,0xe3,0x1e,0xbb, + 0x98,0xe8,0xa0,0x87,0x8e,0x43,0xa1,0x34,0x66,0x9e,0x9d,0x1c,0xa1,0x6b,0x17,0xe6, + 0xe9,0xfa,0xa5,0x79,0x1a,0x19,0xec,0xc7,0xfe,0xc1,0x11,0x7e,0xf3,0xf5,0x23,0xfe, + 0xfa,0xfe,0x12,0xb6,0x76,0x8e,0x14,0x9d,0xb5,0xfc,0x8a,0x27,0x19,0xf,0x95,0x35, + 0xc4,0x81,0x9b,0x9e,0x7f,0x35,0x94,0xc9,0x9,0x14,0x7,0x48,0xa8,0x5c,0x52,0x32, + 0x83,0x8a,0x7a,0x10,0xcb,0x24,0x1f,0x43,0x2b,0x28,0x5e,0xcc,0x89,0x22,0x9c,0x32, + 0xbf,0xd3,0x67,0xc5,0xd7,0x50,0x16,0x36,0x95,0xf8,0xc2,0x3a,0x38,0x80,0x49,0x13, + 0xde,0x44,0xaa,0x20,0xe9,0xbd,0x5,0x44,0x28,0x51,0xca,0x2d,0x8,0x8a,0x9c,0xc1, + 0xfe,0x26,0xcd,0x4d,0x8e,0x60,0x66,0xc2,0x35,0x91,0x33,0x93,0xc3,0x98,0x1a,0x1b, + 0xa2,0xf1,0x91,0x7e,0xc,0xf6,0x35,0xd0,0xac,0xd7,0xd0,0xd7,0xa8,0xa1,0x51,0xaf, + 0x51,0xb3,0x5e,0x45,0x7f,0xb3,0x8e,0x46,0xcd,0x5d,0x9f,0xd5,0x8a,0x41,0xc5,0x10, + 0xaa,0xd5,0x8a,0x5a,0xbf,0xb3,0xc8,0x98,0x90,0xd7,0x2f,0xe0,0xc2,0xff,0xba,0x5d, + 0x1b,0x8b,0x7d,0xbb,0xdd,0x71,0x93,0x7a,0xa7,0x83,0x93,0xae,0x45,0xbb,0x7d,0x82, + 0xd6,0x71,0x87,0xf,0x5a,0xc7,0x68,0x1d,0x77,0xb0,0x7f,0xd4,0xc2,0xfe,0x51,0x1b, + 0x3b,0x7b,0x47,0x58,0xdf,0xde,0xe3,0xd5,0x8d,0x3d,0x2c,0x6f,0xec,0xf0,0xf2,0xda, + 0x2e,0x56,0xb7,0x77,0x99,0xbb,0x71,0xd1,0xc9,0x5a,0x53,0xc8,0x88,0xa,0x73,0x82, + 0x10,0x97,0x39,0x71,0x66,0xd4,0x9e,0x3b,0xff,0x3e,0x8e,0x32,0x4e,0x76,0xa6,0x7e, + 0x60,0x6b,0xb9,0xb,0xb,0x74,0xad,0xff,0x6e,0xcb,0xb6,0x6b,0xc3,0xbd,0xe4,0x3e, + 0xe7,0xfc,0xe2,0xad,0x92,0xc4,0x45,0xdf,0x38,0xe,0x26,0xf5,0x7a,0x60,0xcc,0x8, + 0xae,0x92,0x70,0x8a,0x5c,0xb9,0xa1,0x17,0xba,0xc5,0x9a,0x85,0x62,0xad,0x11,0x83, + 0x76,0x95,0xa,0xb6,0xa9,0xe5,0x39,0xab,0x4a,0x15,0x6a,0x74,0xb1,0x29,0x17,0xc5, + 0x91,0xf2,0x45,0x57,0xd3,0x9e,0xec,0x5a,0x4a,0xa3,0x65,0xb8,0x60,0x76,0x52,0x90, + 0xfa,0x30,0x9,0x2f,0x71,0xa1,0x5b,0x16,0xc6,0xf8,0xba,0x38,0x66,0x26,0x2d,0x4c, + 0x8a,0xa8,0x57,0xa4,0x71,0xb,0x63,0x0,0xce,0x8a,0x39,0x17,0xb,0xa5,0x2e,0x56, + 0x32,0x66,0xb4,0x18,0x70,0x9f,0x18,0xbb,0xe1,0x71,0x53,0xc2,0x6c,0xf2,0xec,0x70, + 0x92,0x42,0x22,0x8,0x9a,0x99,0x4c,0x8f,0xd0,0xc1,0x2f,0xcc,0x45,0x17,0xb7,0x3c, + 0x5d,0x2d,0x34,0x93,0xb9,0xc2,0x82,0x45,0x95,0x25,0x70,0x66,0xab,0xab,0x13,0xd9, + 0xf4,0xde,0x2d,0x38,0x89,0x41,0xe9,0xd4,0xd5,0x1a,0x94,0xf2,0xde,0x45,0xd8,0xbf, + 0x9a,0xb8,0xbd,0x29,0x68,0xb7,0x61,0x1c,0xb5,0x2d,0xf8,0x58,0x7,0x66,0x2f,0x67, + 0xae,0x70,0xce,0x46,0xc6,0x10,0xf9,0x7d,0xae,0x31,0x30,0xc,0xc9,0xba,0x76,0xa5, + 0xd9,0xf8,0x82,0xe3,0x6c,0x9b,0x49,0x84,0xa0,0x32,0x85,0x85,0x7d,0x32,0x41,0xd1, + 0x10,0x25,0x33,0x83,0x2a,0x86,0x1a,0xd5,0xa,0x6a,0xb5,0x3a,0xb9,0x83,0xce,0xa0, + 0xbf,0x51,0xc7,0xc4,0xe8,0x20,0x2d,0x4c,0x8f,0xe2,0xd4,0xf4,0x28,0x9d,0x9a,0x1e, + 0xc3,0xc2,0xf4,0x8,0x4e,0x4d,0x8f,0xd1,0xdc,0xd4,0x8,0x1a,0xbe,0x58,0xcb,0x43, + 0x2f,0xff,0xef,0x18,0xf3,0x2c,0xe,0x44,0x22,0xc2,0x60,0x7f,0x3,0x83,0xfd,0xd, + 0x9c,0x99,0x1b,0xa7,0xf7,0x5e,0x3f,0x83,0x47,0xcb,0x9b,0x34,0x31,0x32,0x60,0xeb, + 0xb5,0x8a,0xb9,0xf3,0x78,0x9d,0xb7,0x76,0xf,0xd0,0xb5,0x5d,0x78,0x7,0x8c,0xb4, + 0x9c,0xf5,0xe9,0xce,0xee,0x25,0x36,0x88,0x4e,0x73,0xee,0x56,0x70,0x4b,0x77,0x76, + 0x94,0x1f,0x1b,0xf6,0x92,0x61,0xb5,0x2e,0xd,0xfa,0x42,0x35,0x31,0x51,0x3c,0xe6, + 0xcb,0x76,0x68,0x9e,0x3c,0xf4,0xce,0x62,0xf5,0x21,0x34,0xea,0x46,0x85,0xb3,0x24, + 0xa,0x7b,0x70,0xd1,0x9d,0x1c,0x1b,0xa4,0x1f,0xbe,0x79,0xce,0xfc,0xfe,0x7b,0x97, + 0xe9,0x87,0x6f,0x5e,0xa0,0xc9,0xd1,0x1,0x6c,0xee,0x1c,0x62,0x7a,0x62,0x98,0x9b, + 0x8d,0x1a,0x7f,0xf4,0xf5,0x3,0xec,0x1f,0x1c,0xa3,0x56,0xad,0xa0,0x52,0x31,0xa8, + 0x1a,0x83,0x4a,0xc5,0xa0,0x56,0x31,0xa8,0x54,0x2b,0x71,0x4d,0x51,0x9,0x5b,0x17, + 0xb1,0x2e,0xd4,0x32,0xd3,0x70,0x17,0x73,0x30,0xcc,0x5,0x23,0x4c,0x92,0x96,0x6c, + 0xd7,0xa2,0xdb,0xb1,0x7c,0x62,0xbb,0xe8,0x76,0x2c,0x3a,0xd6,0xa2,0xd3,0xe9,0xa, + 0x5e,0x6c,0x50,0x76,0x8b,0xfb,0x23,0xd0,0x11,0x5d,0x63,0xe8,0x73,0xa4,0x3c,0x76, + 0xc0,0xce,0x71,0x8c,0x6d,0xa0,0x7b,0x45,0xcc,0xde,0x81,0xc4,0x36,0xcd,0x7e,0xf1, + 0x34,0x8b,0x29,0x9d,0x9e,0xe7,0x17,0x50,0xab,0x8,0x93,0xe8,0xac,0xb5,0x94,0xd0, + 0x2a,0xb3,0xb,0x1c,0x0,0x2,0x76,0xb9,0x2,0xcd,0x46,0x1d,0x8d,0x7a,0x95,0xfa, + 0x9b,0x35,0x4c,0x8c,0xc,0xd2,0xfc,0xd4,0x30,0xce,0x9e,0x9a,0xc4,0xe9,0xe9,0x31, + 0x3a,0x3d,0x3f,0x81,0xd3,0xb3,0xe3,0x34,0x3f,0x39,0xac,0x42,0xd1,0x7a,0x5d,0xab, + 0x52,0x76,0x2d,0x8b,0x79,0xfe,0x75,0xb2,0xc8,0x1b,0x77,0xbb,0xc5,0x86,0x15,0x3, + 0xfa,0x9a,0x4f,0x3c,0x76,0x7d,0x1f,0x6c,0xef,0x1e,0x62,0x69,0x6d,0x9b,0x1e,0xaf, + 0x6c,0xf1,0xc3,0xe5,0xd,0x7a,0xf8,0x6c,0x83,0x9f,0x3e,0xdf,0xa6,0x95,0x8d,0x1d, + 0x3e,0x3a,0x3e,0x41,0xbb,0xdd,0xa1,0x56,0xfb,0x84,0x8f,0x4f,0x3a,0xe8,0x74,0xba, + 0x91,0x9,0x1,0xc1,0x5b,0x12,0x1e,0x16,0x62,0xe5,0xcb,0x86,0x43,0x60,0x11,0x59, + 0x77,0x19,0x5a,0xb8,0xbc,0x54,0xc3,0xc4,0x1c,0x88,0x53,0x1c,0xd6,0x18,0xfe,0xd, + 0x49,0xac,0x6d,0xb2,0x89,0xd1,0x9e,0xc4,0x5c,0xdc,0x63,0x55,0x49,0x5,0x15,0x56, + 0x8e,0x9f,0x16,0x14,0x1b,0xa5,0x6d,0x6b,0x89,0xe8,0x8d,0x34,0x72,0x4a,0x93,0xd7, + 0xff,0xe2,0x33,0x12,0x32,0x2c,0x2e,0x90,0xbb,0x4a,0x48,0xa1,0xc8,0x4c,0x6,0x4a, + 0xed,0xfe,0xf4,0x54,0x96,0x85,0x91,0x95,0x1a,0xdf,0xa8,0xe1,0x1c,0x3d,0xec,0x62, + 0xa9,0x80,0x82,0xab,0x9d,0x1b,0x4a,0xe0,0x8a,0x5c,0x18,0x96,0xc,0x57,0x38,0x23, + 0x7a,0xe8,0xc7,0x29,0x33,0x6f,0x65,0x2a,0x1a,0x73,0xb6,0x2f,0xce,0xa,0x2e,0xa, + 0xd2,0x3a,0x2e,0xcd,0x34,0x47,0x8e,0x37,0x70,0x6a,0x56,0xa4,0xbb,0x9d,0x36,0x8d, + 0xc9,0x5e,0x6b,0xca,0xe6,0x77,0x9,0x8,0x88,0xdf,0x4f,0xf9,0x5c,0xcf,0xba,0x18, + 0xa3,0x44,0x19,0x59,0xc4,0x3a,0x24,0x71,0x32,0x31,0xda,0x74,0x83,0xc1,0xa5,0x97, + 0xb3,0x9a,0x87,0x94,0xfd,0x58,0x16,0x5f,0x47,0x32,0x6f,0x85,0x28,0x6a,0xcd,0xe3, + 0xcd,0x45,0x64,0xc,0xdc,0x8e,0xdc,0xef,0xc5,0x49,0xfe,0xdd,0x38,0xd3,0x67,0x63, + 0x8c,0x71,0xb6,0xca,0x26,0xb0,0xb0,0x1d,0x1c,0xcf,0x50,0x21,0x2c,0x9c,0x3c,0x35, + 0x83,0x1,0x34,0x45,0xad,0x2d,0xca,0x8,0x6e,0x84,0x91,0xe1,0x3e,0x3a,0x37,0x37, + 0x81,0xb,0x8b,0x53,0x74,0xfe,0xd4,0x24,0x9d,0x9e,0x19,0xc7,0xc2,0xec,0x18,0x46, + 0x87,0xfa,0xa9,0x56,0x35,0xa8,0xd7,0xaa,0xa8,0x55,0x5c,0xf1,0x69,0xd4,0x2a,0xa8, + 0x56,0x2b,0xea,0xa0,0xcb,0xf,0xc5,0xb2,0x3,0xf4,0x45,0xc5,0xff,0xe4,0xa4,0x83, + 0xa3,0x76,0x7,0x8f,0x57,0x36,0xf9,0x2f,0x3f,0xf8,0x9c,0xff,0xee,0xe3,0xef,0xec, + 0xfd,0xa5,0x35,0x66,0xcb,0x2c,0xa6,0x75,0xe,0x2,0x1e,0x8,0x53,0x19,0xcf,0xac, + 0xb6,0xfe,0x4b,0xac,0x65,0x96,0xba,0x5c,0xb0,0xd,0xc,0x6c,0x1b,0x8,0x5b,0xc4, + 0xce,0x7a,0xd5,0x93,0xda,0x4c,0xe0,0xb4,0x9b,0x90,0xac,0xe6,0x8e,0xc1,0x50,0xcc, + 0x95,0x99,0x89,0x60,0x63,0xfb,0xf7,0x30,0x98,0xee,0xf9,0x56,0xfb,0xca,0xb9,0x59, + 0xfa,0xa3,0x1f,0x5c,0xa5,0x3f,0xfc,0xfe,0x55,0xba,0xb8,0x38,0x4d,0x8d,0x5a,0x5, + 0x95,0x4a,0x5,0xdd,0x6e,0x17,0x27,0x5d,0x8b,0x8f,0x6f,0x3d,0xe2,0xff,0xf1,0x2f, + 0x3f,0xe4,0x27,0x6b,0x5b,0x68,0xd4,0xaa,0x18,0x1f,0x1e,0xc0,0xe4,0xe8,0x0,0x26, + 0x46,0xdd,0x44,0x39,0x31,0x3c,0x80,0xc9,0xb1,0x41,0x8c,0xd,0xf6,0x61,0x60,0xa0, + 0x49,0x15,0x32,0xa5,0xa8,0x5d,0x78,0xd,0x2d,0xb3,0x9b,0x16,0x4f,0x3a,0x7c,0xdc, + 0xee,0xe0,0xa8,0x7d,0x82,0xdd,0xfd,0x16,0x36,0x77,0xf,0xb1,0xb9,0xb3,0xcf,0x1b, + 0xdb,0x87,0xd8,0xd8,0xde,0xc7,0xda,0xce,0x3e,0x6f,0xee,0x1c,0x62,0x75,0x73,0x17, + 0x7b,0x7,0x2d,0xce,0x32,0x92,0xf5,0x31,0x17,0xa7,0x73,0xe6,0x3c,0x9f,0x12,0x82, + 0x2,0x1f,0xc9,0x45,0x60,0x4d,0xd0,0x93,0xb9,0x59,0xa9,0xf1,0x16,0x91,0x88,0x94, + 0xb7,0xc2,0xbd,0x52,0xff,0xa4,0x24,0x9f,0x0,0xc2,0xe4,0xe8,0x10,0x5d,0xbf,0x38, + 0x47,0x6f,0x5c,0x3c,0x85,0xd7,0xce,0xce,0xd2,0x99,0xb9,0x31,0x1a,0x1b,0x1a,0x40, + 0xb5,0x6a,0x50,0xab,0xb8,0x6b,0xb3,0x51,0xab,0xa0,0x5e,0xaf,0x15,0xae,0xc9,0xfc, + 0x7a,0xcc,0x3f,0xfe,0xb2,0xcf,0x95,0x35,0xab,0xa5,0x20,0x62,0xf6,0xf3,0xc2,0xdf, + 0xc3,0x35,0x70,0xdc,0xee,0xa0,0xd3,0xb1,0x38,0xe9,0x74,0x71,0x74,0xdc,0xc6,0xee, + 0x41,0x8b,0x1f,0xaf,0x6c,0xe2,0xce,0x93,0x55,0xfe,0xfa,0xfe,0x32,0xbe,0xb9,0xbf, + 0xcc,0xcb,0x6b,0x3b,0xcc,0x2c,0x19,0x51,0xc9,0xbf,0x3d,0x7e,0x20,0x5e,0xf7,0x62, + 0x52,0xb7,0xee,0xae,0x71,0x9,0xe8,0xfe,0xef,0x96,0x2d,0x82,0x29,0x13,0xac,0x65, + 0x66,0x4b,0x5d,0x77,0xf,0xb1,0xd,0xc8,0x97,0x47,0xb4,0xd8,0x6,0xb3,0x60,0x56, + 0xab,0x2a,0x8e,0x76,0x43,0x40,0x6e,0xda,0x4d,0xd1,0x74,0xa7,0x58,0xc4,0x94,0x1, + 0x99,0x9e,0x1a,0x75,0xfe,0x48,0x21,0x0,0x4,0x20,0x42,0xb5,0xb4,0x8b,0x60,0x91, + 0x77,0xad,0x2d,0xbe,0x34,0x6f,0x2a,0x2b,0xca,0x8a,0x8d,0x1b,0x9,0xc,0x89,0x49, + 0x1d,0x18,0xd1,0x9c,0x4d,0xdf,0x6a,0xfa,0xa7,0x92,0x5d,0xb3,0x22,0xb,0x24,0x16, + 0xbc,0xdc,0xf0,0x2a,0x1d,0x34,0xb,0xd9,0x16,0xe7,0x53,0x3c,0xab,0x69,0x91,0x73, + 0xb,0x5b,0x49,0xae,0x51,0xd2,0x30,0x9d,0x2e,0xa6,0xaf,0x48,0x46,0xc6,0x53,0x2c, + 0x36,0xa,0x48,0x50,0x1e,0xb,0x1f,0x2b,0x2e,0x1a,0x31,0x20,0x8b,0xc0,0xd1,0x52, + 0xbc,0xcc,0x30,0x47,0x96,0x4a,0x15,0x8b,0x9a,0xc5,0xa3,0x26,0x44,0x84,0x75,0x57, + 0xc8,0x89,0x89,0x4f,0x2f,0x28,0xc2,0xfa,0xf7,0x93,0x88,0x49,0xa4,0x8c,0x38,0x49, + 0x5,0x7,0x3d,0x45,0x31,0x50,0x1e,0xbb,0x61,0x7,0x1c,0xf8,0xdc,0x86,0x52,0xd8, + 0x12,0x11,0xab,0xb7,0xd3,0x84,0x14,0x74,0x2,0x55,0x1c,0xf5,0xc9,0x24,0xcf,0x70, + 0xb7,0x3d,0x8c,0xfe,0x32,0x8e,0xf0,0x46,0x95,0x60,0x68,0x62,0xa4,0xaf,0x3b,0x60, + 0x4c,0xc2,0x5b,0x4,0xcb,0x9d,0x92,0x91,0x78,0x34,0xc2,0x30,0x44,0x3,0xcd,0x3a, + 0xe6,0xa7,0x46,0x69,0x72,0x74,0x80,0x26,0xc7,0x6,0xb1,0x30,0x3d,0x4a,0xb,0x33, + 0x63,0x98,0x9f,0x1a,0xc5,0xec,0xc4,0x8,0xcd,0x8e,0xf,0x61,0x6c,0x64,0xa0,0xf4, + 0xf0,0x92,0x53,0x8,0x3b,0xa7,0xc9,0x38,0x9,0x11,0xd1,0x4b,0xf,0xb8,0x7c,0xa, + 0x2,0x80,0x5a,0xad,0x8a,0x7a,0xbd,0x86,0xeb,0x17,0x4f,0xd1,0x71,0xbb,0x3,0x0, + 0x66,0x6d,0x6b,0xdf,0xee,0x1e,0xb4,0x40,0xce,0xc2,0x5d,0xec,0x8e,0x3d,0xc0,0xc7, + 0x6,0x6c,0x2c,0xa9,0x4e,0xcf,0x72,0x64,0x71,0x83,0x9d,0xb7,0x3b,0x99,0x80,0x58, + 0x26,0x8b,0xdd,0x48,0xc1,0x97,0x3e,0xee,0x46,0xb9,0xbe,0x91,0x50,0xfa,0x45,0x2e, + 0x42,0x72,0xde,0x73,0x72,0xb5,0x10,0x2a,0x12,0x6e,0xa1,0xbe,0x46,0x83,0xde,0xb9, + 0x72,0x9a,0xfe,0xf9,0xf7,0xaf,0xd2,0xeb,0xe7,0xe7,0x48,0x4e,0x88,0x95,0x4a,0x5, + 0xc6,0x18,0xbc,0x79,0x69,0x81,0xfe,0xf4,0x27,0xd7,0xb1,0xb1,0x7d,0x80,0x5a,0xad, + 0x8a,0xa1,0xfe,0x6,0x46,0x7,0xfb,0x30,0x34,0xd8,0x47,0xc3,0x3,0x4d,0x8c,0xe, + 0xf6,0x61,0x64,0xa8,0xaf,0x80,0x80,0xf4,0x2a,0xe8,0xea,0xae,0x65,0x47,0xd4,0x3a, + 0x3c,0x3e,0xc1,0xce,0xfe,0x11,0x76,0xf,0x5a,0xb4,0xb3,0x7f,0xc8,0x3b,0x7b,0x2d, + 0xec,0x1d,0xb4,0x68,0xf7,0xb0,0x85,0xad,0xdd,0x3,0x6c,0xed,0x1e,0xf2,0xee,0xfe, + 0x31,0xb6,0xf7,0xe,0x78,0x7d,0xe7,0x0,0x6b,0x5b,0x7b,0xb4,0xb5,0x7b,0x98,0xd2, + 0xd5,0x64,0xa2,0xd,0xc4,0xc1,0x7,0xe9,0x19,0x43,0x21,0xd8,0x4b,0x2c,0x98,0xbc, + 0x97,0x59,0x74,0x68,0xcb,0x64,0x5d,0x52,0x2c,0xa9,0x33,0x76,0x65,0x8b,0x99,0xe0, + 0x78,0xff,0xf9,0x99,0x89,0x11,0xba,0xb8,0x30,0x49,0x73,0x53,0x23,0x58,0x98,0x19, + 0xa3,0xb3,0xf3,0x13,0x38,0x7f,0x6a,0x12,0x8b,0x33,0x63,0x34,0x32,0xd8,0xa7,0xae, + 0xa7,0x7c,0xc2,0x76,0x1c,0x3f,0xf3,0xc2,0xeb,0xf1,0x55,0x3f,0x97,0xf5,0xe7,0x78, + 0xd9,0x1f,0xeb,0x7a,0xca,0xf8,0x98,0x8c,0x31,0x68,0x18,0x13,0xdf,0x5b,0xc9,0x53, + 0x39,0x33,0x3b,0x8e,0xb3,0xf3,0x13,0xb8,0xb8,0x38,0x8d,0x1b,0x17,0x4f,0xe1,0xe1, + 0xb3,0xd,0x5a,0x5a,0xdd,0xe1,0x67,0x6b,0x5b,0xfc,0xf4,0xf9,0x36,0x47,0x86,0x8d, + 0x4d,0xa6,0x11,0x4c,0x30,0x64,0x7d,0x70,0x5a,0x54,0x6,0x90,0xd3,0x9e,0x73,0x10, + 0xa,0x7b,0xec,0x8e,0x3,0x85,0xc2,0x10,0xb1,0x75,0x68,0x20,0x33,0x9c,0x76,0x8d, + 0x39,0x31,0xcb,0x21,0x7,0x61,0xb1,0xf2,0x67,0x21,0x93,0xce,0x6,0x20,0xe6,0x2, + 0xb,0xbe,0x40,0x74,0xb,0x83,0x58,0xee,0x65,0x12,0x4d,0xc6,0xf2,0xa9,0xdf,0xfd, + 0x96,0xaa,0x24,0x58,0xa5,0x4d,0xbf,0x40,0xf0,0x49,0xb8,0x89,0x89,0x7d,0xb6,0x2c, + 0x3c,0x24,0xa,0xa2,0x43,0x90,0x73,0x1b,0x7e,0x2a,0x38,0x41,0xe4,0x8d,0x1,0x45, + 0x28,0xbf,0x54,0x9d,0x8d,0x22,0xf0,0x4b,0x25,0xa4,0x2d,0x6d,0x92,0x22,0x9,0xb1, + 0xc1,0x1d,0x8e,0x44,0x94,0x1d,0x49,0xc8,0x59,0x34,0x6,0x94,0x11,0xc4,0x89,0x33, + 0x96,0x3b,0x9,0x53,0x96,0x2c,0x61,0x34,0x16,0xb4,0x52,0x31,0x22,0x92,0x29,0x65, + 0x86,0x5a,0xe4,0x44,0x3c,0x2a,0xb,0xb5,0xe7,0x4c,0xaf,0xce,0xd2,0x13,0xde,0x68, + 0xe8,0x4,0x82,0x9c,0x28,0xc8,0x13,0x45,0xf9,0x1d,0xe9,0x38,0xd6,0xa8,0x22,0x60, + 0xa1,0x9d,0x66,0x95,0xee,0x96,0xc3,0xe7,0xa4,0xfb,0xaf,0x84,0x94,0xb0,0xce,0xd3, + 0x56,0x6f,0x1a,0x9,0x9,0x82,0x38,0xb0,0x94,0x8f,0xb4,0x9,0x61,0x14,0x9,0x76, + 0x8f,0x1a,0x24,0x5f,0xbc,0xc3,0x1e,0xd7,0xc4,0x9d,0xb9,0x31,0xce,0x38,0xdb,0x18, + 0xf7,0xf5,0xc6,0x90,0x89,0x93,0xa2,0x91,0x31,0x93,0xd1,0xba,0x34,0xa0,0x6,0x48, + 0xc0,0x1,0x19,0x7,0x5,0xc,0xf7,0x37,0xe9,0xf2,0x99,0x19,0xfa,0xd1,0x8d,0xf3, + 0xf4,0xf6,0xd5,0xd3,0xb8,0x72,0x7a,0x86,0xc6,0x87,0xfb,0xe3,0xd4,0x1d,0xe,0xc1, + 0x1c,0x42,0xcc,0xe1,0x47,0x9,0xa1,0xff,0x43,0xfe,0xf4,0xfa,0xbe,0x77,0xaf,0x9e, + 0xa6,0x4e,0xd7,0xe2,0xa3,0xaf,0x1e,0xd2,0x37,0xf,0x56,0xd8,0x76,0x53,0xc,0x5b, + 0xd2,0x4e,0x50,0xd0,0xd1,0xc6,0x8b,0x86,0xc9,0xb1,0xb3,0xfd,0x7b,0x6b,0xd8,0x5a, + 0x4b,0x52,0x1a,0xc5,0x1c,0x98,0xe5,0x31,0xc7,0x33,0x32,0xdd,0x23,0x83,0x8b,0x54, + 0x48,0x8b,0x70,0x33,0x13,0xc5,0x5c,0x1b,0x9e,0x84,0xf7,0x77,0xa0,0xaf,0x49,0xaf, + 0x9f,0x9f,0xa3,0xef,0xbf,0x79,0x8e,0xae,0x5f,0x5a,0xa0,0x32,0x58,0x97,0x88,0x30, + 0xd4,0xdf,0xc0,0x9f,0xff,0xe4,0x6,0x95,0xad,0x27,0xf2,0xd7,0xf9,0x55,0x5e,0xbf, + 0x7c,0x52,0xac,0x56,0x2b,0x18,0xae,0x56,0x30,0xd4,0xdf,0x8,0x3f,0x8f,0xf2,0x9f, + 0xd7,0xe9,0x74,0x69,0x75,0x6b,0xf,0xf,0x9e,0x6d,0xf0,0xe7,0xb7,0x9f,0xe2,0xf3, + 0xef,0x9e,0xf2,0xad,0xfb,0xcb,0x58,0xdb,0xdc,0xe3,0x4e,0xb7,0x4b,0xca,0xff,0x7, + 0xc6,0x3f,0x17,0xe1,0xd4,0xe0,0x67,0x35,0x81,0x99,0x7b,0x32,0x97,0x11,0x7e,0x84, + 0x36,0x86,0x7c,0x44,0x93,0x5d,0x88,0xc4,0x73,0xef,0xc8,0x49,0xec,0x29,0x7d,0x62, + 0x49,0x24,0xcd,0x89,0x87,0xfa,0x1b,0xf4,0x3b,0x37,0xce,0xd1,0x7f,0xfd,0xcf,0xde, + 0xa1,0xab,0x67,0x67,0x69,0x7c,0x64,0xa0,0x74,0x9a,0xce,0xe3,0xcf,0xc3,0xeb,0xf8, + 0xf,0xbd,0x3e,0xff,0x31,0xfe,0xc8,0x46,0xe2,0x45,0x8d,0x19,0x33,0x63,0x78,0xb0, + 0x89,0xeb,0xc3,0xa7,0xe8,0xfa,0xc5,0x53,0xe8,0x76,0xbb,0xb4,0xbd,0x77,0x84,0x4f, + 0xbe,0x7d,0xc2,0x3f,0xff,0xf4,0x2e,0xff,0xcd,0x6f,0xbe,0xb5,0xcb,0xeb,0xdb,0x41, + 0x68,0xa5,0xe8,0xcc,0x30,0x6c,0x88,0xc9,0x86,0x60,0x35,0x98,0xe8,0x8,0x47,0xcc, + 0x11,0x85,0x32,0xb0,0xdc,0x85,0x75,0xca,0x2,0x4b,0x44,0xf0,0x46,0x32,0x6e,0x85, + 0x12,0x1a,0xb0,0xe8,0x20,0x48,0x59,0x0,0x5b,0x66,0xd3,0x4a,0x52,0x89,0xa8,0x8c, + 0x8f,0x58,0xa5,0x9b,0x52,0x46,0x4f,0x22,0x85,0x7e,0x27,0xdf,0x94,0x32,0xf9,0xb7, + 0xbb,0xc,0xab,0xca,0xe4,0x8c,0x75,0x90,0x41,0x31,0x5f,0x3b,0x3b,0xc1,0x73,0xb2, + 0x56,0x34,0x95,0xa7,0x6c,0xaa,0x96,0xbb,0xea,0x62,0xdc,0xa8,0xf2,0x9,0xa6,0x4c, + 0xe3,0x8,0x8d,0x3a,0xc9,0xa6,0x35,0xc5,0xf2,0x64,0xd0,0x33,0x17,0xb2,0xba,0xd2, + 0x5e,0x9b,0x85,0xdc,0x55,0x75,0x4a,0x2,0x42,0xd7,0x6,0xed,0x9a,0xad,0x4d,0xba, + 0x1e,0xc9,0xaf,0xa7,0x6c,0xc2,0x8f,0xe,0x81,0x2c,0x76,0xea,0x32,0x32,0x36,0x6a, + 0xed,0x49,0xc7,0x2d,0x97,0xa1,0xd1,0x52,0x53,0xcf,0x5c,0xca,0x7a,0x53,0xe3,0x8f, + 0xaa,0xd1,0x1,0xe2,0xa1,0x10,0xa1,0xad,0x74,0xaf,0xf9,0xd5,0x51,0x48,0xf5,0x21, + 0xca,0xde,0x7,0x46,0xa9,0xbe,0x5a,0x75,0x32,0xa4,0xd3,0xdb,0xb,0xb1,0xb2,0x9c, + 0xbc,0x3e,0x55,0x32,0x5c,0x28,0x1e,0x72,0xe2,0x83,0xb2,0x74,0xa5,0x40,0x85,0x53, + 0x45,0xc5,0x6b,0xcb,0x25,0x7b,0x3d,0xb0,0xda,0x33,0x89,0x9a,0x92,0x5e,0xc5,0xe, + 0xc7,0xc4,0x20,0x8c,0x8a,0x31,0xb8,0x7c,0x76,0x86,0xde,0xba,0xbc,0x40,0xd7,0x2e, + 0xcc,0xd3,0xd9,0xf9,0x9,0x4c,0x8e,0xe,0xd2,0xec,0xf8,0x30,0x46,0x86,0xfa,0x7a, + 0x4e,0x7d,0x11,0xd6,0x15,0x53,0xf8,0x3f,0xf6,0x1f,0xd9,0x3c,0x84,0x7b,0xee,0xd4, + 0xf4,0x28,0xfd,0xf4,0xbd,0x2b,0xd4,0xe9,0x5a,0x73,0xfb,0xc1,0x8a,0x95,0xd3,0xa2, + 0x23,0xe9,0x4a,0xc,0xdf,0x25,0xbd,0xb8,0xd5,0x7a,0x8,0x64,0xb1,0xce,0x87,0xc7, + 0xb2,0xb0,0x4d,0x50,0x81,0x29,0x48,0xab,0x9,0x10,0x93,0x89,0xc5,0x3d,0xac,0x38, + 0xfc,0x5a,0x3e,0xda,0xed,0x92,0x71,0xe1,0x36,0xe4,0x79,0x9,0xcc,0x8c,0xb1,0xa1, + 0x7e,0x7a,0xed,0xdc,0x2c,0x2d,0xcc,0x8c,0xd1,0x99,0xb9,0x71,0xba,0x72,0x66,0x6, + 0xd7,0x2e,0xcc,0x45,0xb2,0xb9,0xb5,0xb6,0xf0,0x7a,0x86,0xfd,0xab,0xfc,0x7b,0xfe, + 0xfc,0x7b,0x41,0xb6,0x65,0x3b,0xdf,0x7c,0x2a,0xed,0xd5,0x7c,0xc9,0xaf,0xad,0xd5, + 0xaa,0x98,0x9f,0x1a,0xc5,0x60,0x5f,0x93,0x66,0x27,0x47,0xf0,0xfd,0x6b,0x67,0xf1, + 0x7c,0x73,0x97,0x9e,0xae,0xed,0xe0,0xe1,0xb3,0x75,0x7e,0xb0,0xb4,0x81,0xbb,0x4f, + 0x56,0x79,0x73,0xf7,0x20,0x86,0x99,0xa5,0x91,0x4d,0x99,0xc1,0x11,0xb3,0x61,0x6f, + 0x91,0x94,0xc,0x69,0x12,0x25,0x5f,0xc8,0xe3,0xe3,0xbc,0xe8,0x3f,0xec,0x9,0xe, + 0x7e,0x8f,0x9b,0x52,0x72,0xd2,0x91,0x3f,0x3e,0x3c,0x40,0x7f,0xf6,0x93,0x37,0xe9, + 0xf7,0xdf,0xbd,0x44,0x6f,0x5c,0x98,0xa7,0xe1,0x81,0x66,0x81,0x8f,0x51,0xb6,0xd2, + 0x79,0xd5,0x9,0xfa,0xff,0xcd,0x3f,0xf9,0xb5,0x91,0x5f,0x13,0xe3,0x23,0x3,0x78, + 0xf7,0xb5,0x45,0x9a,0x9d,0x18,0xc2,0xbb,0xaf,0x2f,0x56,0x3e,0xfc,0xe2,0x3e,0xff, + 0xfc,0xd3,0x3b,0x76,0x65,0x63,0x2f,0x70,0xd5,0x42,0x5b,0x15,0x15,0x0,0x40,0x32, + 0xdf,0xf1,0xae,0xd,0x64,0x6c,0x88,0x48,0x77,0xc5,0x3d,0xda,0xf3,0x12,0x83,0x9d, + 0x5d,0x1c,0x3b,0xf4,0xce,0x8a,0xdc,0x99,0x18,0xb6,0x23,0x56,0xaf,0xfe,0x9b,0xb, + 0x61,0x54,0x32,0x35,0x34,0x67,0xbf,0x6b,0xb2,0x79,0x31,0x34,0x48,0x60,0xca,0x24, + 0x73,0x33,0x52,0xed,0xaa,0x4a,0x29,0x96,0x8a,0x2c,0x45,0x6,0xbb,0xcb,0x3,0x5c, + 0xc6,0x37,0x50,0x8f,0x3c,0x17,0x86,0xb2,0x7e,0x4d,0x93,0x6e,0x71,0xab,0x50,0xaa, + 0xfc,0x92,0x85,0xaa,0xe8,0xef,0xa6,0x8b,0x6a,0xc1,0xcd,0x20,0xf3,0x25,0x97,0x5e, + 0x15,0x79,0x80,0x80,0x78,0x12,0x85,0xdf,0x90,0x11,0xc9,0x50,0xaa,0xfd,0xe6,0x92, + 0xef,0xd7,0x7d,0x58,0x4a,0x9a,0xcb,0x8c,0x1b,0xd4,0xdf,0xa9,0x4c,0xbc,0x5d,0x22, + 0x5d,0x93,0xd3,0x6d,0xde,0xe2,0xf6,0x20,0x42,0x52,0x5e,0xe8,0x95,0xbc,0x87,0xb, + 0x5f,0x4c,0xe5,0xcf,0x97,0x7a,0xa,0xcc,0xa1,0xbb,0xce,0x2,0x89,0x43,0xbf,0xfe, + 0x51,0x7c,0x9b,0x5a,0x73,0xe5,0x0,0x7,0x91,0x54,0x6,0xa4,0xa8,0xc7,0x10,0xa2, + 0x12,0xd,0x61,0x4c,0x28,0xe2,0xb1,0x1,0x30,0x61,0xae,0x2f,0x91,0xa8,0x51,0xd0, + 0xbf,0x41,0xfe,0x2f,0xd,0x3b,0x54,0xaf,0x55,0x31,0x31,0x36,0x44,0xe7,0x66,0xc7, + 0xe9,0xfd,0x37,0xcf,0xd2,0x8f,0xae,0x9f,0xc7,0x9b,0x97,0x4e,0x51,0xad,0x56,0xed, + 0x39,0xe1,0x95,0x1d,0x86,0xc6,0x99,0xb2,0xf5,0x2c,0x38,0x65,0x45,0x45,0x16,0xeb, + 0xb2,0x89,0x45,0xfe,0x2e,0x59,0xfc,0x98,0x19,0x23,0x83,0x7d,0xf8,0xbd,0x77,0x2e, + 0xd1,0xfd,0xe5,0x75,0xbe,0xfd,0x60,0x25,0x4d,0xc,0x1c,0x88,0x40,0x69,0x52,0x21, + 0x9f,0x5a,0xe1,0x1d,0xdf,0x0,0xe7,0x72,0xe5,0x50,0x46,0x23,0xbc,0xa7,0x38,0xd0, + 0xda,0xc,0x45,0x4f,0x2e,0x12,0x9e,0xf7,0x59,0x82,0x9a,0xe,0x64,0xe1,0x94,0x70, + 0x7,0xa2,0x6a,0xc5,0xd0,0xe4,0xf8,0x10,0xbd,0x73,0x79,0x91,0xde,0xbf,0x7e,0x96, + 0xae,0x9e,0x9d,0xc5,0xe9,0xd9,0x31,0x9a,0x9d,0x1c,0x89,0x6b,0x88,0x40,0x9e,0x7a, + 0xd9,0xea,0xe1,0x1f,0xa,0x1,0xf7,0xfa,0x59,0xbd,0xbe,0x27,0x27,0x7a,0x11,0x11, + 0x46,0x86,0xfa,0x30,0x3c,0xd8,0x4,0x2d,0x4c,0x11,0x33,0x63,0x67,0xef,0x8,0x77, + 0x9f,0xae,0xe1,0xcb,0x3b,0x4b,0x98,0x99,0x18,0xc6,0xed,0x47,0xcf,0xb1,0xb3,0x77, + 0x84,0xc3,0xa3,0x63,0x1c,0xb6,0xda,0xe8,0xb2,0x2f,0x23,0x24,0xf1,0x71,0x31,0xc4, + 0x19,0x22,0x6f,0xb2,0xab,0xc2,0xfa,0x84,0x2b,0xb0,0x9a,0xa1,0x58,0x7a,0x1a,0x90, + 0xbc,0xe3,0x5c,0x59,0x9f,0x99,0x18,0xa6,0x3f,0xfe,0xc1,0xeb,0xf4,0xce,0x6b,0xb, + 0x24,0x77,0xe2,0xf9,0x75,0xf6,0x4f,0xbd,0x78,0xbf,0x6c,0x7a,0xef,0x75,0x2f,0x4d, + 0x8c,0xe,0x62,0x62,0x74,0x90,0xae,0x5f,0x3c,0x85,0xd9,0xf1,0x11,0x0,0x64,0x3e, + 0xfa,0xea,0x81,0x7d,0xbc,0xbc,0x85,0xd4,0xd3,0x46,0xf5,0x82,0xd7,0xf5,0x71,0x52, + 0xc2,0x71,0xf2,0xb8,0xe0,0x88,0x34,0x31,0x59,0x97,0x90,0xeb,0x48,0x8e,0xae,0xd, + 0x20,0x16,0x59,0x79,0x41,0xa,0x93,0xec,0x86,0x7a,0x7b,0xe1,0xb3,0x58,0xb,0x87, + 0xe2,0x9f,0x85,0xdb,0x65,0xe7,0xbc,0x5e,0x75,0x4b,0x72,0xae,0x48,0xb6,0x8f,0x3f, + 0xaf,0xa,0xd2,0x7b,0x51,0x69,0xe6,0x5b,0x9c,0xac,0x38,0x8b,0xf0,0x2c,0x67,0xc4, + 0xe7,0x55,0x97,0x4a,0x76,0xcd,0x5a,0xf6,0x96,0x39,0x40,0x11,0x7a,0x30,0xe8,0x4b, + 0x3a,0x87,0xc2,0xa4,0x99,0x95,0x20,0x92,0x8e,0x57,0xe5,0x8c,0xc2,0x82,0xfc,0x5b, + 0x26,0x84,0x66,0xfb,0xe6,0xa2,0xfc,0x8b,0x64,0xb6,0x4b,0x91,0x25,0x98,0x55,0x63, + 0xf5,0xfd,0x9e,0xba,0xcd,0xf2,0xb5,0x2d,0x68,0xcb,0xb2,0x6,0x4a,0x49,0xea,0x4a, + 0x2a,0x79,0xc1,0xc8,0x5d,0x59,0xd3,0x15,0x82,0x72,0x84,0x71,0x6c,0xd9,0xb7,0xe7, + 0xda,0x1e,0x91,0x98,0x20,0x47,0xb7,0x24,0xea,0x61,0x49,0xb6,0x63,0x4e,0x4c,0x7f, + 0x8a,0xa4,0x4b,0xed,0x8c,0x20,0x8a,0x6a,0x5a,0x69,0x78,0x56,0x7b,0xfa,0xa5,0x29, + 0xdf,0x3c,0xf1,0xaa,0x7c,0x31,0x21,0x43,0x9,0x2e,0x4f,0xfb,0xdb,0x98,0x73,0xe, + 0xe3,0x95,0xc7,0xb1,0x98,0x53,0x32,0x1d,0x10,0x11,0x9e,0xc0,0x7b,0xd7,0xce,0x9a, + 0xdf,0x7f,0xf7,0x22,0xfd,0xf8,0xed,0x4b,0x34,0x33,0x36,0x84,0x46,0xa3,0x86,0x7a, + 0xbd,0x56,0x7a,0x28,0xe6,0x13,0xc3,0xab,0x4c,0xd6,0x65,0x44,0xb7,0x7c,0xe2,0xfe, + 0x87,0x40,0xf1,0xc3,0x3,0x4d,0x5c,0xbb,0x38,0x47,0x67,0x67,0x27,0x82,0x1d,0x68, + 0x4c,0xf1,0x4a,0x86,0x2d,0x72,0x48,0x9,0xe1,0xaa,0x21,0x46,0xda,0x15,0xfe,0x98, + 0xb1,0xa4,0xef,0x43,0xe5,0x7a,0x1f,0xa1,0xf5,0x50,0xdc,0xc3,0x36,0x38,0xc2,0x29, + 0x7e,0x32,0x17,0x99,0xf2,0xe7,0x17,0xa7,0xe8,0x7f,0xf8,0xb3,0x1f,0x9a,0xb7,0xae, + 0x2c,0xd2,0xcc,0xd8,0x10,0xea,0x5e,0xb7,0xdc,0x4b,0xf6,0xf4,0x4f,0xe1,0x4f,0xaf, + 0x89,0x5e,0xbe,0x77,0x83,0xfd,0x75,0x5c,0x3d,0x37,0x47,0x17,0x16,0xa6,0xf0,0x47, + 0x3f,0x7c,0x9d,0xd6,0xb7,0x76,0xf9,0xe6,0xdd,0x65,0xfc,0xe6,0xeb,0x87,0xfc,0xd1, + 0xcd,0x7,0x58,0xdf,0x3e,0x10,0x41,0x62,0xd4,0x3,0x3e,0x90,0x6a,0x39,0x52,0x69, + 0xd0,0xf9,0x7e,0x8c,0x62,0x34,0x48,0x1c,0x74,0x22,0xb7,0xb7,0x42,0x86,0x66,0xc7, + 0x87,0xb1,0x38,0x37,0x46,0x52,0xfe,0x58,0xc6,0x40,0xff,0xff,0xd3,0x9f,0x5e,0xab, + 0x9a,0x77,0xaf,0x2e,0xd2,0xdc,0xd4,0x8,0x8d,0xc,0x36,0xf1,0x1f,0x7f,0xf1,0x95, + 0x5d,0xd9,0xd8,0xf3,0x4d,0xb6,0x98,0x89,0x9d,0xd5,0x5b,0x2c,0x80,0xde,0x18,0x8e, + 0xdc,0xe2,0xdd,0x5d,0xce,0x6c,0xc,0x99,0x2e,0x13,0x1b,0xeb,0x8e,0x19,0xeb,0x97, + 0x92,0x1e,0xcb,0xa2,0x2,0x35,0x3d,0x99,0x6c,0x94,0xbd,0xda,0xa4,0xe6,0x3c,0x52, + 0x21,0x6a,0x65,0x59,0x8d,0x54,0x98,0xe6,0xa,0x1f,0x85,0xc,0xff,0xaa,0x96,0x4d, + 0x5f,0xca,0x58,0x94,0x34,0xac,0xac,0xca,0x70,0xc0,0xf3,0x45,0x61,0x89,0xc5,0xa1, + 0xc4,0x1,0xa7,0x17,0xd,0x5f,0x3d,0x9,0x2e,0xde,0x40,0xde,0xe8,0x3a,0xf3,0x13, + 0x2c,0x4e,0x8f,0x5c,0x5e,0x6e,0x4b,0xd8,0x84,0x28,0x84,0x89,0x14,0xdd,0xf1,0x0, + 0xe5,0xf3,0x23,0xe5,0x5f,0x32,0x18,0x9d,0xca,0x33,0xe1,0x14,0xe6,0x2f,0x8a,0x2a, + 0x4b,0x16,0x23,0x8b,0xc4,0xb5,0x42,0xd3,0xa4,0x77,0xd6,0x2a,0x6e,0x50,0x53,0xcf, + 0x12,0xd8,0x21,0xe4,0x6b,0xca,0x71,0x8f,0xf5,0xe3,0x51,0x31,0xa6,0x2a,0xdf,0x9d, + 0xf3,0x29,0x3b,0xd9,0x20,0x49,0xc2,0x9d,0xb,0x2d,0x12,0x1,0x3d,0x4,0x16,0x4, + 0xe,0xa9,0x26,0x0,0xb3,0x8f,0x3a,0x36,0xde,0x1b,0x43,0x4e,0x20,0xfe,0x32,0x34, + 0x32,0x9a,0xd4,0x97,0x68,0x3f,0xb0,0xb3,0x9,0x71,0x90,0xbe,0x40,0x57,0x9c,0x4, + 0x2d,0x24,0x77,0x51,0x30,0x36,0x91,0x86,0x27,0x21,0xed,0xcb,0xcb,0xd7,0x18,0xc9, + 0x5d,0xcb,0x6b,0x79,0x63,0x1,0xaa,0x56,0xc,0x9d,0x9e,0x1b,0xa7,0x37,0x2f,0x2d, + 0xd0,0xf,0xae,0x9f,0xa3,0x77,0xaf,0x2e,0xd2,0xc5,0xc5,0xe9,0x9e,0xd3,0x78,0x3e, + 0x31,0xc8,0x49,0x39,0xc0,0xc1,0x72,0x92,0x96,0x7,0x6a,0xcb,0x11,0xd8,0x84,0xdb, + 0xa0,0x27,0x80,0x11,0xd0,0x68,0xd4,0xb,0x53,0x54,0xce,0x6e,0xcf,0xa7,0x77,0x39, + 0xdd,0xf6,0x35,0xea,0x98,0x9f,0x1a,0xa1,0xc5,0xe9,0x51,0x3c,0x5b,0xdb,0x45,0xc7, + 0x76,0x21,0x75,0x5b,0xc9,0x26,0x3a,0xde,0xb4,0x1c,0x5e,0x7c,0x8e,0x61,0x2c,0x7e, + 0xb9,0x1e,0xbd,0x96,0x4d,0x2c,0x20,0x49,0xbf,0x1f,0xa2,0xea,0x82,0x9d,0xab,0xd8, + 0x97,0x13,0x15,0x8c,0x9f,0x2f,0x9f,0x99,0x32,0x7f,0xf8,0xbd,0xd7,0xe8,0x47,0x6f, + 0x5d,0xa0,0x53,0x53,0xa3,0xa5,0xc5,0xfb,0x9f,0x62,0xb1,0x29,0x43,0xb,0xf2,0xc6, + 0xae,0x52,0xa9,0xa0,0xbf,0x52,0xc1,0x40,0x5f,0x1d,0x63,0xc3,0xfd,0x38,0x35,0x35, + 0x42,0x63,0xc3,0x83,0x98,0x9d,0x18,0xc1,0x85,0x85,0x49,0xfa,0xea,0xfe,0xa,0xdf, + 0x79,0xf4,0x9c,0x9f,0xae,0x6e,0xfb,0x24,0xd5,0x80,0x6d,0xb8,0x17,0xdb,0x5a,0x66, + 0x32,0x86,0x54,0x5e,0x84,0x2,0x14,0x63,0xf3,0x1e,0x0,0xe2,0x28,0x91,0x8b,0x64, + 0x79,0xdf,0x9,0x8f,0xc,0x36,0x31,0x35,0x31,0x44,0x3,0xfe,0x3a,0xea,0x85,0x7a, + 0xfc,0x63,0x40,0xdf,0xf9,0xeb,0xf3,0x2a,0xcc,0xf8,0x5e,0x7c,0x86,0x17,0x29,0x3b, + 0xf2,0xd5,0x4b,0x2f,0xb4,0xaa,0xec,0x31,0x54,0xab,0x15,0x9c,0x9e,0x1d,0xc3,0x1f, + 0x7d,0xff,0x2a,0x75,0xba,0xd6,0xfc,0xfb,0x9f,0x7d,0x69,0x37,0xb6,0xf,0xa2,0x9f, + 0x1,0xc5,0x9b,0xd3,0x10,0x60,0x93,0x5f,0x70,0xb0,0x35,0x76,0x59,0xaa,0xa5,0x83, + 0x9f,0x57,0xdd,0xb0,0x60,0x69,0xfb,0x8f,0xb3,0xca,0x40,0x40,0x4f,0x8a,0x71,0xf, + 0x74,0x5b,0xbd,0xe7,0xd9,0x17,0x15,0x7c,0x49,0x32,0x28,0x36,0x40,0xee,0x19,0x8f, + 0x5c,0x0,0xc6,0xc1,0x99,0x27,0xc1,0xd6,0xc1,0x3b,0x9d,0xa3,0xd3,0x1a,0x17,0xf6, + 0xed,0xac,0x26,0x54,0x2a,0xd5,0xa4,0xa9,0x98,0x91,0x62,0xd2,0x88,0xfa,0x56,0x3d, + 0x65,0xe6,0x26,0x64,0xd9,0xa1,0x10,0x2d,0x57,0xc5,0xc4,0x98,0xf1,0xb0,0xb8,0x4, + 0xee,0x66,0x31,0xc0,0xc7,0x9e,0x2b,0x58,0xc5,0xca,0x64,0xb5,0x40,0x76,0x61,0x91, + 0xdb,0x1,0xfd,0x78,0xd2,0x7a,0x81,0xa3,0x26,0x32,0x4b,0x7c,0x89,0x72,0x67,0xce, + 0x1d,0xd4,0x44,0x2e,0x61,0xa1,0x31,0x50,0xbf,0x47,0x5a,0x72,0x50,0x21,0xdd,0x8d, + 0x54,0x52,0x4f,0x26,0x37,0x2c,0xeb,0x2,0x33,0xc6,0x3f,0x17,0xb0,0x10,0x2a,0x80, + 0xe8,0x5,0xbe,0x83,0x8f,0x32,0x8,0x33,0x9d,0x82,0xfa,0xb3,0x55,0x7b,0x66,0xef, + 0x2a,0xa2,0x48,0xd,0x29,0xa5,0xbd,0x89,0xf1,0xa8,0x90,0xa9,0x68,0x61,0x3a,0x17, + 0xa4,0xb8,0xa8,0x7f,0xe,0x3c,0xf8,0x64,0x85,0x99,0x5c,0x66,0x38,0x2c,0x37,0xfd, + 0x3,0xa8,0x55,0x2b,0x34,0x3f,0x3d,0x4a,0x7f,0xfe,0x7,0x37,0xcc,0x9f,0xff,0xde, + 0xd,0x9a,0x9d,0x18,0x42,0xc3,0x4f,0xe4,0xf2,0xb0,0x78,0x15,0x88,0xb7,0x97,0x2c, + 0xad,0xd3,0xe9,0xe2,0xa0,0xd5,0xc6,0xce,0x7e,0xb,0x7b,0x7,0x47,0xc9,0x12,0x53, + 0x5c,0xd6,0xf5,0x5a,0x15,0xa3,0x83,0xfd,0x18,0x1b,0x6a,0xc6,0xc2,0x9e,0x6b,0xd2, + 0x7b,0xc1,0xc6,0xf2,0x63,0x73,0x93,0x23,0xb8,0x76,0xf1,0x14,0xed,0x1d,0x1e,0x63, + 0x7b,0xaf,0x5,0x38,0x16,0xf,0x27,0xb2,0x2a,0xb9,0x30,0xa9,0x60,0x5,0xda,0xf5, + 0x3e,0xa1,0x5e,0x9a,0xe6,0xfc,0x45,0xc3,0x1d,0x24,0xf6,0x7c,0xa9,0x86,0x7b,0xb7, + 0x37,0x93,0x92,0xb7,0x99,0x24,0xa6,0x9c,0xec,0x61,0xd,0x51,0xb3,0x5e,0xa5,0x7f, + 0xf1,0x3b,0xaf,0xd3,0xbf,0xfa,0xd1,0x75,0x9a,0x19,0x1b,0xea,0x9,0x77,0xff,0x7f, + 0x65,0x72,0xcc,0x1f,0x6b,0x59,0x53,0x72,0x66,0x6e,0x1c,0x67,0xe6,0xc6,0xe9,0xa7, + 0xdf,0xbb,0x84,0x4f,0x6e,0x3d,0xc1,0x7f,0xfc,0xd5,0xd7,0xf4,0xd7,0x1f,0x7d,0xcb, + 0xcf,0xd6,0x76,0x38,0x71,0x4a,0xdc,0xc9,0x1a,0x39,0x89,0x24,0xe9,0xa9,0x1e,0x4f, + 0x12,0x33,0x83,0xb2,0xb4,0x4b,0x14,0x2f,0x19,0x9a,0x80,0xe1,0xc1,0x3e,0x1a,0xee, + 0x6f,0x26,0xb2,0xef,0xff,0x43,0xaf,0x69,0xaf,0x2,0x5c,0xa6,0x47,0xef,0x55,0xd4, + 0xf3,0x62,0xdd,0xab,0x90,0xff,0x97,0x20,0x37,0x65,0xd,0x98,0xb5,0x16,0xef,0x5d, + 0x3b,0x43,0x8d,0x46,0x15,0x5f,0xde,0x5d,0xa2,0xcd,0x9d,0x43,0xff,0x16,0xd8,0x94, + 0x7c,0x4a,0x0,0xd9,0x90,0x56,0x28,0xea,0x45,0x58,0x2d,0xb1,0x5c,0x3c,0x3b,0x1e, + 0x23,0xa4,0x7f,0x0,0x31,0xa1,0x9b,0xd1,0x7e,0x39,0xd7,0x58,0xcb,0xe2,0x8,0x15, + 0x37,0x5d,0x88,0xd9,0xd6,0xa8,0x6f,0x69,0xad,0x8f,0x68,0x8e,0x20,0x28,0x87,0xe1, + 0xaa,0x9a,0x4f,0x6e,0x32,0x51,0x4b,0xb1,0xa8,0x73,0x12,0x54,0x66,0x82,0xc2,0xf9, + 0xc7,0x2,0xf6,0x4f,0xa4,0x62,0xe3,0xe4,0x6e,0x81,0xe5,0x8e,0x5c,0xa0,0xc8,0x5c, + 0x98,0xe0,0x49,0x33,0xfc,0x4a,0x92,0xca,0x74,0x21,0xcc,0xb3,0xc3,0x20,0xa3,0x26, + 0xa,0xc4,0xf1,0x3c,0xea,0x33,0x3e,0x46,0xb9,0xbb,0xca,0xb,0x36,0x32,0x0,0x81, + 0x55,0x11,0x26,0x69,0xce,0x4e,0x62,0xea,0x56,0x28,0x3e,0x51,0x66,0xb9,0x4e,0x5, + 0x1a,0x41,0x41,0xef,0x1f,0x59,0x4b,0xe9,0xb,0xa5,0xbc,0x90,0x64,0x58,0x8d,0x5a, + 0x71,0x17,0xe5,0x6f,0x62,0x82,0xe7,0x32,0xa7,0x3e,0x52,0x1d,0x54,0xb6,0x60,0x31, + 0x44,0xf2,0x1,0x8,0xfd,0x83,0x92,0x3,0x90,0x82,0xcd,0x49,0x11,0xfb,0x48,0x38, + 0x41,0x4,0x99,0x61,0x40,0x6e,0x39,0x66,0x9b,0x23,0x45,0x73,0x1a,0x91,0xf0,0x15, + 0x5d,0x4a,0x42,0x64,0xa7,0x9,0xc9,0xce,0x11,0x6e,0x67,0xf,0xbd,0x13,0xfb,0x49, + 0xdf,0x97,0x35,0x0,0x18,0xe8,0x6b,0xd0,0x3b,0xaf,0x9f,0x36,0xff,0xd5,0x8f,0xaf, + 0xd3,0xbb,0x57,0x4f,0xd3,0xc2,0xf4,0x88,0x92,0x93,0xf5,0x2a,0xa4,0x12,0x6a,0x2f, + 0x3b,0x68,0xb6,0x76,0xf,0xf1,0x6c,0x7d,0x7,0x4b,0xab,0xdb,0x58,0x5a,0xdb,0xc6, + 0xca,0xfa,0x2e,0x56,0xb7,0xf6,0x70,0x70,0xd4,0x46,0xb7,0x6b,0x95,0xc8,0x30,0xbc, + 0x42,0x86,0x8,0xf5,0x7a,0x5,0x83,0x7d,0xd,0x8c,0xc,0xf4,0x61,0x7c,0x74,0x0, + 0x93,0x23,0x3,0x98,0x9b,0x1c,0xc6,0xa9,0xa9,0x31,0xcc,0x4f,0xe,0xa1,0x5e,0xaf, + 0x95,0x4e,0xeb,0x72,0x7a,0x99,0x18,0x19,0xc0,0x85,0x53,0x53,0x74,0xf3,0xce,0x12, + 0x6f,0xef,0x1f,0x5,0x34,0x29,0xb5,0x9d,0x1c,0x51,0x72,0x96,0x83,0x1f,0x8c,0xb8, + 0x10,0xa5,0x43,0x70,0x30,0x9b,0xc9,0xe2,0x79,0x23,0xb1,0x30,0xb9,0x1c,0x93,0x44, + 0xc3,0xc8,0x3,0x74,0x8b,0xb3,0xe3,0x74,0xfd,0xe2,0x29,0xba,0x72,0x76,0x86,0xf2, + 0xd7,0xef,0x55,0xb,0x8e,0x44,0x40,0x5e,0x75,0xef,0xfd,0x8f,0x9,0xe1,0x97,0xa1, + 0x24,0xb2,0x78,0xe4,0x13,0x6b,0x78,0xc,0x95,0x4a,0x5,0xd7,0x2e,0xce,0x53,0xa3, + 0x51,0xc5,0xdc,0xe4,0x30,0x7e,0xf6,0xe9,0x5d,0xfc,0xea,0xcb,0x87,0x21,0x59,0x35, + 0xb9,0x5c,0xe4,0x41,0x3d,0x19,0xcf,0x86,0x72,0xaf,0xab,0xc0,0x63,0xcc,0x66,0xbb, + 0x4e,0xd7,0xa2,0x1b,0xb2,0x47,0x4a,0xae,0x8d,0x7f,0xcc,0x82,0xce,0xcc,0xd8,0x3b, + 0x3c,0xc6,0xf2,0xfa,0xe,0x9e,0xad,0xef,0x60,0x7d,0xeb,0x0,0xfb,0x87,0x2d,0xec, + 0x1d,0x1d,0x63,0xef,0xe0,0x18,0x7,0x47,0xc7,0x68,0x77,0xba,0xe5,0x9e,0x20,0x2, + 0x9d,0xaa,0x18,0x42,0xb3,0x5e,0xc3,0xf8,0xc8,0x0,0x26,0x86,0xfb,0x31,0x3e,0x32, + 0x80,0xe9,0xb1,0x21,0x4c,0x8d,0xd,0x62,0x66,0x7c,0x8,0xcd,0x46,0xad,0x74,0xdd, + 0xf1,0x22,0x46,0xbe,0xfc,0x7c,0x40,0xb1,0xe6,0x26,0x47,0xe9,0x77,0xdf,0xba,0x40, + 0xad,0xe3,0xe,0xdd,0xba,0xbf,0xcc,0x9a,0xa8,0x10,0x52,0x1d,0xe1,0xd8,0xeb,0xd1, + 0xb1,0x2c,0xf9,0xd0,0x19,0x43,0xc4,0xd6,0xc1,0x85,0xec,0x5a,0x72,0x8f,0xd6,0xfb, + 0xb7,0xc1,0x10,0x73,0x84,0xda,0xbe,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xc1, + 0xca,0xcd,0xa9,0x70,0xa3,0xe5,0x68,0xa2,0x46,0xe9,0x27,0x4b,0x76,0x3b,0xa9,0x7a, + 0x23,0x13,0x43,0x25,0xf3,0x3a,0x7c,0x4d,0x9e,0x28,0x2a,0xb8,0xcf,0x4e,0x87,0x9e, + 0xc7,0x14,0xca,0x74,0x34,0xc9,0x6e,0x96,0xa8,0x3b,0x41,0xaf,0x70,0xa3,0x69,0xbc, + 0xd2,0x86,0xa7,0xe9,0x94,0x62,0x62,0x99,0x48,0x5d,0xb,0xd9,0x73,0x48,0x29,0x6a, + 0xfa,0x35,0xa6,0x12,0xb6,0x5f,0x2a,0x4b,0xca,0x50,0xe6,0x25,0x0,0x7,0x4b,0xb3, + 0x66,0xc1,0x46,0x7,0x17,0x57,0xd4,0xa4,0x4d,0xe5,0xa5,0x99,0x4,0x18,0x5a,0x67, + 0x9e,0x60,0x67,0x61,0x1a,0xaa,0x12,0xcb,0x42,0x20,0x4c,0x7a,0x1e,0x24,0x50,0x8c, + 0x90,0x96,0x93,0x6f,0x13,0x58,0x6,0xcc,0xc4,0x86,0x20,0x11,0xc,0xe5,0xf3,0x11, + 0x49,0x93,0xa2,0xf5,0xe1,0x12,0x8a,0x82,0xf6,0xfe,0x65,0x29,0x89,0xf5,0x56,0x5e, + 0xb9,0xbf,0x73,0xfc,0xa1,0xa1,0xd0,0x1,0xc8,0xfc,0x97,0x54,0x7e,0x3c,0x9,0xb6, + 0x9f,0x1b,0x3f,0x90,0x91,0xe,0x7d,0xda,0x7a,0xb4,0xc0,0x50,0x27,0x97,0xb7,0x7, + 0x95,0x59,0xe5,0x94,0x9a,0x23,0x52,0xc9,0x68,0xae,0xa6,0x9b,0x24,0x99,0x22,0x6, + 0xa1,0xe2,0xf7,0xe2,0x1c,0x8a,0xbf,0x8,0x71,0x49,0xb2,0x2a,0x8c,0xe,0xf5,0xd1, + 0x8d,0xcb,0xb,0xe6,0x8f,0x7f,0x70,0x95,0xfe,0xec,0xc7,0xd7,0xa9,0x5e,0xaf,0xbe, + 0xd2,0xa1,0x2d,0xf,0x89,0xf0,0xf1,0xa3,0xe3,0xe,0x8e,0xdb,0x27,0x68,0x9f,0x74, + 0xb1,0xbe,0xbd,0x87,0x7,0xcf,0x36,0x71,0xff,0xd9,0x6,0xee,0x3f,0x59,0xc3,0x9d, + 0xa7,0xeb,0x78,0xf2,0x7c,0x13,0x7,0xad,0x76,0x91,0x30,0xda,0x63,0xeb,0x54,0xaf, + 0x56,0x30,0x3f,0x39,0x8a,0xf9,0xa9,0x11,0x9c,0x99,0x1b,0xc7,0x85,0x85,0x49,0x5c, + 0x39,0x33,0x8d,0xf3,0xa7,0x26,0x31,0x36,0xdc,0xaf,0x34,0xb9,0x39,0xac,0x3f,0x34, + 0xd8,0xa4,0xd9,0xa9,0x61,0x34,0x1b,0xf5,0xac,0x21,0xb,0xa8,0x89,0x4d,0xf2,0x86, + 0x20,0x77,0xb0,0x72,0x9b,0x27,0xee,0x66,0x49,0xc8,0x91,0x64,0x38,0x9f,0x21,0x9e, + 0x3c,0xe4,0x62,0x66,0x4e,0xe2,0x27,0x10,0x68,0x7c,0x64,0x90,0x2e,0x2d,0x4e,0xe1, + 0xf4,0xcc,0xb8,0x2a,0x74,0xaf,0x5a,0x60,0xe4,0x6b,0x9e,0x93,0x1,0x4f,0x4e,0x3a, + 0x38,0xe9,0x32,0xba,0xd6,0x99,0x8d,0x9c,0x9c,0x74,0x9d,0xab,0x5b,0xd7,0xc2,0x76, + 0xbb,0xbd,0xb0,0xcc,0x97,0xff,0x4e,0x76,0xbd,0x4d,0xb5,0xe2,0xcc,0x56,0xfa,0x1a, + 0x75,0x34,0xea,0x15,0x34,0x3c,0xc1,0xac,0x6c,0x8d,0x52,0x36,0x5d,0x86,0x7f,0xf, + 0xf4,0xd5,0x71,0xe3,0xf2,0x2,0x26,0xc7,0x6,0x69,0xa8,0xbf,0x89,0x8d,0x9d,0x43, + 0xbe,0xfb,0x64,0xd,0xd6,0xed,0x68,0xa1,0xbd,0x14,0x5,0x9a,0x15,0xc9,0x4b,0x86, + 0xa,0xe7,0x1a,0x65,0xb4,0x1f,0xff,0x82,0xef,0x1d,0x1d,0x63,0x73,0xe7,0x10,0xbb, + 0x7,0x2d,0xc,0xf,0x34,0x5f,0xd8,0x98,0x96,0x41,0xdd,0x2f,0x93,0xad,0xc9,0x46, + 0x8c,0x88,0xb0,0xb9,0x73,0x0,0x27,0xe1,0x5b,0xc2,0xa3,0x95,0xd,0xec,0xec,0xb5, + 0xb0,0xb9,0x77,0x88,0xed,0xdd,0x43,0x1c,0x77,0xba,0xb9,0xeb,0x73,0x4f,0x10,0x9a, + 0x0,0x4c,0x8f,0xf,0x61,0x6e,0x62,0x18,0xb3,0x93,0xc3,0x38,0x35,0x35,0x82,0xc5, + 0x99,0x31,0x2c,0xce,0x8e,0x61,0x7a,0x74,0x10,0x43,0x3,0xcd,0x14,0x60,0x24,0x72, + 0xe,0x7a,0xc1,0xff,0xf9,0x7b,0x4,0x0,0x7d,0x8d,0x1a,0x7e,0x78,0xfd,0x3c,0x2d, + 0xaf,0xed,0xd2,0xad,0xfb,0xcb,0xaa,0x3b,0x71,0x39,0xf5,0x21,0x1d,0x3a,0x26,0x7c, + 0x3a,0x44,0xcf,0xb1,0xda,0x93,0x54,0x19,0xd2,0x8,0x94,0xa2,0x97,0x50,0xaf,0x85, + 0x79,0x48,0xe7,0x21,0xc5,0x5c,0xd7,0x12,0xee,0x54,0xf7,0x58,0x91,0xaa,0x35,0xc3, + 0x22,0x8b,0xab,0xce,0xa,0xbe,0x44,0x61,0xab,0xc5,0x9d,0x34,0x27,0x4f,0x4,0x15, + 0xb6,0xce,0x2a,0x7b,0x9b,0x38,0xe5,0x81,0x23,0x42,0xd1,0x92,0x1f,0x90,0x8,0x69, + 0x1a,0xca,0xcd,0xb5,0xd6,0x5c,0x20,0x7,0xa4,0x89,0x94,0x35,0xc3,0x5d,0xc6,0x7d, + 0x72,0x19,0x80,0xc0,0x29,0x61,0x29,0x90,0x75,0x43,0x21,0xec,0x91,0x70,0xc6,0x9c, + 0x40,0x30,0x48,0xe4,0x1b,0x5a,0xe,0x97,0x80,0x9,0x93,0xd8,0x5b,0x61,0xf9,0x9b, + 0xf1,0xc5,0x5d,0x9c,0xb1,0x89,0xa2,0xc2,0x20,0xdb,0xe5,0x8c,0x0,0x28,0x15,0xfc, + 0x99,0xf9,0x8a,0x92,0xe3,0x73,0x82,0xe9,0xb,0x72,0xc0,0x2,0x23,0x81,0x49,0x87, + 0xab,0x99,0x12,0x66,0xaf,0x4c,0xb1,0xb,0xb8,0x93,0x2c,0xf6,0x92,0x79,0x5f,0xb4, + 0xa8,0xd7,0xa4,0xc,0x5,0xaf,0x43,0x34,0x4d,0x48,0x5c,0xe8,0x2,0xe7,0x9d,0xb2, + 0x28,0xbc,0xc4,0x34,0x8f,0xc5,0x43,0xc8,0xd4,0x52,0x4e,0x39,0x52,0x34,0x6a,0xa4, + 0xd4,0x89,0x53,0x6,0x51,0xa0,0x26,0x3d,0xc7,0x85,0x46,0x9a,0x31,0x3b,0x31,0x4c, + 0xdf,0x7f,0xe3,0x9c,0xf9,0x37,0xff,0xfc,0x6d,0xba,0x71,0x79,0x91,0x1a,0x8d,0xda, + 0x2b,0x11,0xd3,0xca,0x20,0xf8,0xdd,0x83,0x16,0xbe,0x7b,0xb4,0x8a,0x2f,0xee,0x2c, + 0xe1,0xf3,0x3b,0x4f,0xf1,0xf0,0xd9,0x6,0xb6,0xf7,0x8e,0xd0,0x3a,0xee,0xe0,0xa4, + 0xd3,0xc1,0xf1,0x49,0x17,0x27,0x9d,0x4e,0x46,0x6a,0x11,0x21,0x1f,0x25,0x47,0x5e, + 0xfb,0xa4,0x8b,0xa7,0x6b,0xdb,0x58,0xdd,0xda,0xc5,0xcd,0x7b,0x4b,0x68,0xd4,0x6a, + 0x98,0x1a,0x1b,0xc4,0x9b,0x97,0x4e,0xe1,0xbf,0xfd,0xa3,0x77,0x71,0xfd,0xd2,0xa9, + 0x9e,0xb2,0xb8,0x66,0xdd,0xf9,0xc4,0x57,0x2a,0x49,0xb6,0x92,0xc6,0x88,0xd4,0x2, + 0x8b,0xd5,0x52,0xd8,0xc,0xb,0xfd,0xa7,0x86,0x93,0xc8,0x18,0x8a,0xa1,0x39,0x1c, + 0xfd,0x4f,0x95,0xa9,0x38,0xa3,0xc8,0xb3,0x99,0x9e,0x18,0xa2,0x2b,0x67,0x67,0xa8, + 0xd1,0xa8,0xf5,0x94,0xa5,0xbd,0xca,0x24,0x98,0xef,0xaf,0x5b,0xed,0x2e,0x56,0x37, + 0xf7,0xf0,0x7c,0x73,0xf,0xab,0x5b,0x7b,0x58,0x59,0xdf,0xe1,0xa7,0xcf,0x77,0xf0, + 0x74,0x7d,0x1b,0x6b,0x9b,0x7b,0x38,0x6a,0xb5,0x3,0x71,0x5f,0xad,0x4,0x4b,0x74, + 0xa6,0x72,0x50,0x20,0xf6,0xe9,0x76,0xd5,0x8a,0xc1,0xdc,0xe4,0x8,0x2e,0x2e,0x4e, + 0xe1,0xfa,0xc5,0x79,0x7a,0xe3,0xfc,0x1c,0x2e,0x9d,0x9e,0x7e,0xe9,0xe4,0xde,0x4b, + 0xcb,0xcd,0xcc,0x38,0x35,0x35,0x8a,0xdf,0x7d,0xeb,0x2,0x31,0x80,0x7f,0xf7,0xb3, + 0x9b,0xf8,0xed,0xd7,0x8f,0x38,0xbb,0x23,0x88,0x33,0x54,0xb6,0xac,0x42,0x94,0xa9, + 0x64,0x1,0xc0,0x2,0xd8,0x3b,0x68,0xe1,0xbb,0x27,0xab,0xf8,0xe6,0xe1,0x73,0x8c, + 0xc,0x34,0x31,0xe8,0x75,0xf5,0xbd,0xa,0xfb,0xff,0x5d,0xdd,0xf9,0xf3,0x8d,0x3d, + 0x7c,0xf4,0xf5,0x23,0x7c,0xfa,0xed,0x63,0x2c,0x6f,0xec,0xc5,0x2,0xdb,0xb5,0x2c, + 0xb1,0xbf,0x9e,0x51,0x10,0x2c,0x86,0xad,0xf5,0xed,0x3,0x6c,0xef,0x1f,0xe1,0xee, + 0xd3,0x75,0xd4,0x6b,0x15,0x54,0x2b,0x6,0xd5,0x4a,0x5,0x23,0x43,0x4d,0xcc,0x4f, + 0x8d,0xe2,0xb5,0xd3,0xd3,0x78,0xeb,0xf2,0x29,0x7c,0xef,0xda,0x59,0xc,0xf5,0x9b, + 0x9e,0x64,0xc5,0x5e,0xef,0x4f,0x7f,0xb3,0x86,0xd7,0xcf,0xcd,0xd2,0x6f,0x67,0xc6, + 0xfc,0x5,0x6b,0x90,0x8c,0x7f,0x39,0xd1,0x82,0x85,0x1d,0xb8,0x4d,0x37,0x40,0xda, + 0xa7,0xab,0xec,0x34,0x9b,0xee,0x65,0x96,0x30,0x75,0x66,0xf5,0x45,0x3a,0x1a,0xab, + 0x90,0x91,0x11,0x25,0x28,0x22,0xc0,0xf,0x24,0x90,0xd9,0x44,0xb8,0x63,0xce,0xf8, + 0x60,0x72,0x85,0xed,0x2f,0x8a,0xaa,0x4c,0x85,0x89,0xfb,0x5d,0x95,0xf,0x5e,0x64, + 0xab,0x13,0x67,0x82,0x77,0x7a,0x71,0x94,0x27,0x95,0x5c,0x9f,0xd2,0x77,0x9c,0xca, + 0xc,0xe2,0xa0,0x13,0xd9,0x39,0x2b,0x26,0xaa,0xd6,0xb0,0x82,0x3,0xf5,0xd4,0x98, + 0xeb,0x9f,0x4b,0x78,0x78,0x39,0x10,0x4f,0x94,0xe3,0xe3,0xa5,0xb1,0x5a,0x2,0xb2, + 0xa7,0x72,0x32,0x22,0x6b,0x68,0x5a,0x53,0x19,0xa8,0xbc,0x6d,0x55,0xad,0x77,0x68, + 0x81,0x8c,0x7a,0x81,0x64,0xcd,0x2e,0x7c,0x2b,0xe5,0x8c,0xb,0xcd,0x9e,0x2f,0x90, + 0x36,0x4c,0xc,0xde,0x28,0xb8,0xb0,0x66,0x17,0x46,0x96,0xc2,0xaa,0xaf,0x2c,0x52, + 0x49,0x69,0xf2,0xc1,0x10,0x21,0x7,0xec,0x23,0x1c,0x64,0xd4,0x65,0x95,0x1c,0xc6, + 0x52,0x16,0x79,0xb2,0x65,0xd,0xda,0xe7,0xa8,0x3d,0x37,0x52,0x97,0xae,0x5c,0xcb, + 0x5c,0x74,0xa5,0xb8,0xfa,0xdd,0x6b,0x31,0xd8,0x6c,0xd0,0xfb,0x6f,0x9c,0x35,0x7f, + 0xfa,0xe3,0x6b,0xf4,0xce,0xd5,0xd3,0xd4,0xc8,0xc2,0x50,0xf2,0x49,0xb0,0xec,0xe0, + 0xdb,0xdd,0x3f,0xc2,0xe3,0x95,0x4d,0x3c,0x59,0xdd,0xc6,0xa3,0xe5,0x2d,0x3c,0x78, + 0xb6,0x8e,0x7,0x4b,0x1b,0xf8,0xee,0xe9,0x1a,0x76,0xf7,0x5b,0x3a,0xb3,0x86,0x4b, + 0xee,0xd,0x75,0x55,0xe7,0x86,0x4b,0x88,0xb1,0xa9,0x87,0x5d,0x77,0xa4,0xec,0xa1, + 0x8d,0xf5,0x9d,0x7d,0xec,0x1d,0x1e,0xe3,0xea,0xd9,0x19,0x8c,0xe,0xf7,0x63,0x6e, + 0x62,0x28,0x22,0x5,0x92,0x8c,0xd7,0x3e,0x71,0xd6,0x98,0xdd,0xae,0xd,0x91,0xe9, + 0x2a,0xcb,0x20,0xdc,0xc6,0xd1,0x2a,0xcb,0xba,0xc6,0xd3,0xb9,0x9c,0x24,0xf7,0x20, + 0x89,0x96,0x85,0x12,0x6f,0xc8,0xad,0x2d,0xdc,0x65,0xe1,0xd2,0xcf,0xa3,0x83,0x72, + 0x58,0xd,0x71,0xf0,0x6c,0x7,0x3a,0x1d,0x8b,0xd6,0xf1,0x49,0xec,0x6b,0x5f,0xe6, + 0x46,0xd6,0x6b,0x1a,0x3c,0x3e,0xe9,0xe0,0xc9,0xca,0x16,0x9e,0x6f,0xee,0x62,0x63, + 0xf7,0x10,0x6b,0x9b,0xfb,0xd8,0xdc,0x3d,0xe0,0xcd,0x9d,0x43,0x6c,0xee,0x1e,0x62, + 0x6b,0xf7,0x10,0x6b,0x5b,0x7b,0x58,0xdd,0xda,0xe3,0xd6,0x71,0x57,0xd1,0x39,0x23, + 0x32,0x96,0x5b,0x4a,0x17,0x40,0x12,0x12,0xe1,0x2f,0x84,0x27,0x2b,0x5b,0xf4,0x74, + 0x75,0x1b,0x8f,0x57,0x36,0xf9,0xd6,0xfd,0x15,0x9c,0x9e,0x1d,0xa3,0x99,0x89,0x61, + 0xcc,0x8c,0xf,0x62,0x66,0x7c,0x18,0x93,0x23,0x3,0xa8,0xd5,0xaa,0x85,0x86,0x23, + 0x7f,0x4e,0xf2,0x1a,0x3a,0x3d,0x3b,0x8e,0x1f,0xbf,0x5,0xda,0xd8,0x3e,0xe0,0x27, + 0xcf,0xb7,0x69,0x75,0x63,0x97,0x2d,0xa3,0x50,0xf4,0xa0,0xf2,0x1f,0xa,0x3e,0xda, + 0x4a,0xc0,0x96,0xfb,0x53,0x3e,0x5b,0xdd,0xc1,0x7f,0xf8,0xf9,0x97,0x58,0x59,0xdf, + 0xc1,0xe5,0xc5,0x69,0x8c,0xc,0x35,0xd1,0x6c,0xd4,0x60,0xc8,0xc0,0x18,0x77,0x4d, + 0x5b,0x66,0x1c,0xb7,0x3b,0x38,0x6c,0x9d,0xe0,0xf0,0xb8,0x8d,0xa,0x11,0x2e,0x2e, + 0x4e,0x61,0x72,0x74,0xf0,0x95,0x89,0x6c,0x0,0xb0,0xb9,0x77,0x88,0xdb,0x8f,0x9e, + 0x63,0x69,0x75,0x17,0x96,0xb9,0xe4,0x8,0xd3,0x6a,0x29,0x49,0xe6,0x65,0x85,0x70, + 0x32,0xac,0x5,0xda,0xed,0x2e,0xda,0xd4,0xc1,0xfe,0x51,0x42,0x8,0x97,0xd7,0x77, + 0xf1,0x78,0x79,0xb,0x4b,0xcf,0xb7,0xf0,0x70,0x65,0x13,0x77,0x9f,0x6e,0xe0,0xfd, + 0xd7,0x17,0xf1,0xd6,0x95,0xc5,0x97,0xae,0x55,0xe4,0xfa,0x8c,0x88,0x30,0x3c,0xd8, + 0x87,0xd1,0xa1,0x26,0xb4,0xbd,0x1e,0xc0,0x8e,0x94,0x18,0xd3,0xd2,0x92,0x9b,0x68, + 0xfa,0xef,0x98,0xe1,0x9b,0x14,0x3e,0xce,0xbc,0xba,0x2c,0xa8,0x2c,0x37,0x3c,0x95, + 0x3,0x59,0x56,0x6a,0x38,0x97,0x2a,0xb2,0x18,0xf1,0x64,0x4,0x30,0x48,0xbb,0xb2, + 0x66,0xf6,0xe9,0xd2,0xed,0xb4,0x5a,0x8e,0x87,0x50,0x9,0x76,0x2d,0x6d,0x5c,0x11, + 0xa1,0xf9,0xa2,0xee,0xab,0xec,0x2f,0x52,0x1a,0x27,0x6e,0x2,0x1,0x21,0x14,0xbf, + 0x97,0x33,0x6f,0x13,0x2a,0x2e,0x62,0x14,0xb,0x30,0xeb,0xc6,0xb3,0xec,0xed,0x62, + 0x42,0xa9,0xb6,0xc4,0x41,0x49,0xe7,0x94,0x7e,0xb1,0x98,0xaa,0x59,0x70,0x26,0xb2, + 0x5a,0x45,0x6a,0xac,0x67,0x8,0x56,0x9c,0x82,0xb2,0x35,0x1c,0x95,0xf1,0xc,0x20, + 0x9e,0xb,0x89,0xd7,0x97,0xd3,0xf3,0x37,0xd1,0x55,0x2a,0x91,0x33,0xd3,0xce,0x9a, + 0x33,0x62,0xa2,0x7a,0x4d,0x7c,0x46,0x7,0x17,0xa7,0xc6,0x2,0xbb,0xd2,0x63,0x50, + 0x62,0x5f,0x9f,0xec,0x2c,0xb8,0xc8,0x99,0x48,0x12,0x30,0x14,0x19,0xe,0x9a,0xe9, + 0xe8,0x42,0x3e,0x82,0xcd,0xb2,0x91,0x56,0x96,0xde,0x1e,0x54,0x10,0xdf,0xc,0x91, + 0xf,0x9c,0xa6,0x60,0xcd,0xce,0x32,0x42,0x55,0x90,0xb0,0x10,0x19,0xec,0x9e,0xc6, + 0x6e,0x10,0xf5,0xa4,0x83,0x7d,0xd,0xba,0x2a,0x7c,0xc3,0xe5,0x61,0xd0,0x8b,0x41, + 0x9b,0x4f,0xe6,0x1b,0xdb,0x7,0xf8,0xf6,0xd1,0xa,0xfe,0x8f,0x5f,0x7f,0x8b,0xdf, + 0x7c,0xf5,0x8,0xf7,0x9e,0xae,0xa3,0xcb,0xb6,0x98,0x61,0x20,0x7d,0xf9,0x8b,0x9a, + 0x8b,0xac,0xa8,0x50,0x89,0x52,0x43,0x2b,0x6,0xdd,0x14,0xb3,0x8f,0xaf,0x1f,0x2c, + 0xe3,0xf4,0xec,0x18,0xa6,0x46,0x7,0x50,0xa9,0x14,0x49,0x49,0xbb,0xfb,0x47,0xfc, + 0x6c,0x6d,0x87,0x5b,0xed,0x8e,0xe6,0x7a,0x94,0xa8,0x1e,0xe5,0xa,0x9d,0x13,0x12, + 0x17,0x2e,0x24,0x79,0x7d,0x44,0x4f,0xfd,0xe0,0x68,0x22,0x5b,0x4a,0xa,0x5e,0x1, + 0x91,0x4c,0xe7,0xc0,0xc8,0xd5,0xad,0x3d,0xbe,0xfd,0x78,0x8d,0xb6,0x77,0xf,0x79, + 0x61,0x7a,0x94,0xfe,0x4b,0x4c,0x4c,0xe4,0x73,0x5a,0xdf,0x3e,0xc0,0x7f,0xfa,0xf0, + 0x1b,0xfc,0xea,0xcb,0x7b,0xfc,0xed,0xe3,0x35,0xec,0x1d,0xb4,0x9c,0x51,0xa7,0x2a, + 0xf,0xfe,0xce,0x32,0x9c,0xd1,0x3d,0xa4,0x24,0x8c,0x4b,0x1a,0x69,0xcf,0xde,0x67, + 0xbd,0x42,0x3a,0xe9,0x32,0x3f,0x5a,0xde,0xc2,0xa3,0x95,0x4d,0xfa,0xe0,0x93,0xbb, + 0xa8,0x56,0xc,0x5f,0x98,0x9f,0xc4,0x9b,0x97,0xe7,0xe9,0xfd,0x6b,0x67,0xf1,0xd6, + 0xe5,0x53,0xb8,0xb0,0x30,0xf5,0x42,0x4f,0xf3,0xb2,0xeb,0xea,0xf4,0xec,0x38,0x7e, + 0x78,0xfd,0x1c,0xad,0x6c,0xec,0xf0,0x7,0x9f,0xdc,0xa5,0xd5,0xcd,0x3d,0x15,0x90, + 0xa4,0xa7,0x74,0xa9,0x33,0x96,0x2b,0x3f,0x31,0xe0,0x8,0x76,0x10,0x81,0xb0,0x77, + 0xd8,0xa6,0xff,0xf0,0xf3,0x5b,0xf8,0xf8,0xd6,0x13,0xbc,0x76,0x6e,0x16,0xe7,0xe7, + 0x27,0xe2,0x2e,0x3a,0xf4,0xeb,0x47,0xad,0x13,0x6c,0xef,0x1d,0x62,0x79,0x7d,0x17, + 0x3b,0x7,0x2d,0x8c,0xc,0x34,0xf1,0xdf,0xfd,0xc9,0xfb,0x98,0x18,0x19,0x78,0xe5, + 0xf7,0x85,0x99,0xb1,0x77,0xd0,0xc2,0xd2,0xfa,0x2e,0xba,0x92,0x98,0x85,0x32,0x13, + 0xac,0x4c,0x93,0x4d,0x65,0x1,0x58,0x1,0xcc,0x25,0x99,0xdb,0x4,0x30,0x70,0xd8, + 0x3a,0xc1,0xed,0xc7,0x6b,0xb8,0xfd,0x78,0xd,0x1f,0xfc,0xf6,0x3b,0xfc,0xc5,0x9f, + 0xbe,0x8f,0xb7,0xae,0x2c,0xbe,0x32,0xff,0xa1,0x70,0xbd,0x85,0xba,0x63,0xf5,0x31, + 0xef,0xce,0x26,0xab,0x14,0x44,0x2a,0xe3,0x22,0x9e,0xb1,0xc6,0x1b,0x36,0x41,0x57, + 0x58,0x16,0xe6,0x98,0x99,0x69,0x3b,0x95,0x32,0xd7,0xb9,0xc0,0x65,0xa,0x77,0x9f, + 0x52,0x10,0x51,0xfe,0x78,0x48,0xc9,0x4a,0x29,0x33,0x84,0xa9,0x16,0xa0,0xa8,0xfc, + 0x17,0xc7,0x64,0x35,0x16,0xad,0x3b,0x4a,0xa,0x2b,0x50,0x1e,0xf3,0x26,0xa,0x2, + 0xe7,0xa2,0x26,0x2a,0x8f,0xe1,0xcc,0x13,0xbd,0x84,0xdf,0x5,0x40,0x19,0xd1,0x2e, + 0xbc,0xa0,0x62,0x2d,0xc5,0xc5,0x2e,0x11,0xe8,0x35,0x28,0x65,0x31,0xa7,0xf1,0xaa, + 0x13,0xf6,0xb6,0xb1,0x3e,0x19,0xca,0xc8,0xfb,0x91,0x97,0x9d,0xae,0xa,0xd2,0x64, + 0x83,0x40,0x1c,0xa,0xdc,0xa1,0xa8,0x76,0xc8,0x7c,0x80,0x73,0x54,0x40,0x2e,0xdc, + 0x49,0xef,0xda,0x9c,0xb,0x51,0xc8,0x6c,0x12,0x8,0xa,0x85,0x94,0x25,0xc5,0x94, + 0x70,0xdf,0x69,0x65,0x3b,0x4b,0x1a,0xbb,0x23,0x56,0xc7,0x5d,0xb4,0xc1,0x61,0xb1, + 0x18,0x4f,0x77,0x2d,0xb1,0x1e,0xf,0xd2,0xa7,0x42,0xf3,0xa3,0x89,0x3d,0x44,0xa2, + 0x8b,0x8c,0x96,0x95,0xe1,0x82,0x4c,0x50,0x7a,0x7a,0x12,0x3e,0x8a,0xc5,0x65,0x5b, + 0xb9,0x4d,0x3,0x7b,0x1b,0x58,0x16,0x4b,0x71,0x44,0x46,0xbb,0xb4,0x38,0x45,0x34, + 0xa2,0x9,0x24,0x3d,0x26,0xc6,0xc2,0xcc,0x18,0xfd,0x37,0x7f,0xfc,0x9e,0x79,0xff, + 0xda,0x59,0x5,0x1,0xf7,0x3a,0x7c,0xe5,0x64,0x7e,0x74,0xdc,0xc6,0xa7,0xb7,0x9f, + 0xe2,0x57,0x5f,0xde,0xc7,0x67,0xdf,0x3e,0xc5,0xa3,0xe7,0x5b,0x58,0xdf,0xda,0x43, + 0x97,0xad,0x20,0x4a,0x6a,0x8f,0x7c,0x75,0xbb,0xc6,0x74,0xae,0x32,0x25,0x1,0xf7, + 0xb8,0x83,0xb4,0xfe,0xc4,0x32,0x30,0x3e,0x3c,0x88,0x89,0x91,0x81,0xd8,0xbb,0xe4, + 0x64,0xa1,0xfb,0xcb,0x1b,0xf8,0xd5,0x97,0xf,0xb0,0xbd,0x7b,0xc8,0xfa,0x56,0xce, + 0x92,0x6,0x43,0xe1,0xe6,0x62,0xe,0x2,0x93,0x27,0xf8,0x90,0x42,0xfb,0x90,0x54, + 0x1d,0xb2,0x49,0x23,0x2a,0xb6,0xee,0xee,0xad,0xd8,0x3d,0x68,0xd1,0xed,0x47,0xcf, + 0xf1,0xeb,0xaf,0x1e,0x62,0xa0,0xbf,0x81,0x85,0xa9,0x91,0x94,0xb6,0xf5,0xa,0x70, + 0xbb,0xb5,0x16,0xed,0x93,0x13,0x7c,0xf7,0x64,0x15,0x7f,0xf3,0xdb,0xdb,0xfc,0xcd, + 0xc3,0x15,0x74,0x1c,0x6a,0xc1,0xaa,0x3d,0x8e,0xbd,0xb8,0x3,0xda,0x51,0x6c,0x5c, + 0x5c,0x2e,0x4d,0x74,0xb1,0x4c,0xb,0x18,0x5f,0x24,0x59,0xa0,0x51,0xa4,0xdb,0x19, + 0xf7,0xa,0x76,0xbb,0x96,0x1e,0x3c,0xdb,0xc0,0xee,0x61,0x8b,0xbf,0x7b,0xbc,0x86, + 0xbf,0xff,0xf4,0xe,0x5d,0x39,0x3d,0x83,0x1f,0xbf,0x73,0x1,0xaf,0x9d,0x9e,0x46, + 0x30,0x1e,0x2a,0x23,0xfc,0xe5,0x6,0x43,0xaf,0x9d,0x9b,0xc5,0x9f,0x74,0xde,0xa0, + 0x7,0xcf,0x36,0x79,0x75,0x6b,0x4f,0x5b,0x73,0x64,0x8c,0x58,0xa5,0x98,0x95,0xeb, + 0x48,0x19,0xa4,0x18,0x9a,0x7e,0x4e,0xae,0x7e,0x2b,0x1b,0x7b,0x38,0x6a,0x9f,0xe0, + 0xfe,0xd2,0x3a,0xfa,0x9a,0x75,0x54,0x4d,0x2a,0xa6,0x9d,0x8e,0xc5,0x51,0xbb,0x8d, + 0xfd,0xc3,0x36,0xe6,0x27,0x87,0x71,0xfe,0xd4,0x4,0xfa,0x1a,0xb5,0x57,0x86,0xde, + 0xbb,0xdd,0x2e,0xb6,0xf7,0x5b,0x58,0x5a,0xdb,0xc1,0xfe,0x41,0x4b,0x4d,0x9c,0x24, + 0x1a,0x28,0x15,0x30,0x45,0x59,0x98,0x96,0xc,0xbc,0x22,0x94,0x22,0xb8,0x94,0x8f, + 0xb9,0x7e,0x12,0xa8,0x98,0x57,0xbb,0x86,0x64,0x21,0xb7,0xd6,0xe2,0xb0,0x75,0x82, + 0xbd,0xc3,0xb6,0xde,0xc,0xb1,0xb3,0xd3,0xd,0xf6,0xd8,0xb1,0x58,0x86,0x17,0xde, + 0x19,0xc2,0xa5,0xf5,0x6f,0xd8,0x89,0xfb,0x24,0xf5,0x28,0x29,0x26,0x6d,0x19,0xce, + 0xa4,0x7,0x40,0xe6,0x72,0xb3,0x2e,0x69,0xf1,0xa,0xa1,0x2a,0x8d,0x6f,0x24,0x65, + 0x86,0x29,0x4c,0xd1,0xc7,0x3d,0x45,0x64,0x19,0x55,0x4f,0xab,0x71,0x9f,0x27,0x6c, + 0xe5,0x38,0xb3,0x5f,0x25,0x19,0xc0,0x5e,0xc8,0xb,0x15,0xf3,0x7b,0xbc,0x89,0xa8, + 0x50,0xdf,0x3,0x2,0xaa,0x22,0x3e,0x21,0xe8,0x38,0xd2,0x69,0xb5,0x97,0x99,0xb, + 0x51,0x41,0x4c,0x9f,0xa6,0x7d,0x3d,0x9c,0x83,0x62,0x16,0x64,0x86,0x3c,0x70,0x40, + 0x7b,0xb2,0xc7,0x19,0x2f,0xfa,0x58,0x14,0x53,0x91,0x27,0x22,0xb9,0x96,0x8c,0xd8, + 0x44,0x94,0x54,0x29,0x41,0x56,0x24,0x8,0xa6,0x53,0x47,0x47,0xb9,0x66,0x86,0x39, + 0xa9,0xa0,0x96,0xc9,0xf5,0x20,0x7c,0xf4,0xe3,0x4f,0x57,0x79,0xb9,0x54,0x7a,0x23, + 0xe8,0x29,0xd9,0x54,0xbc,0xc6,0x80,0xc3,0xb9,0x97,0x2e,0x3a,0xe,0x38,0x29,0x5c, + 0xe5,0x57,0x95,0x57,0xa0,0x33,0x9,0x28,0x20,0x92,0x52,0x37,0xdf,0xb7,0x26,0xcd, + 0x7a,0xb6,0x1b,0xc9,0x87,0x57,0x45,0x3e,0x4,0x47,0x5d,0xad,0x97,0x41,0xc7,0x5c, + 0xce,0xe0,0xf6,0x16,0x1d,0xe2,0x32,0x8f,0x70,0x4e,0x7c,0x2c,0xff,0xfd,0x61,0xcc, + 0x34,0xc1,0x40,0x9b,0x98,0x40,0xf5,0x6a,0x95,0x5e,0x3f,0x3f,0x47,0x3f,0x7d,0xf7, + 0x32,0x8d,0xe,0xf7,0x17,0xa6,0xa9,0x5c,0x53,0x2b,0x61,0xec,0xa3,0xe3,0x36,0xbe, + 0xba,0xbb,0x8c,0xbf,0xfa,0xf0,0x16,0x3e,0xf8,0xf8,0xe,0x96,0xd7,0x77,0x45,0x1a, + 0x1f,0x29,0xbd,0x4a,0x92,0x62,0x92,0x22,0x1d,0xa8,0x15,0x55,0x41,0xcd,0x92,0xa3, + 0x33,0xfa,0x58,0xb,0x7c,0x8e,0x7a,0xcd,0x60,0x71,0x66,0x4,0x8b,0xd3,0x63,0x31, + 0x8b,0x3a,0x14,0xf5,0xc3,0x56,0x1b,0xcf,0xd6,0x77,0xf0,0xd9,0xb7,0x4f,0xf8,0xd6, + 0x83,0x65,0x3e,0x3e,0xe9,0xea,0x86,0xb2,0xb0,0xc2,0xf7,0xb4,0xd0,0xe0,0x19,0xe7, + 0x5f,0x58,0x16,0xd2,0x88,0x34,0x5d,0x5,0x8e,0x82,0x68,0x9a,0xd,0x29,0xde,0x64, + 0x48,0x8a,0x7,0x69,0x58,0x7b,0x79,0x7d,0x97,0x3f,0xf8,0xe4,0x3b,0xd4,0x6b,0x55, + 0xfc,0xc9,0xef,0x5e,0xa3,0x89,0x91,0xea,0xb,0xb,0x47,0xfe,0xda,0x3f,0x5c,0xde, + 0xc2,0x97,0xdf,0x2d,0xe1,0xdb,0x87,0xcf,0xd1,0xb1,0x36,0x2a,0x65,0x55,0xa3,0xc1, + 0x3e,0x29,0x23,0x87,0xe9,0x38,0xb8,0xa3,0xa3,0x8c,0xc8,0xc1,0xd1,0x67,0x89,0xa1, + 0xf9,0x3,0xce,0xe0,0x5b,0xd4,0x7e,0xf7,0x2b,0xdb,0xb6,0x8b,0x95,0xcd,0x3d,0x2c, + 0x6f,0xee,0xe1,0xcb,0xbb,0x4b,0xfc,0xc5,0x9d,0x67,0xd4,0x72,0x39,0xde,0xb8,0xb8, + 0x30,0x89,0x91,0xc1,0x66,0xb4,0xa9,0x95,0x64,0xad,0xfc,0xda,0x1a,0xea,0x6f,0xe0, + 0xed,0x2b,0x8b,0xb8,0x76,0x71,0x9e,0xee,0x2d,0xad,0xf3,0xe6,0xce,0x11,0x2c,0xb8, + 0x2c,0x5e,0x58,0x30,0x1f,0xf4,0xc4,0x18,0xcd,0xdd,0x63,0x6f,0x68,0x28,0xb8,0x8e, + 0x85,0xcf,0xef,0xec,0xb7,0xb0,0xb3,0xdf,0xca,0x3a,0x6e,0xbd,0x4a,0x3d,0xbf,0x30, + 0x81,0x1b,0x97,0x16,0x30,0x3e,0x3c,0xf0,0x4a,0x4c,0x7f,0x66,0xc6,0xe1,0x71,0x7, + 0x5f,0xde,0x5d,0xc2,0xbd,0x67,0x1b,0x60,0xa2,0xa2,0x1b,0x88,0x57,0x76,0x27,0x22, + 0x79,0x9e,0xaf,0xa1,0x9b,0xcc,0xb2,0xb9,0x8b,0x4,0x17,0x27,0xfc,0x65,0xa8,0xbf, + 0x89,0x77,0xae,0x2c,0xe0,0xf2,0xe9,0xc9,0x9e,0x91,0xad,0xf9,0xba,0x23,0xbc,0xf6, + 0xc7,0x27,0x5d,0x3c,0x5a,0xde,0xe0,0x95,0xcd,0x5d,0x56,0xa8,0x8a,0x24,0x5e,0x11, + 0xe5,0xa1,0x38,0x22,0xd,0x21,0x3a,0xfe,0x85,0xb,0x8e,0xc3,0xe5,0x6e,0x99,0x44, + 0xd6,0x85,0x6f,0x7a,0xad,0xf5,0xcd,0x0,0x31,0x53,0xe6,0x96,0x19,0x65,0x6a,0x12, + 0xbc,0x65,0xb1,0x9b,0xf7,0x9e,0xfd,0x5,0x95,0x59,0xe6,0xb2,0x9a,0x2c,0xa,0x54, + 0xa8,0x6a,0x55,0xae,0xfa,0x24,0x16,0xcf,0x2a,0xc1,0x8f,0xf5,0x4e,0x97,0xa4,0xff, + 0x2c,0x9,0xe6,0x65,0x2a,0xa0,0xc2,0xd7,0x53,0xe0,0x7e,0xa4,0x53,0x4b,0x14,0x64, + 0xc6,0x51,0x5f,0x7,0x15,0x55,0xa4,0x4d,0x4d,0x72,0xd8,0x9f,0xb3,0xe2,0x26,0x59, + 0xf7,0x3a,0xd2,0x34,0xc3,0xa1,0x65,0xbe,0x78,0x94,0x1c,0xa,0xca,0x86,0x21,0xca, + 0xf6,0xf5,0x5e,0x8d,0x90,0x4e,0xb3,0x98,0x72,0xa4,0xa8,0x35,0x41,0x58,0xed,0xa7, + 0x79,0x13,0x16,0xd7,0x9e,0xd1,0xef,0x67,0xfa,0x34,0xa5,0xe6,0x68,0xbf,0x17,0x1b, + 0x31,0x8a,0x33,0x73,0x7c,0xbe,0x62,0xb7,0x9e,0x55,0x9,0xce,0x33,0xde,0xa3,0x68, + 0x49,0xc4,0x5a,0x27,0xa6,0x3b,0xab,0xa9,0x32,0x90,0xf9,0x2c,0x73,0x2e,0xa7,0x48, + 0x7c,0x7,0x26,0xc5,0x9f,0xf2,0x5,0x39,0x5f,0x4,0x12,0xa9,0x66,0xa7,0xb8,0x49, + 0x8e,0x26,0x24,0x46,0xd8,0xba,0xa6,0x20,0x10,0xf6,0x52,0x35,0x32,0xd2,0x75,0x5d, + 0xff,0x43,0x31,0xa0,0x5,0xce,0xda,0x3d,0x14,0x9b,0xf8,0xb8,0x9,0xf5,0x5a,0x15, + 0xef,0xbd,0x7e,0x86,0xde,0x7d,0x6d,0x91,0x9a,0xcd,0x5a,0x69,0x7,0xdf,0x8b,0x4c, + 0x63,0xad,0xc5,0x5f,0xff,0xe6,0x36,0xfe,0xf3,0x47,0xdf,0xe2,0xa3,0x9b,0xf,0xb1, + 0xbe,0x73,0x98,0xf1,0x4,0xc3,0xde,0x4d,0x2,0x1e,0xa4,0xae,0xfd,0x74,0x20,0xeb, + 0xeb,0x4e,0xca,0x34,0x12,0x8a,0xad,0xf3,0xea,0x25,0x3a,0x62,0x8c,0xc1,0xec,0x84, + 0xf3,0x92,0xcf,0x77,0xfb,0xb7,0xee,0xaf,0xe0,0x7f,0xfe,0xab,0xdf,0xf2,0x6f,0xbe, + 0x7e,0x8c,0xe3,0x28,0x17,0x4a,0x5e,0xcf,0x94,0xe3,0xb9,0xe4,0xfa,0xb6,0x18,0x64, + 0xca,0xd1,0x51,0xbf,0x0,0xef,0x89,0x11,0xca,0xcb,0x1,0x41,0x6a,0x69,0x14,0x1e, + 0x3c,0x1,0x45,0xe1,0x2b,0xd1,0xaf,0xbf,0x7a,0x4,0x6,0xe1,0xad,0x2b,0xa7,0x30, + 0x32,0xd0,0x54,0xcd,0x48,0x2f,0x88,0xd4,0xed,0x55,0x19,0x1f,0x7f,0xf3,0x4,0x1f, + 0x7d,0xf5,0x28,0x91,0x80,0xa1,0xe2,0xfb,0x58,0xd4,0x62,0x96,0x8,0x5e,0x3c,0xbd, + 0xa8,0xdc,0x38,0x51,0x2e,0x37,0x28,0x78,0xaa,0x23,0x2d,0x71,0xdc,0x99,0xcb,0x24, + 0x92,0x2,0xf5,0x6e,0x8e,0xc,0x56,0x36,0x76,0xf9,0x7f,0xfa,0xab,0x8f,0xf1,0xf9, + 0xdd,0x67,0xf4,0xaf,0x7f,0xfa,0x16,0xde,0x7f,0xfd,0x34,0x66,0x27,0x86,0xcb,0x61, + 0xde,0xec,0xb9,0xd5,0xab,0x15,0xfc,0xf0,0x8d,0xb3,0xd8,0xde,0x3b,0xa4,0xbf,0xfa, + 0xd5,0x37,0xdc,0x6a,0x75,0xb4,0x1a,0x58,0x82,0xeb,0x9c,0x5b,0x83,0x52,0x21,0x72, + 0xa3,0xc4,0x54,0x2e,0x11,0x87,0x91,0x23,0x2c,0xa9,0x2f,0x3b,0x3d,0x33,0x8e,0xef, + 0xbd,0x7e,0x1a,0x13,0x23,0xfd,0x2f,0x2c,0x8e,0xb2,0x1,0xde,0x3b,0x68,0xe1,0x83, + 0x8f,0xef,0xe2,0xeb,0x7b,0x2b,0xa9,0x48,0x73,0x86,0xf2,0x84,0x3d,0xb4,0x18,0xa8, + 0x24,0x1c,0xcf,0x19,0xd1,0x28,0xae,0x7e,0x4,0x5d,0x3b,0x12,0xa2,0xfd,0xef,0xb8, + 0xb8,0x30,0x89,0x7f,0xfb,0x2f,0xbf,0x87,0x77,0xaf,0x2c,0xaa,0xcc,0x84,0x57,0x81, + 0xdd,0x8f,0x8f,0x4f,0xf0,0xd9,0x77,0x4b,0x7c,0xef,0xe9,0x26,0xb2,0xb0,0xc7,0x12, + 0xab,0xf2,0x30,0x99,0x3b,0x92,0x9,0x87,0xa4,0x1d,0x3,0xb0,0x85,0x3b,0xc7,0xd9, + 0xc6,0xf1,0xdd,0xd,0x6e,0xc6,0x75,0x8f,0xb0,0xfa,0x9e,0x31,0x28,0xac,0x98,0xbd, + 0xa4,0x48,0xf9,0xaa,0x38,0xa4,0x40,0x36,0x5d,0x6,0xc5,0x2e,0x88,0x41,0x6c,0x94, + 0x9f,0x47,0x38,0xf2,0xe4,0x2a,0xa6,0x5a,0x84,0xfb,0xe4,0x64,0x58,0xdc,0xfe,0xea, + 0x4c,0x6e,0x5d,0x34,0x49,0x4c,0x73,0x59,0xb8,0x69,0x76,0xd0,0x69,0x82,0x40,0xee, + 0x64,0xa6,0x7c,0xc7,0x55,0xb8,0x2a,0x89,0xb0,0x97,0x2,0x80,0xa1,0xf6,0x17,0x9a, + 0x7a,0xcd,0x45,0x54,0x27,0x95,0x65,0xf5,0xa5,0xec,0x2b,0x82,0xd0,0x44,0xc7,0x42, + 0x48,0x42,0x92,0x25,0xf8,0xee,0xfe,0x82,0x26,0xa,0x1d,0xa5,0x7,0x8d,0x43,0xf0, + 0xa,0x45,0x1f,0x53,0x39,0xd9,0x29,0xd6,0x78,0xc9,0x3,0x33,0x72,0x82,0xcb,0x90, + 0x6f,0xeb,0x90,0x41,0x26,0xe8,0xee,0x4f,0xae,0xb0,0x18,0x2a,0x5f,0x35,0x37,0x77, + 0x89,0x33,0xb8,0xcb,0xf,0x50,0x4d,0x9d,0x31,0x1c,0x8b,0xa2,0x11,0xef,0xa2,0x91, + 0x84,0x8e,0x4,0x23,0x92,0x28,0x54,0xc9,0xb5,0xda,0x13,0xa9,0xd4,0xc8,0xa6,0xd8, + 0xd2,0x0,0x19,0x26,0xc9,0xc2,0x4b,0x41,0xaa,0x2a,0xb1,0xcb,0x48,0x12,0x1c,0x49, + 0x46,0xbb,0xdc,0x33,0x98,0xb0,0x36,0x37,0x81,0xac,0x45,0x20,0x50,0xbd,0x56,0xa1, + 0x37,0x2f,0xce,0xd3,0xf5,0x8b,0xf3,0xa8,0x55,0x8c,0xd2,0x70,0xbf,0x68,0x77,0xde, + 0x3a,0x3e,0xc1,0x9d,0x27,0xab,0xf8,0xbb,0x8f,0x9d,0x7e,0x78,0x6b,0xef,0x30,0x5f, + 0xff,0x29,0x84,0x5,0x65,0x59,0xf0,0xaa,0xfe,0x94,0x8c,0x5f,0xd0,0x5d,0x7a,0x61, + 0x4c,0x11,0x24,0x44,0x66,0x60,0x63,0xe7,0x10,0x1b,0x3b,0x7,0x38,0xe9,0x74,0xd1, + 0x6a,0x77,0xb0,0xb1,0x7d,0x80,0x47,0xcf,0x37,0xf1,0xc9,0x37,0x8f,0xf9,0xc3,0x2f, + 0x1f,0xf0,0xfa,0xce,0xbe,0xdb,0xbc,0x19,0x8f,0x24,0x6a,0xd6,0x4a,0xd0,0x42,0xba, + 0xf7,0xca,0xc8,0xd5,0x88,0xf5,0x87,0xa,0x11,0xd8,0xa6,0x1e,0xd5,0x88,0xe6,0x93, + 0x2,0x31,0xd3,0x24,0x38,0x30,0x22,0x35,0xe9,0x63,0x71,0x3b,0x28,0x9e,0xa6,0xa9, + 0x18,0xf4,0x35,0xea,0x2f,0x85,0xdc,0x65,0x31,0xd9,0xde,0x6f,0xe1,0xe6,0xdd,0x67, + 0xfc,0xf5,0x83,0x65,0x74,0xad,0x8d,0x36,0xe6,0xd1,0xd4,0x23,0xc9,0x86,0x2,0x6b, + 0x3f,0xeb,0xdb,0x99,0xf3,0xc4,0x44,0x96,0x7e,0xde,0xec,0xa6,0xda,0x68,0x13,0x15, + 0xfa,0x5e,0x31,0x99,0xc4,0xce,0x95,0x48,0xc,0x35,0xee,0xe7,0x74,0x2d,0xb0,0x7b, + 0x78,0x8c,0x4f,0xbe,0x79,0xcc,0xf5,0x6a,0x95,0x3a,0x9d,0x2e,0xfe,0xe0,0xbd,0xcb, + 0x18,0x19,0x68,0x28,0x4d,0x7a,0x4e,0x26,0x33,0xc6,0xa0,0x52,0x31,0xb8,0x7e,0x61, + 0x1e,0xcf,0x37,0xf7,0xf0,0x77,0x9f,0xde,0xa3,0xa3,0x76,0x17,0x79,0xe0,0x79,0x99, + 0x67,0x86,0x9e,0xc5,0x8a,0x4,0x63,0x2a,0xe1,0x20,0x95,0x71,0x64,0x2b,0x44,0x18, + 0x1b,0xee,0xc3,0x99,0xb9,0x71,0x4c,0x8d,0xd,0xbe,0x94,0x60,0x26,0x39,0xd,0x4b, + 0x6b,0x3b,0xb8,0x79,0xef,0x19,0x96,0xd6,0x76,0xc2,0x2e,0xd1,0x5d,0x6c,0x9e,0x2c, + 0x19,0x8f,0x9d,0xb8,0x58,0x33,0x7a,0x47,0x60,0x28,0xca,0x79,0x21,0xe9,0x18,0x90, + 0xc1,0x4f,0x69,0x6d,0x31,0x3c,0xd8,0xc4,0x8d,0x8b,0x73,0xf8,0x83,0x77,0x2f,0xe1, + 0x9d,0x2b,0x8b,0x31,0x1c,0xa9,0x17,0xb1,0x52,0xbe,0xce,0x92,0xc0,0xf7,0xf1,0x37, + 0x8f,0xf9,0xee,0xd3,0x35,0x16,0x53,0x48,0x42,0x4d,0x63,0x9e,0xaa,0x9,0x21,0xb7, + 0xae,0xbd,0x20,0x30,0x91,0x1,0xfb,0xd5,0x1a,0x91,0x85,0xd2,0x3a,0x87,0x19,0xc4, + 0x72,0xa9,0xc9,0x56,0xbc,0xa,0x4d,0xa8,0x5e,0x62,0xe0,0x65,0x52,0xc9,0xd3,0xd1, + 0x3f,0x44,0x84,0x7a,0x85,0x95,0x7d,0x4e,0xec,0x8e,0xbe,0x27,0xb9,0x6f,0x1b,0x1, + 0xd5,0x2,0x31,0x41,0x32,0x2d,0xb3,0xdd,0x75,0x22,0x5b,0xe5,0x7,0x45,0x66,0xf4, + 0xc6,0x84,0xd2,0x10,0x54,0x82,0xca,0x2,0x97,0x5,0x8d,0x4a,0xd6,0xdd,0x4c,0xc8, + 0x8c,0x68,0x50,0xb2,0xd8,0x2b,0x61,0x7d,0xb,0x60,0x9a,0x39,0xa5,0xf,0xea,0x8a, + 0x46,0x42,0x72,0x1e,0xe,0xad,0x4a,0x88,0x93,0x24,0x23,0x2c,0x51,0x20,0xa0,0x78, + 0x63,0xc2,0xeb,0x6d,0x92,0xfb,0x72,0x38,0xf8,0x4c,0x3a,0xad,0xd,0x74,0x15,0xf7, + 0xa6,0x5a,0x8e,0xf2,0x15,0xf2,0xda,0x9,0x4a,0x3e,0x63,0x14,0x29,0x8e,0x39,0x94, + 0x53,0xe9,0x5a,0xe7,0xcf,0x4f,0xca,0x43,0x67,0xc4,0xe6,0x1b,0x29,0xb2,0x49,0xaf, + 0x3,0xa5,0xd3,0x14,0x8c,0x3b,0xcc,0xb8,0x22,0xb6,0x32,0x2c,0x26,0xf6,0xcc,0x5e, + 0xb6,0x70,0x58,0x18,0xd5,0x45,0x64,0x3b,0x12,0xa3,0x16,0x96,0x30,0x22,0x7f,0x36, + 0x4c,0xe4,0x22,0xd1,0xcb,0x5f,0xa4,0x24,0x86,0x8d,0x0,0xf5,0x9a,0x24,0x82,0x8e, + 0xd3,0xa1,0x20,0xc5,0x85,0xf2,0x6f,0xa2,0xf4,0x8d,0x43,0x75,0xf,0xb6,0xaa,0xd5, + 0x2a,0x2e,0x9f,0x9d,0xa1,0xb3,0xf3,0x13,0xd4,0x6b,0x5f,0x5e,0x76,0x78,0x3d,0x5c, + 0xde,0xc0,0xcf,0x3e,0xbb,0x87,0xdf,0x7e,0xfb,0x18,0x5b,0x7b,0x47,0x59,0x1a,0x1d, + 0xf4,0x40,0x28,0x5e,0x33,0x83,0x32,0xcb,0x7c,0x2a,0x45,0xd4,0xb,0xe4,0xb8,0xdc, + 0x48,0x48,0xf0,0x58,0x3a,0x1d,0x8b,0xcf,0xef,0x2c,0xb9,0x33,0xd1,0x38,0xb2,0xd8, + 0x9d,0xc7,0xab,0xfc,0xd1,0xad,0x47,0x58,0x5e,0xdb,0x61,0x52,0x68,0x98,0xd,0x16, + 0xa1,0x2e,0xe,0x94,0x99,0xa5,0x76,0x55,0x86,0x24,0xb1,0x7f,0xd4,0x49,0xe7,0x1a, + 0xe3,0x6a,0xe1,0x70,0x25,0xa3,0xf4,0xfc,0xa1,0xa9,0x62,0x70,0x46,0x74,0x93,0x3a, + 0x45,0xd7,0xe2,0x54,0x8d,0x73,0x4e,0x7b,0xe7,0xd2,0x2,0xe6,0x7c,0x10,0xcb,0xab, + 0xb8,0xee,0x1d,0x1d,0x9f,0xe0,0xd1,0xca,0x26,0xee,0x3d,0x5d,0xc7,0x41,0xeb,0x84, + 0xcb,0x55,0x2a,0x11,0x43,0x14,0x74,0x1a,0x8f,0x7d,0x1a,0x44,0xa5,0x91,0x44,0xfd, + 0x54,0x40,0x83,0xf2,0xe1,0x96,0xf6,0xde,0x2c,0x13,0xa,0x1c,0x1f,0x53,0xfc,0x2, + 0x41,0x2,0x1,0x11,0xa1,0xdd,0xb1,0xf8,0xfb,0xcf,0xee,0x81,0xc1,0x18,0x19,0xec, + 0xc7,0xdb,0x57,0x4e,0x61,0x62,0x64,0xa0,0xe7,0x5a,0x27,0x7c,0x7c,0x6a,0x6c,0x10, + 0x17,0x17,0xa6,0x30,0xd4,0xdf,0xc4,0xf6,0x7e,0xeb,0xc5,0xdc,0xe2,0x12,0x9e,0x29, + 0x71,0x89,0xbb,0x74,0x61,0xb0,0x2a,0x4b,0xed,0x2,0x6,0xfa,0x1a,0xb8,0x71,0x79, + 0x11,0xe7,0xe7,0x27,0x5e,0x38,0x99,0xcb,0xf7,0xa5,0xdb,0xed,0x62,0x65,0x73,0x1f, + 0xb7,0x1f,0xaf,0x62,0x69,0x7d,0x57,0x98,0x82,0x25,0x24,0x4a,0xef,0xbc,0xe5,0x8a, + 0xd3,0x24,0xd2,0x17,0x74,0xac,0x75,0x71,0xb7,0x9c,0xee,0x95,0x91,0xa1,0x26,0xde, + 0x38,0x37,0x8b,0x7f,0xfb,0x2f,0xde,0xc3,0xef,0xbd,0x75,0x1,0x95,0xca,0xcb,0xe3, + 0x55,0xf3,0xc2,0x7e,0xd8,0x3a,0xc1,0xbd,0xa5,0xd,0xfe,0xfc,0xbb,0x67,0xbc,0xbe, + 0x73,0xc0,0xc9,0xb9,0xd3,0x5f,0x1e,0x71,0xe5,0x68,0xd9,0x21,0x35,0xc4,0x16,0x3a, + 0x3d,0x4d,0xa6,0x80,0x85,0xa1,0x92,0xd8,0xa,0x43,0x95,0x18,0xc6,0x2a,0x20,0x74, + 0xb9,0x94,0x35,0xe9,0xa,0xcb,0xee,0x19,0xcd,0xdd,0xd6,0x83,0x6e,0xe4,0x44,0x1b, + 0x14,0xe3,0x48,0x94,0x7d,0x7c,0xba,0x3e,0xaa,0x44,0x19,0xdb,0xaf,0xa0,0x9,0xd3, + 0x76,0xa2,0x2c,0x76,0x30,0x54,0xd8,0xd1,0x9,0xe6,0x7a,0xd0,0xa9,0xb,0x14,0x3b, + 0xee,0x96,0xb3,0xc9,0x94,0xa8,0x18,0xd5,0xa9,0xb6,0xaf,0x2c,0xa0,0xca,0xec,0xb8, + 0x8b,0x56,0xaf,0x2c,0xa2,0x5a,0x15,0x5,0x4b,0x14,0x6d,0x22,0xc5,0xd7,0x12,0x83, + 0x63,0x2c,0xce,0x69,0x25,0x61,0xd4,0xfa,0x2d,0x96,0x14,0xa1,0x98,0x56,0xbf,0x21, + 0xc0,0xce,0xd2,0xe9,0x85,0x74,0x5c,0x52,0x2,0xaf,0x33,0x14,0x81,0xb,0xc2,0x39, + 0x50,0x12,0xfe,0x27,0x3f,0xee,0xec,0xe,0x17,0x29,0x1c,0x19,0xc1,0xca,0x28,0x53, + 0x1c,0x8a,0x47,0x5d,0x64,0x34,0x47,0xda,0x8d,0x1b,0xc6,0x2d,0xb3,0xda,0x70,0x73, + 0x94,0x2f,0xe6,0x7b,0xb2,0x42,0x98,0x5b,0x64,0xd,0x4,0xcb,0x98,0x68,0x5e,0xa9, + 0x62,0xb3,0x59,0x26,0xe1,0x19,0x71,0x69,0xc4,0x80,0xf,0x90,0x92,0x33,0x44,0x5b, + 0x77,0x44,0x16,0x7b,0xf0,0x76,0x8f,0x1e,0xd6,0x8e,0x1,0x1f,0x78,0x24,0x7e,0x88, + 0x4f,0xcc,0x6c,0x80,0x60,0x2a,0x44,0x13,0x23,0x3,0x18,0xec,0x6b,0xbc,0x50,0xb7, + 0x9a,0x1f,0x4,0xdf,0x3c,0x7a,0x8e,0xbf,0xfd,0xe4,0xe,0xd6,0xb6,0xf,0x52,0x94, + 0x80,0x5c,0x7,0xb1,0xb8,0xe1,0xa,0xf7,0x41,0xd1,0x6f,0x1f,0xa5,0x57,0x6f,0x6, + 0x89,0x86,0xb7,0x4e,0x24,0x15,0x86,0x3f,0x27,0x5d,0x8b,0xf,0xbf,0x78,0x80,0x5b, + 0xf7,0x57,0x60,0xa8,0x82,0xa3,0xf6,0x31,0xef,0xec,0xb5,0xb0,0xba,0xb9,0x5f,0x50, + 0x6,0x92,0x28,0x5c,0xe,0x41,0x8e,0x19,0x9c,0xac,0xe4,0x35,0xf2,0x18,0x35,0x7e, + 0x94,0x10,0xae,0x8e,0x86,0xd,0x41,0xb,0x35,0xc4,0xdb,0x64,0xe2,0xb5,0x4e,0xd2, + 0x6d,0x4a,0xdc,0xdf,0x64,0xc,0xae,0x5f,0x9c,0xa7,0x1b,0x97,0x17,0xa8,0x5e,0x35, + 0x8a,0x24,0x96,0x1b,0xf7,0xc8,0xdb,0xe9,0xe1,0xb3,0xd,0xfc,0xf2,0x8b,0x7,0xbc, + 0xba,0xb3,0x9f,0xa5,0x13,0x32,0xeb,0xb1,0x3c,0xd0,0x52,0xa2,0xbb,0x7,0x7,0xf2, + 0x92,0xe3,0xb7,0x71,0x2a,0xfd,0xc2,0x41,0x2a,0x7c,0x5,0xf2,0xb5,0x94,0x13,0x23, + 0x45,0xc,0xd8,0x21,0xef,0xcc,0xe1,0x2c,0x60,0x81,0x97,0x85,0x2f,0xb,0xc3,0xd4, + 0x17,0x77,0x9e,0xa1,0x59,0xff,0x82,0x26,0x46,0xfa,0x31,0x31,0x32,0xf0,0x52,0x24, + 0x82,0x99,0x31,0x36,0xdc,0x8f,0xb,0xa7,0x26,0xb1,0xb5,0x7b,0x88,0x83,0xd6,0x49, + 0x7c,0xac,0x5,0xfa,0x43,0x76,0xc1,0x30,0x95,0x28,0x71,0x29,0xd7,0x48,0xe4,0x59, + 0x5f,0xe9,0x23,0x3,0x7d,0xd,0xbc,0xff,0xfa,0x69,0x5c,0x5c,0x9c,0x8a,0x8f,0xa5, + 0x97,0x47,0x7b,0x98,0x84,0x8d,0x31,0xf8,0xe2,0xce,0x12,0x3e,0xbc,0xf9,0x8,0x7, + 0x47,0x27,0x48,0xa6,0x60,0x88,0xb2,0x63,0x2e,0x95,0xe3,0x52,0xae,0x7e,0xce,0xd6, + 0x4a,0xac,0x89,0x17,0xfe,0xcf,0xf5,0xb,0x73,0xf8,0xc1,0x1b,0xa7,0xf1,0xa3,0x37, + 0xcf,0xe3,0xda,0xb9,0x59,0x54,0xab,0x95,0x42,0x98,0x51,0xae,0x32,0x28,0x8b,0x8a, + 0xfd,0xf0,0xcb,0xfb,0xfc,0xef,0x7e,0xfe,0xb5,0x5d,0xdf,0x39,0x10,0x5c,0x30,0xf6, + 0x89,0xd5,0x2e,0x6e,0x10,0x11,0x65,0xb2,0x9,0x55,0x60,0xcb,0x82,0xd,0x1e,0xc0, + 0x1c,0x16,0x94,0x74,0x61,0xd,0x47,0xa2,0xc4,0x91,0x20,0x6f,0x8,0xd2,0x1a,0x95, + 0x53,0x19,0x8c,0xf0,0x7d,0x52,0x8d,0x99,0x54,0x9b,0x96,0xa8,0xc8,0x15,0xdf,0x8a, + 0xb2,0x9,0x5d,0x4f,0xf4,0x9c,0xe1,0xf7,0xac,0x74,0xc9,0x5,0xe9,0x1,0x95,0x48, + 0x25,0xa3,0xa2,0x8d,0x4a,0xc8,0xe,0x54,0x4c,0x3b,0xcb,0xfd,0xdf,0x95,0x5a,0x5b, + 0x74,0xd7,0xc2,0xc6,0x27,0xe9,0x63,0xf5,0xab,0x25,0xfb,0x8d,0xd8,0x19,0xc6,0xbd, + 0x4,0x9,0x9e,0x37,0x47,0xb4,0x36,0x6d,0x9f,0x8d,0xc,0x90,0x22,0x16,0x24,0xb8, + 0x0,0x38,0xb,0x56,0xb5,0x20,0xcb,0x26,0x70,0x2e,0xd6,0x28,0xe,0x6b,0xe,0xe1, + 0xd9,0x1e,0xcc,0x9b,0x91,0xe7,0xdc,0x2a,0x79,0x4,0x28,0x52,0xd2,0xc5,0x3e,0x89, + 0x8a,0x37,0x8c,0x9b,0xd6,0x90,0x8,0x7c,0x6c,0xb4,0x2d,0xae,0x88,0x6e,0x22,0x23, + 0xd5,0x68,0xe9,0x65,0x71,0xd8,0xac,0x89,0xdd,0x26,0xb1,0xb2,0xc7,0x4b,0xaf,0x4e, + 0x64,0xa4,0xb2,0x38,0xd,0xa1,0x70,0x7d,0x23,0xb9,0x47,0x64,0x48,0xfa,0x21,0x29, + 0x9e,0xa5,0x74,0x88,0x45,0x8c,0x45,0x27,0x2d,0x13,0x74,0xf8,0x79,0xca,0x30,0x4f, + 0x96,0x64,0x69,0xdf,0xee,0x64,0xd4,0xa9,0x73,0x95,0x5a,0x42,0x77,0xe6,0x18,0x54, + 0xd0,0xac,0xd5,0x5e,0x69,0x12,0x91,0x87,0xed,0xf3,0x8d,0x3d,0x7c,0xf7,0x78,0xd, + 0x9d,0x8e,0x45,0x84,0x5e,0x38,0x97,0xc0,0xe4,0x10,0x54,0x2,0x3f,0x7b,0x45,0xe2, + 0x12,0x34,0x22,0x55,0xc,0x45,0x62,0x5,0xc7,0x93,0x30,0xf,0x79,0xb2,0xb6,0x8b, + 0x27,0xab,0x3b,0xac,0x20,0x2,0x27,0x1,0x50,0xf7,0x6e,0xde,0x50,0x30,0x85,0xfd, + 0x9b,0xf5,0xc,0x76,0xdf,0x60,0xda,0x0,0xed,0x91,0xef,0xdd,0x48,0x87,0x15,0x13, + 0xa7,0xc,0xf5,0xc4,0x10,0x22,0xa5,0x4c,0x20,0x49,0x54,0x74,0x3b,0xc6,0x30,0xa8, + 0x37,0xeb,0x55,0xbc,0x7e,0x6e,0x16,0xaf,0x9d,0x9d,0xe,0xd4,0x86,0x52,0x74,0x44, + 0x4e,0xaf,0xcc,0x8c,0xbb,0x4b,0xeb,0xf8,0xc5,0x97,0xf7,0xb1,0xbd,0x7b,0xc4,0x2, + 0xb2,0x66,0xe1,0xf,0xcc,0x94,0xf6,0xb5,0x1,0xce,0x72,0xd,0xb,0x53,0xd6,0x2a, + 0x73,0x1a,0x67,0x19,0x59,0x36,0xb4,0xe7,0xca,0x84,0x1f,0x2e,0x9d,0xac,0x2,0x13, + 0x90,0x34,0xb5,0x15,0x3e,0x9c,0x4e,0xaa,0x4f,0x18,0xc0,0xce,0x41,0xb,0x1f,0xde, + 0x7c,0x84,0x9f,0xbe,0x77,0x19,0xaf,0x9f,0x9b,0x41,0xfd,0x5,0xeb,0x85,0x70,0x1d, + 0x36,0xeb,0x55,0x2c,0xcc,0x8c,0xe1,0xc1,0xca,0x16,0xe,0x56,0xb6,0x2,0x91,0x5b, + 0x13,0xb2,0xb8,0xec,0x8c,0xcd,0x88,0x73,0xc9,0x42,0x40,0xa1,0x7d,0x9c,0x1,0xf5, + 0x81,0x6a,0x33,0x3a,0xdc,0x8f,0x6b,0xe7,0x66,0xb1,0x30,0x3d,0xfa,0x52,0x7,0xbf, + 0x0,0x5d,0x1f,0xb6,0x4e,0x70,0xf3,0xde,0x32,0xbe,0xb8,0xf3,0xd4,0xa9,0xd,0x48, + 0xdf,0x2,0xfa,0x4c,0x28,0x1e,0xef,0xf9,0xa,0x4a,0x66,0x41,0x84,0xaf,0xa9,0x54, + 0xc,0x9a,0xcd,0x1a,0x2e,0xce,0x4f,0xe2,0xa7,0xef,0x5d,0xc4,0x1f,0xbc,0x7b,0x11, + 0x57,0xbc,0xa9,0x8f,0x2c,0xe6,0x65,0x8a,0x14,0x79,0xff,0x86,0xfd,0xfa,0xd3,0xd5, + 0x1d,0x7c,0xf0,0xe9,0x3d,0xfe,0xc5,0x17,0xf7,0xb9,0xd5,0xee,0x78,0xba,0x15,0xa5, + 0x78,0xe,0xe3,0x93,0xa3,0xac,0x65,0xeb,0x8e,0x62,0xaf,0x48,0x77,0x8d,0xa3,0xf5, + 0x10,0xbc,0x5c,0x47,0x72,0xa0,0x66,0xc6,0xac,0x13,0x62,0x1d,0x47,0x4d,0xc8,0x17, + 0x96,0x85,0xd0,0xcd,0x2,0xe9,0xb1,0xe4,0x7d,0x95,0x83,0xb6,0x11,0x92,0x3e,0x52, + 0x4c,0xab,0xc4,0x6d,0xb,0xc6,0x32,0x85,0xc0,0x7,0x91,0xe9,0x25,0x19,0x74,0x2c, + 0xa0,0x13,0x96,0x64,0x86,0x4c,0x75,0x86,0x92,0x6e,0x8c,0xb,0x24,0x3d,0x51,0xc4, + 0xc,0xd2,0x85,0xac,0x24,0x5a,0x7e,0x9a,0xa,0xe8,0x6a,0x98,0x29,0xc5,0xbe,0x6, + 0x24,0xc3,0x53,0x22,0xdc,0x4f,0x79,0xb7,0x9a,0xac,0x43,0x85,0x5e,0xd8,0x18,0x1, + 0x12,0x86,0x2b,0x86,0x20,0x17,0xe3,0x62,0x31,0x2b,0x46,0x6c,0x9,0xc1,0x8b,0x69, + 0x90,0xe4,0xda,0xdb,0x50,0x59,0x7c,0x49,0x50,0x5a,0x2b,0x3d,0x3b,0x4a,0x26,0xa0, + 0x94,0x31,0xca,0xd2,0x12,0xaa,0xf0,0x4e,0x19,0xe1,0x6e,0x4,0x41,0xf4,0xd,0x6, + 0xdc,0x86,0xf4,0x4e,0xc2,0xcd,0x30,0x81,0xde,0x17,0x61,0x76,0xd5,0xa2,0x59,0xc9, + 0x94,0xe3,0xd2,0x9b,0x94,0xa,0xa9,0x7e,0x1e,0xa8,0x94,0x5b,0x30,0x45,0x2c,0x2e, + 0x88,0xfb,0xd4,0xe2,0x83,0xf2,0x6d,0x74,0xc,0x56,0x61,0xd2,0xe,0x72,0xc6,0xb8, + 0xd5,0xa6,0x9,0x2d,0x54,0x24,0xcc,0x25,0x17,0x78,0xa8,0x66,0x90,0x88,0xbd,0xbc, + 0xec,0xd5,0x3c,0xbe,0xe5,0x1,0x57,0xab,0x56,0x7d,0x42,0x9a,0xf0,0xc8,0xcf,0x50, + 0xf6,0x32,0xd1,0xd9,0xcb,0x5,0x40,0x9a,0x0,0xa7,0x29,0x8f,0xa4,0x8e,0xc2,0x94, + 0x99,0xc,0xf5,0x77,0x77,0xae,0x18,0x8,0xc0,0x45,0xb0,0x83,0x4d,0x50,0x59,0x80, + 0xad,0xdf,0x91,0x3b,0xd7,0x78,0x97,0xd8,0xc5,0x92,0x55,0x6d,0x88,0xc,0xb3,0xfb, + 0x12,0x8a,0xa,0x1e,0x2a,0x5c,0x98,0xd1,0x89,0x4f,0xef,0x3f,0xe5,0x2d,0x27,0x4d, + 0x1b,0x88,0x30,0x34,0xd0,0xc4,0xb9,0x53,0xe3,0x74,0x6a,0x6a,0xe4,0x95,0x5e,0x73, + 0x22,0xc2,0xfe,0x51,0x1b,0xf,0x96,0x36,0xf8,0xab,0xfb,0x2b,0x7c,0xd2,0xb1,0x69, + 0xa,0x27,0x82,0xb3,0xe9,0x8c,0x7,0x47,0x28,0xd6,0xc,0x36,0xbe,0xc0,0x73,0xb4, + 0x64,0x31,0x4c,0x2c,0x5f,0x39,0xdf,0xbd,0x26,0xb1,0xa8,0x60,0x9a,0x5,0x2,0x25, + 0x23,0xd1,0x5e,0x90,0x19,0x4a,0x84,0x68,0xa6,0x90,0x75,0x13,0x56,0x70,0x9,0xc1, + 0x25,0x1c,0x77,0xba,0xb8,0xfb,0x74,0xd,0xdf,0x3d,0x59,0xc7,0xa5,0x85,0x89,0x68, + 0x19,0xdb,0x8b,0x74,0x59,0x35,0x6,0xa3,0xc3,0x4d,0xc,0x34,0x6b,0xc8,0xfc,0x7f, + 0x4,0xf1,0x49,0x79,0xfc,0x15,0x52,0x22,0x3d,0x91,0x55,0xc5,0x18,0x43,0x6e,0x8, + 0x64,0xd8,0x86,0x61,0xd4,0x6b,0x15,0x9c,0x9e,0x1e,0xc5,0xe9,0xd9,0x31,0x34,0xeb, + 0xd5,0x57,0x6a,0x6e,0x4f,0x4e,0x3a,0x78,0xba,0xb6,0x8d,0xbb,0x4b,0x1b,0x58,0xdb, + 0x3e,0x54,0x90,0x37,0x97,0xad,0x9,0x4a,0x3e,0x1e,0xef,0x1b,0xa3,0x37,0xa6,0xb1, + 0xb0,0x19,0xc2,0xec,0xc4,0x30,0xfe,0xf4,0x47,0xaf,0xe3,0xc7,0x37,0xce,0xe3,0xec, + 0xfc,0x38,0xc6,0x6,0x9b,0xa5,0x6e,0x7c,0xbd,0x5e,0x53,0xd9,0x18,0x7e,0xf3,0x70, + 0x15,0xff,0xeb,0x7,0x5f,0xd8,0x8f,0xbe,0x7e,0xc8,0x7b,0x87,0x6d,0xce,0x74,0x9b, + 0xcc,0xd1,0x28,0xc2,0xef,0xca,0x99,0x18,0x30,0x1e,0x92,0x71,0xff,0x18,0x62,0xb6, + 0xd6,0x15,0x78,0xa7,0x58,0x73,0x0,0xa1,0x25,0xdf,0xd,0x4,0xbe,0x49,0xc9,0x92, + 0xb2,0xc8,0xa9,0xe1,0x17,0x22,0x9d,0x44,0x3d,0xd2,0xad,0xb,0x1b,0xc,0x99,0x37, + 0x62,0x40,0x2,0xb,0xe5,0xb8,0x43,0x2f,0xdc,0x6b,0x72,0xa3,0x5b,0xc,0x3a,0x29, + 0x88,0xb1,0x33,0x59,0x98,0xb6,0x4f,0xc9,0xa2,0x0,0x63,0xcd,0x36,0x8a,0xe1,0x98, + 0x34,0xef,0x94,0xb1,0x1f,0x65,0xb1,0xca,0xe4,0x27,0xd1,0x7e,0xd6,0x24,0x2a,0x4e, + 0x9a,0x17,0x33,0xfe,0x5d,0x30,0x35,0xf1,0xf6,0x6d,0x45,0x98,0x17,0xc1,0xff,0x3b, + 0x16,0x21,0xe1,0x70,0x29,0xa7,0x71,0x29,0xdc,0xa,0xae,0x66,0x1e,0xd6,0x8e,0x65, + 0x26,0x1a,0x96,0xb,0x8d,0x13,0x29,0xf6,0xbe,0x7e,0xab,0x55,0x34,0xaa,0xe1,0xe4, + 0xe,0xe4,0xc6,0x8,0x21,0x6d,0x62,0x21,0x5e,0x2b,0x51,0xfc,0x7,0x3d,0xa5,0xc9, + 0x38,0xbf,0x2,0x99,0xb0,0x32,0xf8,0x2f,0x5,0x31,0x86,0x9f,0xcd,0x2a,0xd5,0x27, + 0x9d,0x5,0x4a,0xc9,0x58,0xd8,0x2a,0x88,0xc2,0x9d,0x36,0x13,0x31,0x16,0x2a,0xcb, + 0xbd,0x53,0x1c,0xd7,0xa4,0xc2,0x91,0xcb,0x78,0xe7,0x5,0x9f,0x7e,0x94,0x63,0xd7, + 0x44,0x6e,0x7b,0x2c,0x32,0xc6,0x83,0xa0,0x46,0xe9,0xb,0xe3,0x55,0xd0,0x5,0xb0, + 0xb9,0x7b,0x88,0xf6,0x49,0x7,0xb5,0x6a,0xe5,0x95,0xcd,0x33,0x2e,0x2e,0x4c,0xe2, + 0x77,0xde,0x3c,0x87,0x5f,0xde,0x7c,0x80,0xfd,0xc3,0xe3,0x78,0x3d,0xe5,0xcc,0x58, + 0x53,0x16,0x3e,0x91,0xc1,0x8a,0x9c,0x39,0x3c,0x95,0xb1,0x12,0x54,0xd2,0x20,0xa0, + 0x88,0x90,0x52,0x12,0x24,0xcd,0x86,0xe2,0xb5,0xc3,0x99,0x44,0x48,0x62,0x39,0x4e, + 0xaf,0xef,0xd5,0x88,0x14,0x62,0x23,0x45,0x67,0xeb,0x8b,0xa0,0x71,0xa4,0x4e,0xca, + 0x91,0x7,0x79,0x4f,0x85,0x86,0xc6,0xa4,0xdc,0xb5,0x2,0x59,0x8b,0xa2,0x2b,0x1f, + 0x2e,0x2c,0x4c,0xd2,0xcc,0xd8,0x70,0xa1,0x68,0xe7,0xf2,0xa2,0x30,0x55,0xed,0x1d, + 0xb4,0xf0,0xd5,0xfd,0x15,0xdc,0x79,0xba,0x81,0x4e,0x57,0xaf,0xe0,0xc8,0x1f,0xbc, + 0x51,0x76,0x93,0x7e,0x22,0xa7,0x33,0x5f,0xa4,0x1f,0x90,0xed,0xb5,0x95,0x56,0x50, + 0x70,0xbc,0x98,0x42,0xeb,0xac,0x17,0x66,0x69,0x29,0x2f,0xb8,0x39,0x50,0x4a,0x37, + 0x51,0x70,0x2d,0x63,0x7d,0xe7,0x10,0xcf,0xb7,0xf6,0x70,0x7e,0x7e,0xa2,0xf4,0x5a, + 0x53,0xd3,0x25,0xb9,0x70,0x92,0x5a,0xad,0x26,0x1,0xf,0x69,0x6a,0x25,0x50,0x33, + 0x6f,0x38,0x92,0x3b,0x7b,0x2a,0x63,0x2d,0x92,0xb4,0x77,0x45,0xd2,0xa,0xa3,0xc5, + 0xf9,0xf9,0x49,0xbc,0x76,0x6e,0x6,0xc3,0xfd,0x8d,0x97,0xca,0x7,0xc3,0xe3,0x5f, + 0xd9,0xdc,0xc7,0x27,0xdf,0x3e,0xc5,0xd2,0xda,0x6e,0x81,0xc5,0x4b,0x78,0xc1,0x30, + 0xc7,0x45,0x42,0x9e,0xac,0x3,0xec,0x9,0x7a,0xa7,0x67,0x46,0x71,0x71,0x71,0x12, + 0x6f,0x9c,0x9f,0xc3,0xef,0xde,0x38,0x8b,0xd7,0xcf,0xcc,0x44,0x35,0x44,0x59,0x6c, + 0x70,0x59,0xf3,0x1d,0x57,0x53,0x27,0x1d,0xdc,0x7e,0xbc,0x86,0xff,0xf3,0xb7,0xb7, + 0xed,0xcf,0x3f,0xbb,0xc7,0x4f,0x57,0xf7,0xd8,0x9f,0x44,0x7e,0xa1,0x6d,0x53,0x43, + 0xe8,0x1a,0x40,0xa7,0xe8,0xf1,0x72,0x5d,0x2b,0x87,0x4d,0x22,0xc0,0x18,0x46,0x97, + 0xe3,0xb7,0x5b,0xf7,0x7d,0xee,0x7d,0xf1,0x3c,0x13,0x75,0xeb,0x67,0x7,0x9d,0x10, + 0xe,0x3,0xda,0xc5,0x3d,0x33,0x99,0xd2,0x94,0x73,0x52,0x1c,0x69,0x56,0xfe,0x66, + 0x80,0x50,0xd1,0x89,0x4e,0x90,0xc0,0xa8,0x6,0xb6,0x2b,0x97,0xd9,0xb5,0x66,0xc, + 0x35,0x39,0xa5,0x14,0x72,0xbb,0x15,0xc5,0x46,0xfc,0x17,0xc9,0x3d,0xaf,0x70,0x32, + 0x4b,0x79,0xa5,0x8e,0xbc,0x23,0x7f,0xa6,0x8c,0x13,0x94,0x9e,0x68,0x1e,0x56,0xd6, + 0x46,0xf5,0x26,0xda,0xc9,0xb3,0x62,0x1c,0x93,0x82,0xbe,0x93,0x34,0xca,0x7f,0x87, + 0x89,0xc5,0x59,0xe5,0x17,0x1a,0x16,0x1f,0x33,0x81,0x1,0xe1,0x67,0xd0,0xc0,0x6c, + 0x33,0x24,0x58,0xee,0x59,0x13,0x80,0x28,0x51,0x8c,0x12,0xb7,0x24,0xc0,0x30,0xa5, + 0x7b,0xd5,0xf4,0x46,0x4a,0x2a,0x1e,0x9,0x4c,0x5c,0x13,0xb,0x15,0xfa,0xc0,0x45, + 0xca,0xa0,0xfe,0x7a,0x56,0x8d,0x59,0x68,0xf,0x92,0x8d,0x93,0x71,0x93,0x4f,0xfa, + 0xd9,0xac,0x60,0x61,0x41,0x6e,0x4e,0x8c,0x7e,0x75,0x66,0x10,0x58,0xb2,0x8,0x49, + 0x7b,0xe7,0x46,0x1e,0xb4,0x51,0x4a,0x7c,0x31,0x80,0xf8,0xd7,0x49,0x3e,0x7c,0xdf, + 0xb2,0x18,0x8a,0x19,0xe6,0x21,0xfe,0x94,0x92,0xa9,0x3d,0x45,0xbb,0x3e,0x23,0x7, + 0x4a,0xed,0xc2,0x64,0xbb,0x8c,0x7,0xcf,0x36,0xf1,0x64,0x75,0x7,0x67,0x67,0xc7, + 0x50,0xad,0x9a,0x57,0xda,0xa1,0xbf,0xfb,0xda,0x22,0x4c,0xc5,0x60,0x65,0x63,0xf, + 0x5f,0xdc,0x5d,0x8e,0x5e,0x1,0xe9,0xf2,0x22,0x8d,0x9f,0x87,0x96,0xc8,0xe8,0x22, + 0xcd,0x46,0x9b,0x9,0x91,0xb4,0x6e,0xa3,0x32,0xda,0xa,0x69,0xe8,0x15,0x22,0x36, + 0x38,0xc7,0xe8,0xa4,0x54,0x51,0x89,0xf,0xc9,0x53,0x75,0x2,0xb2,0xcc,0xda,0xce, + 0x98,0x82,0x5e,0x96,0x93,0xfe,0x25,0xae,0xa5,0x73,0xf5,0x61,0x98,0x67,0x25,0x39, + 0x2e,0x5c,0xd0,0xc6,0x8b,0xec,0x63,0xc8,0x6d,0x6c,0x9c,0x17,0x67,0x46,0xf1,0xce, + 0x95,0x45,0xc,0xf9,0xc2,0xf1,0x32,0x6,0x35,0x0,0x6c,0xed,0x1d,0xe1,0xe7,0x5f, + 0xdc,0xe7,0xbb,0x4f,0xd6,0x3c,0x41,0x8d,0xa4,0xd8,0x38,0xd5,0x71,0x8e,0x6a,0x7a, + 0x46,0xcc,0xb7,0xf2,0x19,0x1b,0x3a,0x8,0xa2,0x7,0x0,0xec,0xc5,0x86,0x24,0xe3, + 0x95,0xd2,0xb1,0x8,0x12,0xf3,0xad,0x8c,0xb,0xe4,0x38,0xcc,0xfb,0xb7,0x34,0x28, + 0xf0,0x63,0xcc,0x2c,0x8e,0x4f,0x3a,0x38,0x6e,0x77,0x5f,0xba,0xe2,0x61,0x29,0x57, + 0x2c,0xac,0x31,0x25,0xb,0x4a,0xc0,0xd9,0x4c,0x99,0x62,0x88,0xd3,0x2,0x1b,0x3d, + 0x1c,0x5a,0xc4,0x7b,0x5e,0x31,0x84,0x6b,0xe7,0xe7,0xf0,0xf6,0xe5,0x53,0xa8,0x54, + 0x2a,0x2f,0x7d,0x5f,0xc2,0xe7,0x1e,0x3f,0xdf,0xc2,0x7,0x9f,0xde,0xc3,0xfa,0xf6, + 0x41,0x99,0x2c,0xa7,0x88,0x3e,0x21,0xdf,0x2b,0x89,0xe9,0x20,0x83,0x21,0x4e,0xcf, + 0x8e,0xe1,0x5f,0xfe,0xf0,0x35,0xfc,0xfe,0xdb,0xe7,0x71,0xe3,0xe2,0xbc,0xa,0x57, + 0x51,0x31,0xd,0xaf,0x20,0x4f,0x23,0x22,0x3c,0x58,0xd9,0xc2,0xff,0xf2,0x9f,0x3f, + 0xb3,0x1f,0x7e,0xf5,0x90,0x97,0xd6,0x76,0x3d,0x46,0xef,0x5f,0x2f,0x6b,0xd9,0xe1, + 0xec,0x96,0xa3,0x52,0xce,0xaf,0x6c,0xa2,0x5c,0x31,0x6,0x93,0xc4,0xf8,0xf9,0x24, + 0x19,0x61,0x62,0x81,0xd0,0xe8,0x2,0xce,0x19,0x29,0x90,0x23,0x1d,0x5b,0xc,0x5e, + 0x26,0x26,0xb1,0xe9,0x89,0x32,0x15,0x7d,0x2a,0x49,0x6e,0xa2,0xcc,0xa0,0x2d,0x20, + 0xd6,0x51,0x65,0x16,0xcd,0xc1,0x8,0x55,0x2e,0x13,0xfe,0x73,0xbe,0xfe,0xa6,0x82, + 0x99,0x9b,0x36,0xae,0xcb,0xe2,0x33,0x73,0xa,0x50,0x61,0x72,0x28,0x28,0xf7,0x5, + 0xa,0x29,0xf2,0xc2,0xc4,0xc1,0x4c,0x99,0x66,0x5b,0x6,0xa3,0x73,0x20,0x3a,0x4b, + 0xa6,0xa0,0x21,0xd2,0xc4,0x3d,0xa1,0xa9,0x91,0x24,0xf7,0xa8,0xad,0xf2,0xac,0x74, + 0xa3,0x27,0x70,0x57,0x63,0xbd,0xc7,0xb8,0x64,0x62,0x83,0xa2,0x76,0x9a,0xc4,0xa4, + 0x1f,0xa,0x1e,0xc7,0xfd,0xb9,0x49,0x50,0x7c,0x4e,0x5c,0x2b,0x70,0x5,0x42,0x71, + 0x37,0xa2,0x79,0x4a,0xfd,0x9d,0x2d,0x43,0x63,0x48,0x13,0x53,0x20,0xf2,0xda,0xb3, + 0x51,0xce,0x4f,0xda,0xee,0xe7,0x43,0xfa,0x6a,0x55,0xd2,0x45,0xe9,0x77,0x72,0xac, + 0x7c,0x83,0x8d,0x36,0x6f,0x54,0x2,0xc6,0x80,0xb7,0x1b,0x29,0x5d,0xf6,0x5c,0x22, + 0xaa,0x90,0xba,0x99,0x41,0x99,0xd3,0x0,0xe9,0x19,0x90,0x85,0x27,0x3c,0x55,0xc4, + 0x62,0x97,0x92,0x43,0x5c,0x2c,0x28,0x86,0xa,0xb,0xa9,0x38,0xb8,0x9b,0x78,0xcf, + 0xb4,0xbb,0x8c,0x5b,0xf,0x56,0xf8,0xec,0xdc,0x38,0xce,0xcd,0x8d,0xd1,0xcb,0xa2, + 0x25,0xc3,0x61,0x32,0x32,0xd8,0x87,0x37,0xce,0xcd,0xe1,0xbf,0xff,0x93,0xef,0xe1, + 0x6f,0x3e,0xbe,0x83,0xbf,0xfe,0xf8,0x2e,0xda,0xed,0x4e,0xd1,0x66,0x58,0x5d,0x9b, + 0x5c,0xe8,0x56,0x48,0xde,0x48,0xc9,0xd4,0xb,0x5,0x1f,0x68,0xc1,0x77,0x70,0xcd, + 0x93,0xf8,0x1d,0xa6,0xe4,0x8e,0x93,0x8a,0x3f,0x65,0x25,0x16,0xf3,0x9e,0x5,0xd, + 0x51,0xfa,0x4c,0x27,0xc2,0x23,0xc5,0xa9,0x3c,0x2c,0xa8,0x35,0xc1,0x29,0xbe,0xbd, + 0xe9,0xba,0xf,0x4c,0x13,0x4d,0x98,0x35,0x89,0xdc,0xe8,0xff,0x4e,0xf3,0x53,0xfb, + 0xd5,0x81,0xf3,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x23,0xf4,0xce,0x6b,0xb, + 0x34,0xea,0x75,0xf3,0xbd,0xa,0x9c,0xdc,0x8d,0xae,0xed,0x1c,0xe0,0xa3,0x5b,0x4f, + 0xf0,0xf0,0xf9,0x8e,0xe8,0x5a,0x39,0x45,0x1e,0x89,0x75,0x3e,0x9c,0xfd,0x5b,0x98, + 0x96,0xd8,0x9f,0x6c,0x1c,0xe8,0xa4,0x89,0xb0,0xe6,0xcd,0x34,0x29,0x13,0x77,0x85, + 0x62,0x6a,0x84,0x2e,0x87,0xa8,0xe8,0xc5,0x99,0x65,0x15,0x45,0x21,0x6,0x5,0xde, + 0x8a,0xf0,0x6a,0x20,0x83,0x5a,0xb5,0x82,0x7a,0xed,0xe5,0x5a,0x7b,0x0,0xe8,0x74, + 0xbb,0xd8,0x3f,0x6a,0xa3,0x75,0xd2,0xd5,0x36,0xcf,0xe2,0xf7,0x28,0xde,0x46,0xbe, + 0x6b,0x55,0xab,0xf,0x2e,0x49,0xb7,0x12,0xc8,0x27,0x18,0x15,0x63,0xf0,0xda,0xe9, + 0x69,0x5c,0x3b,0x37,0x8b,0x7a,0x95,0x5e,0xda,0x64,0x31,0x33,0xba,0xdd,0x2e,0x1e, + 0x2c,0x6f,0xe1,0xcb,0x7b,0xcb,0xd8,0x3e,0x3c,0x2e,0x38,0xc4,0x94,0xa5,0xa9,0x15, + 0x6d,0x8d,0x49,0xf9,0x9c,0xf4,0x35,0xaa,0x78,0xfd,0xec,0x2c,0xde,0xbe,0x3c,0x8f, + 0x6b,0xe7,0x66,0x70,0xf1,0xd4,0x4,0x4e,0xf9,0xf8,0xe2,0xdc,0xfd,0xb0,0x97,0x9e, + 0x3f,0xff,0xd8,0xea,0xd6,0x3e,0x3e,0xfc,0xea,0x21,0xff,0xe2,0x8b,0x87,0xfc,0xc9, + 0xb7,0x4f,0x78,0x79,0x63,0x4f,0x23,0x3a,0x9e,0x95,0x1e,0x98,0xec,0x89,0x99,0xce, + 0xec,0x67,0xce,0xb8,0x43,0xf,0xff,0x8b,0x1f,0x83,0x61,0x27,0xe7,0xc,0x96,0x22, + 0x4,0xee,0x5a,0xff,0x39,0xcf,0xb2,0x33,0x41,0xfa,0x23,0x10,0x6a,0xd6,0xe1,0x86, + 0x72,0xdd,0x56,0xac,0x9f,0xd4,0xa3,0xf,0xd3,0x23,0x61,0x44,0xd1,0xc,0x65,0x21, + 0x68,0xee,0x7a,0xa9,0xca,0xd8,0x4f,0xbd,0x94,0x27,0x15,0xbe,0x6e,0xe2,0xce,0x8e, + 0xb,0x72,0x1d,0x15,0xd9,0x59,0xec,0x86,0x63,0xd6,0x58,0x94,0x37,0xc8,0x7a,0xc, + 0x2a,0xa0,0x7b,0x2c,0x8b,0x3b,0x65,0xa4,0x21,0xd5,0xc8,0x66,0x6e,0x38,0x62,0x12, + 0x97,0x2e,0xee,0x6a,0xd,0x6f,0x48,0xee,0xc3,0x53,0xe4,0x88,0x30,0x36,0x9,0xfb, + 0x59,0x3f,0x90,0x53,0xc8,0x88,0x44,0xf2,0xcc,0x8a,0x2b,0xf6,0x50,0x67,0x38,0x4a, + 0x7e,0x82,0x4f,0x9a,0x89,0xe9,0xed,0xa4,0x21,0xbe,0x82,0x8f,0x5b,0x1e,0xcb,0xea, + 0xf0,0x51,0x83,0xcc,0xea,0x47,0xf4,0x6f,0x7a,0xbc,0x33,0x65,0x4,0x45,0x94,0x10, + 0xac,0x85,0x74,0xd2,0x5d,0xce,0xcc,0x9a,0x14,0x21,0xdf,0xf,0xcb,0xe5,0xdc,0x6, + 0x35,0x73,0x93,0x30,0x43,0xf0,0x1c,0x10,0x56,0x5c,0x68,0xf9,0x0,0x49,0xb,0x57, + 0xd2,0x8a,0x41,0x66,0xd6,0x32,0x9,0x2e,0x24,0x91,0x49,0xdb,0x91,0xf0,0xc6,0xf9, + 0x0,0x10,0x99,0xc8,0x96,0x27,0xf6,0x24,0x72,0x76,0xb7,0x6b,0xf1,0xed,0xa3,0x35, + 0x9c,0x3b,0xb5,0x8a,0x9f,0xbc,0x7d,0x1,0x3,0x7d,0xf5,0x82,0x36,0xb8,0x8c,0x2d, + 0x4b,0x44,0x98,0x1c,0x1d,0xc0,0x1f,0x7e,0xef,0x32,0x6,0xfa,0xea,0xd8,0x39,0x68, + 0xe1,0x9b,0xc7,0x6b,0xd8,0xde,0x39,0x84,0x2d,0x75,0x14,0xa6,0xf2,0xbf,0x1b,0x14, + 0xac,0x8d,0x23,0x99,0xc3,0x10,0xb4,0xff,0xa5,0xbc,0x31,0xa2,0x98,0x3c,0x39,0xdb, + 0x32,0x40,0xb0,0x1a,0x4,0x89,0x13,0x9d,0x74,0x36,0x33,0xe5,0x47,0x85,0x47,0x53, + 0x22,0x13,0x3c,0x51,0x6b,0x54,0x9a,0x0,0x93,0x6a,0xb5,0xd2,0x2b,0x4a,0xb1,0xd1, + 0x75,0x9c,0x5,0x83,0x10,0x51,0xa1,0xbe,0x8,0x0,0xe6,0xa7,0x46,0x70,0x79,0x71, + 0xa,0x83,0x7d,0xf5,0xd2,0xc3,0x59,0x1e,0xcc,0xd6,0x5a,0x1c,0x1c,0x9d,0xe0,0xc1, + 0xf2,0x6,0x3f,0x5c,0xde,0xe4,0x8e,0xb5,0xa2,0x6d,0xa4,0x48,0xfc,0xf0,0xdd,0x18, + 0xfb,0x63,0x95,0x3d,0xd2,0xc0,0xfe,0x25,0x89,0xc,0x78,0x75,0xe3,0xf9,0x3,0x5d, + 0x1d,0x98,0xe1,0x21,0x1b,0x71,0xea,0x51,0x26,0xb,0x21,0xea,0x41,0xcd,0x26,0x81, + 0x8c,0x49,0x12,0xaa,0xfb,0xd6,0xc1,0xbe,0x3e,0x8c,0xc,0x34,0x51,0xa9,0xf4,0xe6, + 0x6b,0xc4,0xdd,0x74,0xa7,0x8b,0xd5,0xed,0x7d,0xec,0x7a,0xb,0x55,0xca,0xe6,0x33, + 0xbd,0x72,0xc8,0xa2,0x13,0xb2,0xf3,0xb2,0xd4,0x6a,0x4d,0x7d,0x2f,0x61,0x6a,0x74, + 0x10,0x8b,0xb3,0x23,0x18,0x13,0x4d,0x56,0xaf,0x49,0xd7,0x85,0xfd,0x74,0xf0,0x78, + 0x75,0x7,0xf7,0x9e,0x6d,0x38,0x69,0x5d,0xc6,0xa8,0xe7,0x8c,0xce,0xa9,0x56,0x19, + 0xd9,0xdf,0xab,0xd5,0xa,0xfa,0x1b,0x35,0xf4,0x37,0xab,0xb8,0xb2,0x38,0x85,0x1f, + 0x5c,0x3b,0x83,0x9f,0xbc,0x7d,0xe,0x17,0x4e,0x4d,0x16,0x82,0x7b,0xca,0xa0,0xf4, + 0x9c,0xdd,0x1e,0xbe,0xe6,0xa0,0x75,0x82,0x67,0xeb,0x3b,0xb8,0x79,0x6f,0x99,0xff, + 0xf2,0xe7,0xb7,0xf8,0xb7,0xb7,0x9e,0xb0,0xb5,0x96,0x39,0xa6,0xa,0x7a,0x5a,0x88, + 0x33,0xfa,0x67,0x61,0x93,0x12,0x4c,0x59,0xd9,0x8f,0xb7,0x42,0xa3,0x1e,0xbc,0xd2, + 0x2,0x1a,0xc4,0x21,0x2e,0x83,0xfd,0x6a,0x85,0x9d,0xca,0xc3,0x22,0xb,0xfb,0xe4, + 0x8,0xe1,0xc0,0x4a,0xb,0x26,0x8e,0xdd,0xb0,0x70,0x8f,0xd4,0x5e,0x9a,0x5,0x56, + 0x41,0x36,0x1c,0xa7,0xb5,0x4b,0xd1,0x2b,0x38,0x7d,0x7d,0x35,0xdd,0x34,0x48,0x16, + 0x74,0xc1,0xdd,0xcc,0x18,0xc1,0xa4,0x23,0xd,0x37,0x82,0xb,0xce,0x3f,0x54,0x48, + 0xca,0x96,0x7c,0x5b,0x52,0x11,0x2d,0x39,0xa5,0x93,0x4a,0xe4,0xd,0xda,0x4a,0x96, + 0x4b,0x28,0x5a,0xfa,0x3,0x61,0x52,0x90,0x73,0x93,0x4,0x34,0x5d,0x30,0x49,0x18, + 0x31,0xa2,0x3b,0x49,0x4,0x17,0x7d,0x49,0xf6,0xc5,0xdb,0xb,0xa1,0x42,0x82,0x94, + 0xd8,0x9d,0x27,0x77,0xc8,0x8,0xf7,0xfa,0xda,0x62,0x28,0xdd,0x5e,0x26,0x0,0x77, + 0x24,0x5f,0x17,0xa7,0xb5,0x62,0x21,0x1,0xe2,0x2,0x3f,0x81,0x39,0x1a,0xe8,0xeb, + 0x1d,0x39,0x67,0x3,0x69,0xf9,0xda,0x56,0xab,0xc7,0x25,0x14,0x2a,0x16,0x10,0x14, + 0x96,0x7e,0x8,0x4f,0x83,0x33,0x13,0xa7,0x2a,0x2,0xe9,0x83,0xe5,0x16,0x43,0xb6, + 0x6e,0x81,0x1b,0x5f,0xa1,0x6c,0xb5,0x90,0x42,0x57,0x22,0x54,0xad,0xba,0x33,0x2e, + 0x34,0x83,0x1e,0xb8,0x8c,0x7b,0x42,0x87,0x88,0x84,0x36,0xc9,0x63,0xaf,0x89,0xa0, + 0x48,0x85,0xa9,0x5c,0x61,0xb4,0xe9,0x51,0x74,0x19,0x78,0xb2,0xba,0xcd,0xb7,0x1f, + 0xad,0x61,0x75,0x6b,0x9f,0xce,0xf7,0x4f,0xc4,0xe7,0x9f,0x67,0x6e,0xe7,0x85,0x86, + 0x99,0xd1,0xd7,0xa8,0xe1,0xfd,0xab,0xa7,0x31,0x3b,0x3e,0x8c,0xff,0xfd,0xc3,0x6f, + 0xf0,0x9f,0x7e,0x7d,0x1b,0x4f,0xd7,0xb6,0x4b,0x56,0x4d,0x10,0x8e,0xf,0xd9,0xd8, + 0x62,0x4a,0x18,0x74,0xa1,0xe5,0x34,0xe2,0x7b,0x2,0x3,0xca,0x88,0x35,0x57,0x89, + 0xa7,0x3f,0x95,0xb8,0x80,0x15,0xb8,0x95,0x32,0x99,0xc4,0xb0,0xce,0x99,0xc8,0x5e, + 0x7e,0xca,0xb6,0xfa,0x69,0x33,0x48,0x9a,0xcb,0x2e,0x9b,0xb5,0x38,0xa9,0xba,0x66, + 0xce,0xf5,0x27,0xee,0x7,0xf,0xf,0x34,0x31,0x37,0x31,0x8c,0x69,0x6f,0x5a,0xf2, + 0x32,0x98,0xb4,0xdb,0xb5,0xf8,0xec,0xee,0x12,0x3e,0xfd,0x76,0x9,0xed,0x8e,0x8d, + 0x6f,0x63,0x6a,0x3b,0xa2,0xdc,0x86,0x83,0xf4,0xc4,0x8f,0x55,0x69,0xd2,0xa,0x7c, + 0x77,0xe1,0x70,0x2c,0x41,0x40,0x9d,0x40,0x2d,0x88,0x1e,0x49,0xcf,0x87,0x60,0x85, + 0xc7,0x92,0x75,0x43,0x62,0x3,0x4c,0x22,0x2a,0x43,0xbd,0x1a,0xe1,0xcb,0xc,0x4f, + 0x8c,0xf6,0xd3,0xe4,0xc8,0x0,0x2a,0x3d,0xa0,0x62,0x59,0xe4,0xdb,0x1d,0x8b,0xc7, + 0xcf,0xb7,0xb1,0xb9,0x7b,0x98,0xf6,0xf3,0xdc,0x63,0x2f,0x2d,0xed,0x41,0x65,0x7a, + 0xa2,0x56,0xb,0xa,0x98,0x4c,0x5f,0x6e,0x53,0x23,0x3,0xb8,0x7e,0x71,0x1e,0x13, + 0xc3,0xfd,0x2f,0x9c,0x80,0xe5,0xc7,0x77,0xe,0x8e,0xf1,0x8b,0x2f,0x1e,0xe0,0x9b, + 0x47,0xeb,0x6e,0x35,0x97,0xe9,0xaa,0x88,0x72,0xd2,0xad,0xb8,0xa8,0x4,0x1,0x87, + 0x88,0x71,0x76,0x6e,0xc,0xdf,0x7b,0x6d,0x1,0x3f,0x7c,0xe3,0xc,0xce,0xcd,0x8d, + 0x61,0x72,0x64,0x0,0x83,0xcd,0x5a,0x61,0xe2,0x7e,0x55,0x8e,0xb,0x0,0x1c,0x1e, + 0x9f,0xe0,0xef,0x3e,0xbd,0xc7,0x7f,0xff,0xf9,0x7d,0xfe,0xe8,0xd6,0x63,0xde,0xdc, + 0x3d,0x82,0xf5,0x90,0x79,0xf2,0xd5,0x40,0x9c,0xc2,0x3,0x5,0x8a,0x3d,0xa2,0xe3, + 0x4b,0xb,0x33,0x47,0x67,0x76,0x3f,0xa5,0x3b,0xf7,0x6,0x2,0xb1,0xb5,0x22,0x7e, + 0xc1,0x4d,0xb8,0xec,0x12,0x55,0xbb,0x4c,0x8,0x4d,0x42,0x88,0x2e,0xc,0xe6,0x47, + 0x96,0xbd,0x8c,0x57,0xe0,0xd6,0xac,0x58,0x81,0x92,0xb,0x91,0x5c,0x3c,0x65,0x31, + 0x37,0x4a,0x72,0x29,0x51,0x8f,0x32,0xee,0x54,0x90,0xc7,0x55,0x63,0xa6,0xb7,0x94, + 0x7c,0xab,0xe0,0x2c,0xa3,0xa5,0x6c,0x8a,0x8,0x23,0xa2,0x56,0x23,0x3c,0xa4,0x95, + 0xf0,0xc4,0x54,0x70,0x9d,0x2b,0x10,0x69,0xb4,0x18,0x4b,0x6d,0x9a,0x55,0x5e,0x4a, + 0x96,0x3,0xa5,0xa0,0x66,0x88,0x9d,0xb8,0x1e,0xdf,0xd3,0x38,0x6e,0x42,0x26,0x85, + 0xa1,0x24,0x95,0x4a,0x3b,0xf1,0x8a,0x9f,0x48,0x7c,0x30,0x88,0x49,0x70,0xbb,0x1b, + 0x15,0x3,0x45,0x1,0xc6,0x50,0x1c,0x76,0x4d,0x70,0x6d,0x37,0x71,0x65,0x1d,0xa7, + 0x75,0xca,0x37,0x5b,0x9e,0xde,0x60,0x4c,0x46,0xa4,0x2a,0x4e,0x8a,0x1,0x1b,0xa6, + 0x1e,0x70,0x56,0x8e,0x81,0x8,0xba,0x5d,0x49,0x58,0x86,0x9c,0xc,0x84,0x74,0x91, + 0x2b,0x9c,0x95,0x7f,0xd6,0xeb,0x9a,0xa,0xb4,0xd7,0x3f,0x4,0x43,0x3f,0x9d,0xed, + 0xc6,0x4,0x36,0x11,0xc5,0x41,0x8a,0x84,0x9d,0x2e,0x15,0xfa,0xab,0x4,0xc3,0xb3, + 0x98,0x5,0xf3,0xc2,0x92,0x82,0xb7,0x13,0xc1,0x4e,0x4a,0x2f,0xa2,0x5c,0x8a,0xd5, + 0x6e,0x29,0xb2,0xeb,0x92,0x69,0x83,0xc1,0xc3,0x95,0x4d,0xfc,0xfc,0xcb,0x7,0x5c, + 0xa9,0x10,0x9d,0x9e,0x19,0xeb,0x79,0x60,0xe4,0x6,0x20,0xcc,0x8c,0x81,0xbe,0x3a, + 0x5e,0x3f,0x37,0x83,0x93,0x4e,0x17,0xfd,0xcd,0x3a,0x6e,0xde,0x5f,0xc6,0xbd,0xa7, + 0x1b,0x58,0xde,0xdc,0x43,0xbb,0xd3,0xcd,0xa6,0xa3,0x62,0xfe,0xd,0xca,0x98,0xab, + 0x25,0x3a,0x96,0xb2,0x78,0x45,0x29,0xdf,0xf7,0x10,0x71,0x21,0xb3,0x27,0xec,0xc2, + 0x39,0x1b,0xe1,0xfc,0xe1,0x25,0x13,0x9b,0x3,0x99,0xc7,0x83,0x33,0xe4,0x78,0x64, + 0x16,0xea,0x64,0x17,0xcb,0x15,0x21,0xd9,0xc,0x93,0x5b,0x48,0x56,0xf3,0x11,0xb5, + 0xe1,0x75,0xab,0xb8,0xa,0x37,0xd0,0xac,0xd1,0xc5,0xc5,0x49,0x9c,0x9a,0x1a,0x29, + 0xd5,0x7,0x97,0xfd,0xe9,0x58,0xc6,0x97,0x77,0x56,0xf8,0xb3,0x3b,0xcb,0xdc,0x8d, + 0x9a,0xf4,0x4,0xad,0x53,0x68,0x7a,0x52,0xac,0xa8,0x23,0xc0,0xf9,0x3,0x16,0x86, + 0x99,0xa3,0x6f,0xb6,0xe5,0xb8,0xf5,0xe2,0xc2,0x66,0xcf,0x95,0x45,0x3f,0xa7,0xb9, + 0x79,0x22,0x2a,0x34,0x64,0xe4,0x32,0x27,0x67,0xc3,0x2,0x49,0x37,0xb9,0x92,0x92, + 0x26,0x2a,0x56,0xab,0x15,0xcc,0x8c,0xd,0x62,0x7a,0x6c,0xd0,0xfb,0xd1,0xbc,0x78, + 0xc5,0xb0,0xb2,0xb9,0x87,0xb5,0xed,0x7d,0x74,0xac,0x60,0x1e,0x11,0x95,0x2f,0xc0, + 0x33,0xb9,0xa4,0x41,0x51,0x83,0x6c,0x32,0x9c,0x54,0x2e,0xf5,0xa6,0xc7,0x6,0x71, + 0xe3,0xe2,0x5c,0xd4,0xc8,0xe7,0xc4,0xb7,0xb2,0xc7,0xb7,0xbd,0xdf,0xc2,0x6f,0xbf, + 0x7d,0x8a,0xfb,0xcf,0x36,0xf5,0x2f,0xa5,0x12,0xd4,0x42,0x6,0x93,0x30,0xa3,0x56, + 0x33,0x98,0x19,0x1f,0xc2,0xec,0xf8,0x10,0xe6,0x27,0x86,0x71,0xe5,0xf4,0x24,0xae, + 0x9d,0x9d,0xc1,0xf5,0xb,0xb3,0x18,0xf0,0xa8,0x4d,0x59,0x4e,0x7b,0x19,0x61,0x32, + 0xdf,0xe9,0xef,0x1f,0x1e,0xe3,0xe1,0xca,0x16,0x6e,0xde,0x5b,0xe1,0x5f,0xde,0x7c, + 0xc8,0x9f,0x7e,0xb7,0xc4,0x1b,0x3b,0x87,0xbe,0xed,0x8b,0xd5,0x80,0x7d,0xb,0x14, + 0xb2,0xd0,0x1c,0x74,0xee,0xaa,0x2d,0x13,0xb3,0x25,0xa2,0xc8,0x62,0x7,0x60,0xbd, + 0x9,0xb0,0x37,0xe1,0xf4,0xa1,0xaa,0x6,0xec,0xba,0x84,0x30,0xa5,0xbb,0x17,0x87, + 0x4,0x5f,0x27,0xd8,0x97,0xe5,0xaa,0x25,0x4a,0x53,0x72,0xec,0xd2,0xd3,0x31,0x2a, + 0x1c,0xe4,0xa,0xe6,0x6a,0x22,0x8c,0xc5,0x94,0x46,0x9d,0x95,0xcc,0xee,0x21,0x3e, + 0x95,0x48,0xec,0xfb,0x32,0x2d,0x77,0xb6,0xa0,0x95,0xec,0x5b,0x96,0xbe,0xb3,0x62, + 0xe0,0x4e,0xec,0x5c,0xb1,0x43,0x20,0x2a,0x4c,0x99,0xc5,0xa0,0x7b,0xf9,0xf0,0x62, + 0x6e,0x44,0x89,0xdd,0x66,0xf6,0xdc,0xbd,0x4,0x4d,0xce,0xef,0x4c,0x4c,0x22,0x32, + 0x24,0xa6,0xd6,0xb3,0xdf,0x93,0x1b,0x5,0xa5,0x7,0xe8,0xb6,0x22,0x8a,0x79,0x80, + 0x16,0x89,0x60,0x60,0x1c,0x7c,0x9e,0x52,0xba,0xa3,0x83,0x21,0x85,0xc2,0xee,0x27, + 0x47,0x91,0xdb,0xa9,0x9,0x5e,0x42,0xa3,0xc5,0x2c,0xf0,0x7f,0x56,0x7a,0x7f,0x65, + 0xfa,0x11,0xe0,0x26,0x71,0xc5,0xe7,0xda,0xe5,0xa2,0x60,0xa2,0x87,0xfe,0x53,0x7e, + 0xd,0xe9,0x40,0x5c,0x72,0x62,0x4c,0x21,0x48,0xe3,0xcc,0x17,0x5b,0x2b,0xe,0x74, + 0x87,0x95,0x88,0x6f,0xc2,0x7c,0x25,0xf4,0x74,0xee,0x5f,0xa1,0x43,0x54,0x4,0xd, + 0x23,0x61,0x78,0xe4,0xce,0x3,0x5c,0x4c,0xb7,0xcd,0x46,0x80,0x28,0x8e,0x16,0xba, + 0x67,0x3f,0x9f,0x18,0x29,0x82,0x4b,0x27,0xdb,0xea,0xf6,0x1,0xfe,0xfd,0x2f,0x6f, + 0xf1,0xc4,0x70,0x3f,0xce,0xcc,0x8e,0x93,0xc,0x1,0x79,0xd9,0x24,0x10,0xde,0x86, + 0x37,0x2f,0xce,0xe1,0xca,0x99,0x29,0xdc,0xbc,0xb7,0x82,0x5f,0xdc,0x7c,0x88,0xf, + 0x3e,0xb9,0x8b,0xc7,0xcf,0xb7,0x71,0x78,0xdc,0xc9,0x90,0xa7,0x30,0x41,0x73,0x16, + 0x87,0x9a,0xa7,0x45,0x67,0xa8,0x93,0xec,0x77,0xf2,0x17,0x47,0x2a,0xf,0xa3,0xa6, + 0x42,0x92,0x3d,0x3d,0xc7,0x5b,0xb8,0xa,0x22,0x5e,0xf8,0x16,0x11,0x30,0xb2,0xc6, + 0x77,0x0,0x51,0xa4,0xc1,0xa8,0xc8,0x7e,0x33,0x8f,0x8e,0x11,0x4a,0x83,0xe8,0x27, + 0x60,0x22,0x99,0x35,0x67,0xf5,0xd,0xd,0x34,0xf1,0xd6,0xa5,0x39,0x9a,0x9f,0x1c, + 0xa6,0x5e,0x39,0xe1,0xf2,0x80,0x66,0x66,0xec,0x1d,0x1e,0xe3,0xd6,0xa3,0xe7,0xb8, + 0xbf,0xbc,0x11,0xf9,0x24,0xc,0x99,0xcb,0x99,0xa6,0x70,0xe,0xb1,0xf,0x94,0x18, + 0x1f,0x6e,0x6a,0x42,0xf4,0xdd,0x26,0x39,0xa4,0xc6,0x6f,0x77,0x63,0xbd,0x21,0xcf, + 0x6c,0x22,0xed,0x98,0xec,0x8f,0xd,0x61,0x14,0x15,0x18,0xfb,0xb2,0x33,0xa4,0x88, + 0xb8,0x28,0x53,0x69,0xdf,0xdb,0x8e,0xe,0x36,0x31,0x3d,0x3e,0x88,0xc1,0x17,0x30, + 0xc8,0x89,0x8,0x9d,0x4e,0x7,0x4f,0xd6,0x76,0xf1,0xdd,0x93,0x75,0xec,0x1e,0x9e, + 0x40,0x27,0xad,0x94,0xde,0xb5,0x45,0x49,0x1b,0x65,0x3a,0x66,0x92,0x24,0x59,0x28, + 0x4f,0x75,0x0,0x98,0x9d,0x18,0xc6,0xf5,0xf3,0xb3,0x18,0x1d,0xe8,0x2b,0x14,0xc8, + 0x32,0x86,0x3b,0x33,0x63,0x79,0x63,0x17,0xdf,0x3c,0x5e,0xc3,0xde,0x51,0x3b,0xc5, + 0x78,0xaa,0xf7,0x52,0xc2,0x49,0x89,0xac,0x55,0xaf,0x57,0xb0,0x38,0x3d,0x82,0x1f, + 0x5c,0x3b,0x8d,0xdf,0x79,0xe3,0xc,0x6e,0x5c,0x9c,0xc3,0x48,0x7f,0x23,0x32,0xd7, + 0x15,0xf,0xf9,0x25,0xe,0x75,0x39,0xff,0x62,0xef,0xe0,0x18,0x77,0x9f,0xad,0xe3, + 0x7f,0xfb,0xe0,0x2b,0xfe,0xbb,0xcf,0xef,0xdb,0xcd,0x9d,0x43,0x74,0x39,0x7a,0x27, + 0x25,0xde,0x85,0xe7,0x54,0x70,0x84,0xd2,0x5d,0x3,0xe8,0xaf,0x16,0xcf,0x19,0x65, + 0x76,0x92,0x4d,0xa,0x45,0xdf,0x46,0x8,0xde,0xc9,0x77,0x93,0xb4,0xcd,0x2d,0xda, + 0x98,0xc4,0x2f,0x71,0x1c,0x6d,0x83,0xb8,0x49,0xf,0x6f,0x8e,0xb1,0x2a,0x4a,0x47, + 0xda,0x32,0x92,0xe8,0xc8,0x88,0x65,0x2e,0x3a,0x94,0xbf,0x4a,0xd0,0x41,0xb,0x8b, + 0x81,0xa2,0xba,0x41,0x62,0x30,0xfe,0x12,0xad,0x92,0xd1,0x3f,0x91,0x24,0xc6,0x1f, + 0xf7,0x9f,0xc2,0xb4,0x44,0x25,0x6f,0xa,0x5f,0xf5,0x58,0xda,0x34,0x6,0x48,0xe5, + 0x2b,0x21,0x2d,0xff,0x29,0xcb,0x39,0xcf,0x2c,0x2a,0xf3,0x76,0x50,0x1c,0x37,0x62, + 0xa3,0x9b,0xc0,0xb2,0x24,0x3b,0xb,0x93,0x9d,0x21,0x13,0xaf,0x22,0x26,0x13,0x8a, + 0x31,0x79,0x8b,0x51,0x37,0x55,0x1b,0x4a,0xcc,0xf6,0x24,0x81,0xa,0x41,0x21,0x2a, + 0xaa,0x33,0xe5,0xb0,0x85,0xd3,0xce,0x21,0xe5,0x26,0xc,0x85,0x1a,0x10,0x8e,0xf4, + 0x3d,0x93,0x6c,0xbd,0x3,0xd4,0x22,0xea,0x3f,0x33,0x79,0x89,0xbc,0xd4,0xbb,0x16, + 0xb5,0x8d,0xba,0x0,0x72,0xa1,0xa4,0x53,0x11,0xe3,0x15,0xff,0xdf,0x72,0x54,0x21, + 0xc4,0x89,0x3d,0xc6,0xed,0x25,0xf9,0x92,0x2a,0x4e,0xca,0x6c,0x4b,0xa5,0xf1,0x12, + 0xb1,0x18,0xe9,0xa2,0xff,0x6,0x4c,0x81,0xc6,0x29,0x1c,0x6b,0x33,0xa8,0x81,0x4a, + 0x44,0x9a,0xd1,0x8,0x36,0xfe,0x62,0x43,0x49,0xcb,0x20,0x44,0x73,0xf1,0xae,0xf, + 0xcd,0xa6,0x91,0xb,0xa,0x26,0x2,0xb5,0xda,0x1d,0xbe,0xf3,0x64,0x83,0x7e,0xfd, + 0xd5,0x63,0xcc,0x4d,0xe,0xe3,0xcd,0xf3,0xb3,0x2a,0xf6,0xf2,0x45,0xbe,0xd0,0xf2, + 0x4f,0xa3,0x56,0xc5,0xd5,0x33,0xd3,0x18,0x1d,0xea,0xc3,0x8d,0x8b,0x73,0x78,0xf2, + 0x7c,0x1b,0x8f,0x56,0xb6,0xf1,0xe8,0xf9,0x36,0x9e,0xae,0xed,0x60,0x79,0x63,0xf, + 0xc7,0x9e,0x3c,0x47,0x7a,0xe1,0x59,0x32,0x9b,0x53,0x71,0x75,0x1e,0xc1,0x25,0x2e, + 0xc4,0xd3,0xca,0x43,0x33,0x67,0x26,0x51,0x64,0xd4,0x7,0x9a,0x22,0x53,0x14,0x9c, + 0x53,0x85,0x5c,0xa0,0x4,0xb1,0xf3,0x71,0xf0,0x4b,0xc,0xe,0xab,0x2c,0xef,0x4c, + 0x64,0x98,0x62,0x0,0x84,0x30,0xfa,0x53,0x8b,0x67,0xe3,0xe9,0x60,0x54,0x21,0x75, + 0x93,0x7b,0x74,0x7e,0xa0,0x59,0xc7,0x9b,0x17,0xe6,0xe3,0x84,0xde,0x8b,0xd4,0x14, + 0x8a,0xf9,0xd6,0x5e,0xb,0x37,0xef,0xaf,0x60,0x75,0xeb,0xc0,0xc1,0x86,0x2a,0x29, + 0x45,0xd8,0xb7,0x4a,0xa2,0x9e,0xf3,0x74,0x47,0x88,0x55,0xe1,0x84,0x9a,0x7b,0x23, + 0xc4,0x30,0xa7,0x85,0xdf,0xe5,0xae,0x7,0x36,0xc9,0x10,0x4e,0xea,0xcd,0x52,0xd8, + 0x94,0xc0,0x48,0x21,0x15,0xb0,0x4,0xce,0x41,0x4f,0xe1,0xc9,0xd,0x6,0x46,0x86, + 0xfa,0x70,0xed,0xdc,0x2c,0x4d,0xf8,0x34,0xbf,0xdc,0xf3,0x40,0x5e,0x4b,0x95,0x4a, + 0x5,0x37,0xef,0xad,0xe0,0xd3,0xef,0x9e,0xe1,0xb8,0xdd,0x4d,0x11,0xa8,0x8a,0x6e, + 0x58,0xb2,0x12,0x2f,0xc1,0xe8,0x8,0x7a,0x32,0x2e,0x1,0x29,0x1,0x0,0x33,0xe3, + 0x83,0xb8,0xb4,0x30,0x81,0xc1,0xfe,0xfa,0xb,0xb,0x79,0xf8,0xdc,0xed,0xc7,0xeb, + 0xf8,0xfc,0xce,0x32,0xf6,0xf,0xdb,0x51,0x6,0xab,0x42,0xbb,0x2,0xc4,0xe1,0x1f, + 0x4a,0x5f,0xa3,0x86,0x73,0x73,0x63,0x78,0xed,0xf4,0x14,0x2e,0x2d,0x4c,0xe2,0xf4, + 0xec,0x8,0x66,0xc7,0x86,0x30,0x33,0x3e,0x88,0x89,0xe1,0xfe,0xd2,0xe9,0x3b,0xdf, + 0x93,0xe7,0x51,0xb3,0x72,0x82,0xdf,0xda,0x3b,0xc2,0xa7,0x77,0x9e,0xf1,0xcd,0xbb, + 0xcb,0xf8,0xfa,0xe1,0x1a,0x7f,0xf7,0x64,0x8d,0xd7,0x77,0xe,0x3d,0xc7,0x94,0x52, + 0xe8,0x5e,0x78,0x2a,0x5e,0x5b,0xee,0xfe,0x2f,0x14,0x77,0xb2,0xfe,0x15,0xf1,0x53, + 0x3a,0x2c,0x18,0xd6,0x26,0x6b,0x25,0xf6,0xd6,0x4b,0x9c,0xf2,0xc2,0x2c,0x5b,0xd7, + 0xa,0x2,0xb0,0x6c,0x61,0x18,0x64,0xd9,0xa9,0xad,0x98,0x11,0xec,0xe,0xac,0x5f, + 0xad,0x79,0xb8,0x5d,0x6e,0xfe,0xa2,0xee,0xc4,0xa4,0x46,0x5f,0xba,0x60,0x13,0x97, + 0x10,0x1e,0xa5,0x9f,0x9a,0x28,0xc1,0xf2,0xeb,0x19,0xa9,0x46,0x86,0x7b,0xa6,0xaa, + 0xfd,0x2b,0x95,0xc4,0x5b,0x97,0xb,0xca,0xba,0x9,0x96,0xcd,0xab,0x7b,0x73,0xa9, + 0x64,0xe7,0x9b,0x5b,0xaf,0x27,0xf9,0x49,0x3e,0xf9,0xa7,0x88,0x55,0x99,0xe,0x84, + 0xc2,0xc,0xa0,0x3d,0x63,0xf5,0x52,0x58,0x9a,0x86,0x5,0x1a,0xa0,0x89,0xbb,0x71, + 0xaf,0xae,0x71,0xf2,0x27,0xc9,0x9e,0xe,0x0,0x1a,0xb9,0xfc,0xc3,0x4,0xa3,0x27, + 0x99,0x4e,0x0,0xed,0x9d,0x35,0x19,0x94,0x9,0x2c,0x48,0x18,0x58,0x7,0x6b,0x52, + 0x13,0x47,0xcd,0x62,0xcb,0x2d,0x1d,0x93,0xb2,0x9e,0x25,0xb6,0xb,0x96,0x38,0xac, + 0x2,0xf4,0xfe,0x9c,0x32,0xaa,0x93,0x20,0x4f,0x70,0x96,0x37,0x4b,0x54,0x32,0xaf, + 0x5b,0xaf,0xfe,0x74,0x27,0xa1,0x94,0x3b,0x93,0x72,0x99,0x9,0xb6,0x85,0xa1,0x51, + 0x4b,0xd2,0x9c,0xe4,0x2a,0x9a,0x45,0xa2,0x4a,0xd2,0x9f,0xdc,0xc8,0x94,0x21,0x6, + 0xc2,0x59,0x90,0x95,0xbc,0xa5,0x60,0x5,0x2c,0x8a,0x75,0xf0,0x89,0x4f,0xd,0x66, + 0xfa,0x32,0x13,0x65,0x24,0x44,0x49,0x9c,0x4c,0x42,0x1e,0x79,0xdc,0xee,0xf2,0xa7, + 0x77,0x96,0x30,0x34,0xd8,0x44,0x5f,0xbd,0x4a,0x57,0xcf,0xce,0x14,0x60,0xc6,0xfc, + 0x40,0x91,0x7,0x4d,0x38,0x80,0x6,0xfb,0x1b,0xb8,0xd4,0xdf,0xc0,0xa5,0x85,0x49, + 0x1c,0xb4,0x4e,0xf0,0x70,0x79,0x3,0xb7,0x1e,0xae,0xe1,0xee,0xd2,0x3a,0x1e,0x2e, + 0x6f,0xe1,0xf9,0xe6,0x3e,0x76,0xf,0x8f,0xd1,0xb5,0x16,0xb6,0xcb,0xe8,0x58,0x8b, + 0xae,0xb5,0xe8,0x76,0x19,0x96,0xfd,0xdf,0xbb,0x16,0xd6,0xa6,0xe6,0xac,0x48,0x58, + 0x16,0x1c,0x14,0x12,0xaa,0x8f,0x18,0x68,0x44,0x5,0xd7,0xba,0xc0,0x7f,0x61,0xe9, + 0x1f,0x4a,0x44,0x64,0x1d,0xab,0xd5,0xdd,0xaa,0x26,0x30,0x7d,0x43,0xee,0xa3,0xb7, + 0xb3,0xf6,0x12,0xcf,0xf0,0xfe,0x1a,0x16,0xcb,0x7f,0xe9,0xaf,0xaf,0xf6,0xe8,0xda, + 0xa9,0x9e,0x8,0xe3,0x23,0x3,0x74,0x71,0x61,0x82,0xa6,0x46,0x7,0x7a,0x92,0xe, + 0xe5,0x74,0xf6,0xf8,0xf9,0x16,0x7e,0xfb,0xcd,0x53,0x5e,0xdf,0x3d,0x64,0x49,0x22, + 0xf2,0xae,0x38,0x61,0x72,0xe6,0xa8,0xdd,0x8,0x82,0x22,0xb2,0x4e,0x72,0x44,0x9, + 0x8c,0x70,0x6,0x3a,0xe9,0xef,0xec,0x13,0xcf,0xa3,0x23,0xa4,0x83,0xb,0xf2,0x5b, + 0x92,0x35,0xe7,0x85,0x72,0xd3,0xa4,0x44,0xbb,0x9,0x81,0x1a,0x42,0x7d,0x12,0xb8, + 0x74,0x8b,0x33,0x23,0x78,0xff,0xea,0x22,0x26,0x47,0x6,0x7b,0x12,0xe1,0xc2,0xf3, + 0xdf,0x3f,0x6c,0xe3,0xeb,0x87,0xcf,0x71,0xf3,0xde,0x8a,0x37,0x3d,0x12,0x52,0x2d, + 0xc5,0x93,0xe6,0xb2,0x33,0x50,0xa0,0x9f,0x32,0x2e,0x82,0x91,0x3d,0xf4,0x78,0x5f, + 0x8c,0xd,0x35,0x31,0x3f,0x31,0x84,0x51,0x1f,0x6c,0x52,0x96,0xdb,0x2e,0xaf,0xfb, + 0x93,0x4e,0x7,0x5f,0xde,0x7f,0x8e,0x8f,0x6f,0x3f,0xf3,0x9c,0x6,0x28,0xb6,0x7a, + 0xf8,0xb9,0x7d,0x8d,0x1a,0x1a,0x15,0x83,0xf1,0xe1,0x3e,0x9c,0x99,0x1d,0xc3,0xf5, + 0xf3,0x33,0x78,0xfb,0xd2,0x29,0xbc,0x71,0x6e,0x3a,0xc2,0xea,0xf2,0xb9,0x97,0xc5, + 0xca,0xbe,0x28,0x2c,0xe9,0xa4,0xd3,0xc1,0xee,0x61,0x1b,0x5b,0xbb,0x47,0xf8,0xf6, + 0xf1,0x1a,0xff,0xed,0xa7,0xf7,0xf8,0x37,0xdf,0x3e,0xc5,0xfa,0xf6,0x41,0xa,0x58, + 0xf1,0xe5,0xd2,0x2b,0x10,0x43,0xca,0x3a,0x47,0xdf,0x2,0xe,0x26,0x32,0xb0,0xfe, + 0xa4,0xb5,0x4c,0x96,0x61,0xd9,0x7a,0x52,0x11,0x93,0x13,0x10,0x59,0x26,0x62,0xb2, + 0xcc,0xec,0x72,0xd5,0x7c,0x47,0x6c,0x98,0x60,0xa3,0xb4,0x8d,0xe0,0xa4,0x6f,0x30, + 0x81,0x37,0x4c,0x61,0x89,0x23,0x8a,0xb4,0xe6,0x42,0xa8,0x74,0x35,0x53,0x84,0x9a, + 0xd9,0x94,0x34,0xf5,0x2a,0xb7,0x86,0xa0,0x3c,0x5b,0xa2,0x3f,0x41,0x0,0xcb,0xc, + 0x7c,0xde,0xb4,0x33,0x96,0xd1,0x81,0x88,0x54,0x10,0xb6,0x53,0xc6,0xce,0x92,0x6b, + 0x72,0x52,0x24,0x51,0xe8,0x53,0x9c,0xb2,0xbd,0xa0,0x24,0x83,0x9,0xa6,0x8a,0xa, + 0x75,0xa1,0x8c,0xc7,0x2d,0x31,0x2d,0xf5,0x20,0x88,0x20,0x6,0xc3,0x60,0x11,0x9e, + 0xaa,0x4e,0x32,0x1f,0x9,0x6e,0xdf,0x4,0x43,0x1e,0x40,0xf,0x2c,0x3f,0x32,0xbe, + 0x88,0x47,0xe1,0x7a,0x8,0x4,0x49,0x5b,0x32,0x47,0x7c,0x73,0xdf,0x6e,0xf4,0x82, + 0x24,0x65,0x73,0x7b,0x24,0xd2,0xfb,0x8d,0xa7,0x72,0xcf,0x2a,0xbc,0x91,0x42,0xdc, + 0xad,0xf7,0x35,0x8,0xbf,0xc2,0x72,0x2c,0x6c,0xe1,0x5d,0xac,0x68,0xe5,0x9f,0x61, + 0x88,0x20,0x36,0xce,0xf8,0xef,0xa4,0x38,0xb,0x9c,0xf9,0xf3,0x73,0x8c,0x42,0x63, + 0x30,0x2a,0x14,0x56,0x25,0x24,0xa4,0x6b,0x2c,0xe3,0xe5,0x42,0x6b,0xc8,0x25,0x45, + 0x18,0x81,0xc7,0x25,0xad,0x73,0x59,0xec,0x22,0x85,0x12,0x5c,0xe5,0x4e,0x16,0xd2, + 0x62,0x14,0x69,0xc4,0xa3,0x13,0x1c,0x1d,0xce,0x72,0x82,0x90,0x57,0xac,0x89,0x58, + 0x5f,0x2a,0x4c,0xc1,0xe2,0x82,0x2f,0xe9,0x7d,0x89,0x9,0xb8,0xb7,0xb4,0xc5,0x7, + 0xad,0xdb,0x30,0x64,0x70,0x7c,0xd2,0xa5,0xb7,0x2e,0xcd,0x97,0xba,0x51,0xe9,0x10, + 0x85,0x72,0xd2,0x1c,0x11,0xa1,0xaf,0x5e,0xc1,0xb9,0xb9,0x9,0x2c,0x4c,0x8d,0xe2, + 0x27,0x37,0xce,0xe2,0xb8,0xd3,0xc5,0xc1,0x51,0x1b,0xdb,0xfb,0x2d,0xac,0x6e,0xed, + 0x63,0x6b,0xef,0x8,0xdb,0xfb,0x2d,0x6c,0xed,0x1d,0x62,0xe7,0xe0,0xd8,0xff,0xfd, + 0x8,0x3b,0xfb,0x2d,0x6c,0xee,0xb5,0x70,0x7c,0xd2,0x29,0xf1,0xe,0x28,0xd9,0x8f, + 0x51,0x76,0xf9,0xcb,0x1b,0x4c,0x91,0x5d,0xd,0xb4,0x73,0x3e,0xc9,0xc0,0x2,0x19, + 0xa7,0x90,0x2a,0x40,0xe0,0x46,0x9a,0x0,0x48,0xb1,0x77,0x9b,0x4b,0xaa,0x38,0x13, + 0xd7,0x51,0x14,0xd0,0xf6,0xd0,0xd,0x6,0xe0,0x89,0x9a,0xf5,0x2a,0x4e,0x4d,0xd, + 0x63,0xc2,0xe7,0x6b,0xbf,0x8a,0x3b,0xdc,0xa3,0x95,0x6d,0xfc,0xfc,0xe6,0x23,0x1f, + 0x80,0xe3,0x16,0x96,0x9,0x18,0x22,0x41,0x87,0x8d,0x35,0x8c,0x75,0xc0,0x2b,0x85, + 0x6b,0x37,0x91,0xa,0x81,0x44,0x2c,0x80,0x11,0x67,0x92,0xc9,0xa6,0x23,0x61,0x2d, + 0x49,0x31,0x82,0x4b,0x70,0x8,0x32,0xd6,0xb9,0xa1,0x4c,0x5d,0x1b,0x1e,0x9d,0xc1, + 0xe9,0x99,0x31,0xfa,0xf1,0x8d,0xb3,0x98,0x18,0x6e,0xf6,0x5c,0xe3,0x30,0x33,0x8e, + 0x4f,0x3a,0x78,0xb0,0xb2,0x89,0x3b,0x4b,0x9b,0x58,0xdf,0x3b,0xd2,0x56,0xf9,0x54, + 0xc0,0x6d,0x50,0x8c,0xb9,0x92,0x99,0xe8,0x3a,0xd2,0xba,0x88,0x74,0x12,0x6,0xfa, + 0x6a,0xb8,0x7e,0x61,0x16,0xa7,0x67,0xc6,0x5e,0x98,0x65,0x20,0xdf,0xab,0xf6,0x89, + 0xc5,0xd7,0xf,0x57,0xf1,0xc5,0xbd,0x67,0x38,0xe9,0x48,0xf8,0x38,0x3d,0x8e,0xf1, + 0xe1,0x7e,0xbc,0x79,0x7e,0x6,0xef,0x5d,0x39,0x85,0xd7,0xce,0x4e,0x63,0x7e,0x62, + 0x8,0x23,0x3,0x4d,0xd4,0xab,0x15,0xf4,0x35,0xaa,0xa5,0x8d,0x4c,0xaf,0x6b,0xa2, + 0xec,0x6b,0x98,0x19,0x8f,0x9e,0xef,0xe0,0x97,0x37,0x1f,0xf1,0x87,0x5f,0x3d,0xc6, + 0xed,0xc7,0x6b,0xbc,0x77,0xd4,0xe6,0xd6,0x71,0x3b,0xf2,0x23,0xdc,0x84,0x6c,0x2, + 0xb2,0xce,0x9c,0x7c,0x4,0x9c,0x2d,0x9,0x5b,0x26,0x76,0xa6,0xec,0x7e,0xa,0x70, + 0xd3,0x38,0x93,0x75,0xf8,0xbb,0xb5,0x51,0x35,0xe1,0xde,0x48,0x9b,0x48,0x96,0xd0, + 0xb2,0x36,0x6f,0x21,0x17,0x7,0x60,0xff,0x31,0x25,0x21,0x64,0x66,0x86,0x41,0x16, + 0x4a,0xa9,0xc,0xba,0x90,0xad,0x4f,0x94,0xb,0x25,0x33,0xe4,0x16,0x4b,0x42,0xec, + 0x2c,0xc4,0x3c,0xf9,0x9a,0x4e,0xca,0x66,0xab,0x44,0x54,0x2e,0xbc,0x29,0xa1,0x4d, + 0x2b,0x47,0xb8,0x2c,0xbf,0x94,0x20,0xad,0xe8,0x49,0xf9,0x9,0xc7,0xcc,0xe8,0x10, + 0xc1,0x18,0x8e,0x1a,0xe3,0xf,0x8e,0x94,0x69,0x16,0xed,0xec,0x54,0x47,0xc8,0x81, + 0x0,0x47,0x1,0x79,0xa5,0x48,0xc0,0x33,0x22,0xcf,0x26,0x38,0xb4,0xc7,0x4c,0x6c, + 0xc4,0x22,0x1e,0x8e,0x24,0x3,0x43,0x30,0x64,0x18,0x29,0x61,0xdb,0xb1,0x6e,0x5c, + 0xa1,0xf7,0x66,0xa2,0x86,0x22,0xa1,0x1d,0x9,0x6a,0xcf,0x65,0x3b,0x24,0x65,0x3d, + 0x91,0x29,0x1f,0xfd,0xce,0xc3,0xb7,0x6,0xf4,0x81,0x8c,0x37,0xae,0x8c,0xfb,0x28, + 0x72,0xc5,0x9d,0xc,0x45,0x5a,0xc,0xe5,0xbb,0xd4,0x40,0xc0,0x60,0xa5,0x3b,0xd6, + 0x5a,0xa1,0xf4,0xd,0xaa,0x6b,0x57,0xac,0x67,0x99,0x7a,0x14,0xe4,0x96,0x46,0xa9, + 0x97,0x8b,0xfb,0x91,0xfc,0xee,0x27,0x2a,0x63,0x54,0x33,0x91,0x24,0xc1,0x43,0x4e, + 0xeb,0x79,0xd8,0x4e,0x6e,0x3,0x4c,0x9a,0xc4,0x45,0x88,0xb2,0x90,0x4c,0x6a,0x2b, + 0x7,0x76,0x71,0x1f,0xa9,0x4c,0x60,0x8a,0x96,0x4a,0x9c,0xf3,0x10,0x23,0xd8,0x65, + 0x88,0x9e,0x6f,0xed,0xf3,0xcf,0xbe,0x78,0x80,0x93,0x6e,0x17,0x7,0xc7,0x27,0x74, + 0xed,0xec,0x4c,0x94,0xf2,0x48,0x2f,0xe8,0x30,0x31,0xbc,0x48,0x6e,0x65,0x8c,0x41, + 0x7f,0xd3,0x0,0xa8,0x1,0x68,0xaa,0xcf,0x6d,0xef,0x1f,0x63,0x7b,0xff,0x8,0x7, + 0xad,0x36,0xf6,0xf,0xdb,0xd8,0x3f,0x3a,0xc6,0xee,0x61,0xb,0x7,0xad,0x13,0xec, + 0x1f,0xb5,0xb1,0x77,0x70,0x8c,0xfd,0x56,0x1b,0x47,0xed,0xe,0x8e,0x8f,0x4f,0xd0, + 0x6a,0x77,0x70,0x7c,0xd2,0xc5,0xf1,0xc9,0x9,0x5a,0xc7,0x1d,0x1c,0xb5,0xbb,0x38, + 0x3a,0x3e,0xc1,0xd1,0x71,0x1b,0x47,0xc7,0x27,0xb0,0x10,0xb6,0x74,0x44,0x22,0xc3, + 0x3e,0x9,0x45,0xb4,0xfd,0x64,0x8,0x8c,0x4a,0xe3,0x9f,0x2b,0x8a,0x2,0x8b,0xf5, + 0x53,0x2b,0x2b,0xde,0x41,0x70,0xcb,0xa,0xe2,0x10,0x16,0xe1,0x84,0x2,0x3f,0x49, + 0xe,0xc,0xa8,0x18,0x83,0x73,0x73,0xe3,0x38,0x37,0x3f,0x8e,0xa6,0x3f,0xd0,0xcb, + 0xbc,0xb7,0xe5,0xeb,0xbb,0x7f,0xd4,0xc6,0xc3,0x95,0x2d,0x7e,0xb4,0xb2,0xcd,0x36, + 0xa6,0x5f,0x99,0x78,0x3a,0x12,0x49,0xca,0x67,0x8a,0xe0,0xd4,0xbc,0x43,0x4e,0x36, + 0xc9,0xf2,0x3e,0x8,0x24,0xe,0x75,0xf2,0x49,0xef,0x49,0x11,0x32,0x23,0x3b,0x4e, + 0xa2,0x18,0x6,0xab,0x14,0xa,0x99,0x75,0x74,0xf2,0xbb,0x37,0x98,0x9b,0x1c,0xc0, + 0xb5,0x33,0xd3,0x38,0x33,0x33,0x82,0x5a,0xb5,0xda,0x13,0x6a,0x27,0x22,0x2c,0xad, + 0xef,0xe1,0xd7,0xb7,0x9e,0xe0,0xe9,0xea,0x6e,0xe6,0xa3,0xa4,0x8b,0x99,0x3e,0x7f, + 0x65,0x46,0x45,0x6e,0x43,0x46,0x85,0xc3,0x9a,0x4,0x1,0xab,0xbf,0xaf,0x81,0xeb, + 0xe7,0x67,0xb1,0x38,0x3d,0x52,0x5a,0xcc,0x73,0xe2,0xd9,0x41,0xeb,0x4,0xb7,0x9f, + 0xae,0xe3,0xfe,0xf2,0x26,0x1c,0xdf,0xd3,0x9d,0xe8,0x7d,0x8d,0x1a,0x26,0x86,0xfb, + 0x30,0x3d,0x3a,0x80,0xe9,0xf1,0x41,0x9c,0x99,0x19,0xc5,0xe5,0x85,0x9,0x5c,0x5e, + 0x9c,0xc4,0x99,0x99,0x11,0x54,0x2b,0x95,0xd2,0x46,0x21,0xdc,0x23,0x39,0xe2,0x55, + 0xc6,0x5f,0x21,0x22,0x6c,0xef,0x1d,0xe1,0xd9,0xc6,0x1e,0x1e,0xae,0x6c,0xf3,0xd7, + 0xf,0x9f,0xe3,0xf3,0xbb,0xcb,0x7c,0xeb,0xc1,0x2a,0xbc,0x17,0x7b,0xda,0xaf,0x78, + 0x18,0x9c,0x61,0xd9,0x2d,0xb6,0x3d,0xa3,0x3d,0xfc,0x13,0x24,0x8e,0xee,0xd0,0x65, + 0x27,0xe9,0x21,0x26,0xb0,0x4d,0xcc,0x76,0x62,0x30,0x5b,0x87,0xa1,0xbb,0x1d,0x95, + 0x5,0xd9,0x60,0x2e,0xc3,0x48,0xc5,0x3c,0xfd,0x7c,0x62,0xcd,0x22,0xd7,0x6f,0xb, + 0x95,0x8,0xf3,0x95,0xca,0x42,0x20,0xdf,0x28,0xc4,0xa2,0x66,0x2a,0x19,0x2a,0x59, + 0x49,0x4a,0x8e,0x1a,0x69,0xce,0x24,0xc3,0x38,0x52,0x5c,0xd1,0x20,0x6,0xe5,0xda, + 0x47,0xe9,0x7,0x93,0x99,0xcd,0x48,0xee,0x12,0x67,0xf,0x20,0xfd,0x42,0x1,0x3b, + 0xf8,0x68,0xa9,0x50,0x8e,0x53,0x4,0xaa,0x38,0x58,0x42,0x5e,0xab,0x89,0xe8,0xa0, + 0x4c,0xe2,0x53,0x3,0x74,0xc8,0x95,0x74,0x28,0x4c,0xa8,0xc8,0xa1,0xde,0x19,0xe3, + 0x3f,0x6d,0xdc,0x18,0xe2,0xb7,0xe5,0x50,0x24,0x38,0x83,0xec,0xbf,0x5,0x13,0x48, + 0x4f,0xe3,0x14,0x86,0x71,0x29,0xa1,0x92,0x2f,0xb3,0x49,0x56,0x28,0x9,0x95,0x90, + 0x9b,0x39,0x31,0xee,0x86,0x74,0x1f,0x68,0x57,0xb7,0xf0,0x46,0x99,0xf8,0xdc,0xe2, + 0x24,0x9d,0x4c,0x64,0xb5,0x34,0x24,0x2c,0x9,0x83,0xab,0x2e,0x43,0x58,0xb3,0xb1, + 0xca,0x31,0x27,0xcd,0xdd,0x62,0x4a,0x1e,0xa6,0x32,0x50,0x8f,0xa,0xc,0x7,0xcd, + 0xd1,0x52,0xa4,0x39,0xca,0x90,0x15,0x42,0xf4,0x21,0x57,0x76,0xb,0x82,0xa9,0x4b, + 0x3a,0x76,0x31,0x6c,0x38,0xd,0x65,0x36,0x4,0xac,0x3c,0x3f,0x14,0xa3,0xce,0x8b, + 0x50,0x44,0x9c,0x2b,0xc7,0xa4,0x6c,0xdf,0x44,0xb9,0x5,0x9b,0x51,0x8c,0x8f,0x3b, + 0x4b,0xeb,0xbc,0xb6,0x73,0x80,0x27,0xab,0x3b,0xf8,0xf3,0x1f,0x5f,0xc3,0xef,0xdf, + 0x38,0x4b,0xcd,0x46,0xed,0xa5,0xf2,0x99,0x5e,0x93,0x7b,0x99,0xec,0x67,0x6c,0xa8, + 0x89,0xd1,0xc1,0x46,0x81,0xd1,0x2b,0x51,0x0,0x66,0xc6,0xc1,0xd1,0x9,0x76,0x8f, + 0x8e,0xb1,0xbe,0x73,0x80,0xcd,0xbd,0x23,0x6c,0xef,0x1e,0x62,0x73,0xaf,0x85,0xf5, + 0xed,0x3,0xac,0x6e,0x1f,0xe0,0xf9,0xd6,0x1,0x56,0xb7,0xf6,0xb1,0xba,0x7d,0xe0, + 0xf6,0xf3,0x92,0x4c,0x97,0x67,0x49,0x13,0x44,0x4b,0x69,0x7c,0x28,0x58,0x8,0x1f, + 0x9,0x1a,0xca,0x34,0x5b,0x73,0xc9,0x5c,0x18,0xa7,0xd4,0x54,0xb5,0x0,0x5d,0xb, + 0x29,0xb,0x69,0x22,0x53,0x31,0xb8,0x74,0x7a,0x92,0xae,0x2c,0x4e,0x91,0x21,0xbc, + 0x94,0x78,0xb5,0x7f,0xd4,0xc6,0x57,0xf,0x9e,0xe3,0xc1,0xca,0x16,0xba,0x21,0xee, + 0x9c,0xa8,0xa8,0x6e,0x66,0x1,0x57,0x52,0x59,0xec,0x54,0x9e,0xb6,0xc8,0x10,0x18, + 0x4e,0xb6,0x9b,0xa4,0x74,0x25,0x89,0xdb,0x96,0xa1,0xcf,0x33,0xa7,0x54,0x85,0xe, + 0x88,0x95,0x74,0x1c,0x91,0x28,0x37,0x31,0xd2,0x8f,0x7f,0xf6,0xce,0x5,0xdc,0xb8, + 0x38,0x8b,0x6a,0xa5,0xf2,0x42,0xed,0x39,0x0,0xdc,0x5b,0xda,0xc0,0xdf,0x7e,0xfa, + 0x0,0x1b,0x7b,0x47,0x41,0x40,0x93,0x52,0xd,0x95,0x80,0x5e,0xbb,0xab,0x31,0xa4, + 0x81,0x32,0x43,0x22,0x7a,0xf9,0xc4,0x27,0x77,0xfd,0x3,0xcd,0x3a,0xae,0x9e,0x9d, + 0xc2,0xe2,0xf4,0x48,0xe9,0x7b,0x22,0xb,0x2b,0x33,0xe3,0xe9,0xea,0x36,0x3e,0xfa, + 0xe6,0x29,0xb6,0xf6,0x5b,0x71,0xf0,0x18,0x1e,0x6c,0xe2,0xdc,0xcc,0x18,0xae,0x9f, + 0x9f,0xc6,0xdb,0x97,0xe6,0xf1,0xf6,0xc5,0x39,0x4c,0x8d,0xf6,0x47,0xb7,0xb9,0x5c, + 0xfe,0x99,0xaf,0x55,0x5e,0x76,0xf,0x25,0x4d,0x79,0x1b,0x5f,0x3f,0x58,0xc5,0xcf, + 0x6e,0x3e,0xe4,0xbf,0xf9,0xe4,0x3e,0x3f,0xdb,0xd8,0xd,0x4e,0x9,0xc9,0xbe,0xd5, + 0x1f,0x94,0xe9,0x88,0xa,0xd2,0x31,0xe3,0x89,0x6b,0xe4,0xf6,0x5a,0x9e,0x7e,0xee, + 0x31,0x79,0xeb,0xd,0xd8,0xad,0x27,0x5e,0xc4,0x5d,0xba,0xf3,0xc2,0x6,0x1b,0x22, + 0xb6,0x1c,0xfc,0xc,0x5c,0xc1,0xf7,0x13,0x12,0x6b,0x27,0x9f,0x0,0xd,0x44,0xab, + 0xe0,0xe2,0xfc,0x9b,0x11,0x98,0xa8,0xa0,0x25,0xa5,0xa4,0x52,0xe5,0xe4,0xa8,0xa, + 0x41,0xb2,0x4b,0x1c,0xe5,0xc4,0x86,0xe7,0x3c,0x63,0xd7,0x7f,0x2e,0x69,0x58,0xa8, + 0x7c,0x42,0xef,0x5,0x1,0x6a,0xa2,0x14,0x2b,0x59,0x84,0xdc,0xe2,0x53,0x30,0xc4, + 0x80,0xb6,0x25,0xd4,0x2e,0x23,0xac,0x4c,0x31,0x42,0xce,0x88,0xd2,0x54,0x1a,0x35, + 0xa7,0xf9,0x49,0x96,0xe3,0x9a,0x3a,0xb4,0x4,0x20,0x22,0x36,0x21,0xc2,0xd6,0x24, + 0xb,0x18,0x24,0xf3,0x17,0x12,0x5a,0x72,0x43,0xc6,0x84,0x49,0xdc,0x24,0xb8,0xdd, + 0xc8,0x20,0x10,0xe,0xb9,0x5e,0x1,0x6c,0x14,0x5,0xdc,0x97,0x2a,0x41,0x13,0x16, + 0xbe,0xee,0xb9,0xdd,0xbe,0xa9,0xc8,0x23,0xa3,0x60,0x72,0x5c,0x30,0xb,0x13,0xfb, + 0x30,0x46,0x9,0x9c,0x16,0xa5,0xc9,0x1,0xa6,0x9,0xd7,0x34,0xc1,0x8,0x5b,0x5e, + 0xa2,0xa4,0x57,0x88,0x56,0x57,0x36,0x12,0x47,0x20,0x3d,0xb1,0x22,0x74,0x64,0xc4, + 0xbb,0xcd,0x42,0x4f,0x97,0xb4,0x8e,0xa,0x68,0x24,0x31,0xa2,0x17,0xb4,0xbe,0xa4, + 0x61,0xe2,0x38,0x15,0x6,0xb0,0x86,0xa8,0x68,0xa8,0x43,0xd2,0x4,0x57,0x82,0x14, + 0x99,0xe2,0x42,0x75,0x16,0xd2,0x94,0x3e,0xc5,0x67,0x44,0x67,0xd8,0x80,0xfe,0x27, + 0xf2,0x7c,0x74,0x61,0xdf,0x3e,0x38,0xe6,0xcf,0xef,0x2e,0xbb,0xe2,0x72,0x7f,0x5, + 0x3f,0x7c,0xe3,0xc,0x5d,0x3b,0x33,0x15,0x77,0x8d,0x65,0x44,0xae,0x17,0xfd,0x29, + 0x93,0x2,0xe5,0xd3,0x69,0xbe,0x2f,0x24,0x22,0xc,0xd,0x34,0x30,0xd8,0x5f,0xc7, + 0xe8,0x40,0x13,0xc7,0x9d,0xee,0xff,0xc5,0xda,0x7b,0x36,0x47,0x76,0x66,0x69,0x62, + 0xcf,0x79,0xd3,0x67,0x22,0x91,0x99,0xf0,0xb6,0x0,0x94,0x77,0xac,0xa2,0xeb,0x66, + 0xb3,0xd9,0xd3,0x9c,0x76,0x33,0x3d,0x3b,0x76,0xb5,0xbb,0x1f,0x24,0x6d,0x48,0x21, + 0xe9,0x83,0x7e,0x96,0x36,0x42,0xa,0x4d,0x48,0x11,0x8a,0xd5,0x8e,0xeb,0x9d,0x9d, + 0x76,0x64,0x37,0x9b,0x6c,0x7a,0x56,0x15,0xcb,0x1b,0x14,0xbc,0x37,0x9,0x20,0x13, + 0xe9,0xee,0xd1,0x87,0xfb,0x9a,0xf3,0xde,0x7b,0xb3,0x58,0xb3,0x1a,0x44,0x47,0x13, + 0x85,0x42,0xc1,0xdc,0xbc,0xf7,0x3d,0xe7,0x3c,0xe7,0x31,0x68,0xb7,0xbb,0x38,0xed, + 0x74,0xd1,0x6c,0x75,0xd0,0x38,0x6d,0xe3,0xb4,0xd5,0x45,0xa3,0xdd,0xc1,0x51,0xb3, + 0x8d,0x83,0xa3,0x53,0xec,0xd6,0x1b,0xd8,0xde,0x3f,0xa1,0xad,0x83,0x13,0xac,0x6e, + 0x1f,0xf0,0xe6,0x7e,0x3,0x9d,0x5e,0x2f,0xd4,0xf2,0xb3,0x91,0xd7,0xba,0xd8,0x46, + 0x63,0x91,0x15,0xe,0x2b,0xe1,0xab,0xa5,0x53,0x73,0x65,0xbe,0xb2,0xa5,0xb6,0x28, + 0x21,0x35,0x67,0x72,0xd,0xa0,0x24,0xe0,0x4a,0xc3,0x7,0xe,0xfd,0x1f,0x70,0x71, + 0x66,0x14,0x97,0xcf,0x8c,0x22,0xdd,0x27,0xb9,0x4b,0xa2,0x1e,0x47,0xcd,0x36,0x3e, + 0xba,0xbb,0xcc,0x8f,0x57,0xf7,0xb4,0xb3,0x1f,0x7b,0x36,0x54,0x3e,0xaa,0x23,0xa4, + 0x92,0x2c,0x9a,0x3a,0x12,0x3e,0xdf,0x64,0xa9,0xfe,0xce,0x90,0xc6,0x43,0x93,0x48, + 0xd8,0xc5,0xd8,0xf7,0x49,0x48,0x21,0x49,0x90,0x3,0xc0,0x52,0x2c,0x19,0x3f,0xc, + 0xed,0xd,0x3a,0x3f,0x51,0xc5,0x8f,0x5e,0x3f,0x47,0x57,0xe6,0xc6,0x3c,0x7f,0x83, + 0xa8,0x7d,0x69,0xaf,0xd7,0xc3,0xe1,0x49,0x1b,0x8f,0x56,0xf6,0xf0,0x68,0x6d,0x2f, + 0x54,0x46,0x90,0x3f,0x29,0xc5,0x82,0x7e,0x62,0xac,0x52,0xd1,0x4e,0x5b,0x8f,0x2, + 0x72,0x52,0x68,0xa9,0x3c,0xd2,0x5f,0x6d,0xa4,0x5a,0xc4,0xdc,0x78,0xcd,0x5a,0xf0, + 0xf6,0x93,0xaa,0x99,0xb7,0xa5,0xad,0x43,0x7c,0xfa,0x70,0xd,0xb5,0x72,0x1,0xe7, + 0xa7,0x46,0x70,0x6e,0xba,0x86,0xe9,0x91,0x41,0x8c,0xd5,0x4a,0x18,0xad,0x14,0x31, + 0x52,0x29,0x61,0xa4,0x52,0x4c,0xbc,0x97,0x93,0x62,0x4d,0xa3,0x1c,0x94,0xa4,0x86, + 0xf8,0xf1,0x6a,0xc8,0x41,0xb9,0xfd,0x6c,0x93,0x9f,0xae,0xef,0x63,0x79,0xf3,0x90, + 0xd7,0xf6,0x8e,0xcd,0xd1,0x64,0x86,0x42,0x9b,0x2a,0x64,0x3c,0xfb,0xd9,0xe8,0xcb, + 0xc3,0xd1,0xda,0x98,0xad,0x73,0x28,0x65,0x60,0x46,0x48,0xb4,0xd0,0xc6,0x32,0x8, + 0xf4,0xed,0x12,0xe8,0x7d,0x7b,0x10,0x98,0xfd,0x39,0xd9,0x22,0x1f,0xc0,0x8,0x24, + 0x59,0xa7,0xfd,0x28,0xd6,0x1c,0xe,0xeb,0xfb,0xee,0xac,0x62,0x85,0x1b,0xb3,0x78, + 0x11,0x12,0xc2,0x59,0x10,0x59,0x5b,0xc8,0xce,0x58,0xd4,0x2,0x25,0x88,0x8d,0x14, + 0x31,0x64,0x81,0x33,0x32,0xf2,0x65,0xe4,0x42,0x6e,0x49,0x8,0xb,0xba,0x24,0x5c, + 0xf9,0x76,0x75,0xdc,0xc7,0x79,0xdc,0xdf,0xf7,0x44,0x33,0x65,0xa4,0x19,0x46,0x74, + 0x32,0x31,0x5,0xc6,0x9f,0xa3,0xcc,0x29,0xa2,0x2f,0x1b,0x79,0x11,0x5,0xd6,0x2, + 0x46,0x2a,0x71,0x64,0xad,0xb6,0x4,0x39,0x16,0xee,0x55,0x4a,0xd8,0x85,0xba,0x4c, + 0x6d,0x45,0xd6,0x28,0x46,0x29,0x5d,0xf8,0x95,0x81,0xe6,0x49,0xc1,0xee,0xd3,0xc9, + 0x16,0x76,0xa5,0xc8,0x2e,0xbb,0x5,0xf,0x2c,0x9c,0x9c,0x23,0xb1,0x22,0x4c,0x11, + 0xea,0x88,0xad,0x21,0x4a,0x29,0xa4,0x53,0x84,0x6c,0x2a,0x8d,0x4c,0x26,0xec,0x1d, + 0x7a,0x41,0x68,0xa2,0xde,0xed,0xf5,0xd0,0xed,0x5,0xdc,0xed,0x6,0xda,0x85,0x2c, + 0x49,0x65,0x18,0x99,0x54,0xbd,0x94,0xb5,0xa8,0x96,0x31,0x3c,0xf8,0x52,0x8a,0x90, + 0xcb,0xa4,0x91,0x4a,0x85,0xe1,0x1c,0xa7,0x9d,0x2e,0xf5,0x7a,0x6c,0x53,0xd4,0xad, + 0x74,0xcd,0x7a,0x5a,0x47,0x49,0x6b,0x4e,0xd0,0xed,0xe5,0xca,0x43,0xa0,0xde,0x24, + 0x29,0xd1,0xfa,0x6b,0xe9,0x9f,0x2d,0x9b,0x4e,0x61,0xb0,0x94,0xa3,0x5c,0x36,0x85, + 0x94,0x52,0x50,0x4,0x74,0x3,0x50,0xb7,0xd3,0xc5,0xc9,0x69,0x87,0x1b,0xa7,0x6d, + 0xf4,0x7c,0xeb,0x40,0xd1,0x1a,0x58,0x97,0xfa,0x98,0x93,0xa4,0xf4,0xb1,0x90,0x84, + 0xcd,0xb0,0xe3,0xd5,0xd1,0x9a,0xca,0xc1,0x18,0x24,0x41,0x2b,0xb2,0xe1,0x87,0xc, + 0x80,0xe,0x8e,0x5b,0xfc,0xe9,0x83,0x75,0x3c,0x5e,0xd9,0x43,0xbd,0xd1,0xc2,0x49, + 0xb3,0x85,0x4b,0xb3,0x23,0x34,0x3c,0x58,0x42,0x3a,0x5,0xe4,0x73,0xd9,0xd8,0xe4, + 0x11,0x25,0xc9,0x25,0xc9,0x6c,0x5e,0xc6,0x18,0x43,0xc2,0x9d,0x0,0x50,0x2a,0x64, + 0x51,0x4c,0x70,0x54,0x93,0x7f,0x6e,0xb5,0x3b,0x58,0xdb,0x39,0xc2,0xea,0x4e,0x1d, + 0xcf,0x37,0xf,0xf0,0x6c,0xfd,0x80,0x9e,0x6d,0xec,0xf3,0xd2,0xe6,0x21,0xe,0x4f, + 0x9a,0x68,0x9e,0x76,0xa9,0xab,0xd9,0x76,0xb1,0xa1,0x80,0xed,0x76,0x84,0xa5,0x3d, + 0xb2,0x35,0x89,0x23,0x49,0x52,0x44,0xfc,0x99,0x83,0xf0,0xa,0x94,0x3b,0x40,0x6, + 0x6,0x7,0xa,0x74,0x66,0x7c,0x90,0xa6,0x46,0x6,0x63,0xbf,0x57,0xd2,0xef,0xbe, + 0x7d,0x70,0x82,0xcf,0x1f,0x6d,0x60,0x65,0xe7,0x28,0x5c,0x3d,0x49,0x12,0xad,0x99, + 0x40,0xed,0x59,0xa4,0x5c,0xa4,0x1,0x8b,0x3c,0x59,0x72,0x1e,0xcb,0x80,0xa6,0x3d, + 0x85,0xf2,0xd3,0x24,0x75,0x8d,0xb5,0xe5,0x89,0x98,0x33,0x44,0x8b,0x8c,0x6b,0xda, + 0x4d,0x14,0xba,0xdb,0x3e,0xd8,0xd5,0x9f,0x2,0xd1,0xc2,0x64,0x15,0x6f,0x5e,0x9e, + 0xa1,0xeb,0xb,0xe3,0x28,0x15,0xb2,0xb1,0x15,0x83,0x9c,0x7c,0x8f,0x1a,0x6d,0x7c, + 0xfe,0x68,0x15,0x5f,0x3f,0xdf,0x42,0xe3,0xb4,0xcb,0x4e,0xe5,0xc2,0x9,0xcf,0xb8, + 0x4f,0xd7,0xb3,0xa1,0x60,0x26,0xca,0x20,0xca,0x46,0x11,0xc7,0xd,0x8b,0xce,0xa4, + 0x3a,0x90,0xc7,0xec,0x58,0xd,0x43,0x7a,0x9d,0x94,0xd4,0x70,0x26,0x45,0x8f,0x56, + 0x4b,0x5,0x9c,0x39,0x5b,0xc1,0xf5,0xf9,0x31,0xbc,0xb2,0x30,0x8e,0xb1,0x5a,0xe9, + 0x85,0xe6,0x4b,0x49,0xd3,0x78,0x34,0x50,0x45,0x7e,0x5e,0xb7,0xdb,0x43,0xb3,0xdd, + 0xc5,0x69,0xbb,0x8b,0xe5,0xed,0x43,0x7c,0xf1,0x68,0x1d,0xbf,0xbd,0xb3,0xc4,0x9f, + 0x3d,0x58,0x47,0xb7,0xd7,0x63,0x21,0x80,0x35,0x28,0x85,0x33,0x85,0x31,0xfe,0x3, + 0xae,0xbd,0xd3,0x7f,0x67,0x9,0x70,0x1,0x9,0xeb,0x56,0x80,0x2,0xd,0xb9,0x33, + 0xb3,0x9e,0xc8,0xc3,0x56,0x36,0x84,0xdf,0x35,0xec,0xe,0x3b,0x99,0xc3,0xee,0xd0, + 0x75,0xc1,0x66,0x3,0xc7,0x93,0xe,0x82,0x82,0x5e,0x7e,0x59,0x2f,0x43,0x41,0xb1, + 0x17,0x3f,0x2f,0x8c,0x62,0x24,0x16,0x52,0x16,0x5b,0x52,0xbb,0x21,0x86,0x35,0x9b, + 0x9a,0x3d,0x6d,0x7f,0x14,0x27,0x55,0xe2,0xfc,0x13,0xa,0x27,0x62,0xd,0xb9,0x7b, + 0x23,0xb9,0x92,0x16,0x9c,0x9,0x6e,0x66,0xdc,0xc7,0xe4,0x32,0x9e,0xca,0xe6,0xa1, + 0xd1,0x91,0x5c,0x4d,0x27,0x3c,0x52,0x7e,0x96,0x3a,0xc5,0x95,0x3a,0xfe,0x1,0x62, + 0xe8,0xe6,0xba,0x68,0x3b,0x7c,0x8d,0xac,0xe4,0x2c,0x45,0x64,0x83,0x56,0x42,0x28, + 0xd6,0xc2,0xe9,0x48,0x85,0x9,0xda,0x46,0xae,0xa6,0xff,0x52,0x39,0x6,0x7c,0x88, + 0xd6,0xc3,0x39,0x86,0xeb,0x7d,0xb9,0xb2,0xf3,0x8a,0x8,0x7d,0x77,0x41,0x2d,0x20, + 0xb7,0x76,0xf4,0x72,0xd6,0xc3,0xff,0xc,0x16,0xf3,0x98,0x19,0x1b,0xa4,0x99,0xb1, + 0x2a,0x26,0x87,0xcb,0x54,0xc8,0xa6,0x50,0x6f,0xb4,0x71,0xd4,0x38,0x45,0xfd,0xa4, + 0xcd,0x1b,0xfb,0xc7,0xb4,0xb9,0x77,0x8c,0xfd,0xfa,0x9,0xcb,0x1d,0x7,0x27,0x98, + 0xc4,0x78,0x70,0x34,0x21,0x51,0xa7,0x9a,0x4e,0x2b,0x8c,0xd,0xd,0xe0,0xc2,0xf4, + 0x30,0x55,0x4a,0x39,0x9c,0x76,0x7a,0x78,0xb0,0xb4,0xcd,0xcf,0x37,0xf,0x42,0x80, + 0x9e,0x23,0xf2,0x1b,0xd1,0xea,0xfb,0x3b,0x3c,0xe9,0x4b,0x0,0x7f,0x3d,0xa0,0xb3, + 0x6a,0x28,0xb2,0x23,0x37,0x1f,0x3a,0x3b,0x3d,0x4c,0x7f,0xf1,0xdd,0x4b,0x74,0x71, + 0x76,0x84,0x42,0xc2,0x8c,0xa,0xe3,0x31,0x37,0xf6,0xf9,0xc3,0x3b,0xcb,0xfc,0xe9, + 0x83,0x15,0xde,0x3a,0x38,0x31,0x6c,0x7b,0x7,0xdb,0x73,0xc0,0x70,0x62,0x9e,0x58, + 0x6e,0xa2,0xe8,0x2d,0xe2,0xaa,0x5d,0x4d,0x8f,0x74,0xcf,0x58,0xec,0x1a,0x92,0xb5, + 0xef,0x13,0x54,0x95,0x7a,0xb3,0xcd,0xff,0xf0,0xd1,0x43,0x7c,0xfa,0x60,0x15,0xe7, + 0xa7,0x47,0xf0,0xf6,0xb5,0x19,0xbc,0x75,0x65,0x86,0x16,0x26,0x87,0x12,0x27,0xec, + 0x97,0x99,0xd8,0xbf,0xe9,0xed,0x65,0xe0,0xfb,0xe8,0xa1,0x99,0xcd,0xa4,0x31,0x35, + 0x52,0xc6,0x68,0xb5,0x84,0x6b,0xb,0x13,0xe8,0xf5,0x7a,0x38,0x38,0x39,0xa5,0xa5, + 0xad,0x43,0xbc,0xff,0xe5,0x22,0xff,0xf6,0xce,0x73,0xac,0xed,0x1c,0x41,0x8a,0xb6, + 0x8c,0x8f,0xb5,0x2e,0xcb,0x2e,0x23,0xc7,0x38,0x5,0x2a,0x45,0x9e,0xf1,0x8c,0x34, + 0xb0,0x61,0x63,0x51,0x4d,0x22,0x26,0x97,0xd,0x75,0xe,0x0,0xa1,0x98,0x4f,0xd3, + 0xc2,0x78,0x15,0x23,0xda,0xb4,0xa4,0x5f,0xb6,0xb6,0x69,0x62,0x9a,0xad,0x2e,0x96, + 0xb7,0xe,0xf1,0x7c,0xeb,0x10,0xad,0x4e,0x8f,0xad,0xb6,0xdd,0xba,0x6d,0x91,0x17, + 0x5e,0xe2,0x7e,0x7f,0xcb,0x5b,0x87,0x9,0xbd,0x62,0x25,0xec,0x92,0x94,0x58,0xc2, + 0x20,0x66,0x7a,0x6b,0x75,0x2,0xb6,0x15,0x75,0x59,0xef,0x91,0xaa,0x6e,0x10,0x42, + 0xe5,0x47,0xab,0x9,0xcf,0xc7,0x74,0x26,0x85,0x9f,0x7e,0xfb,0x22,0xfd,0xe9,0x77, + 0x2e,0x22,0x97,0x49,0xbd,0xb0,0xc0,0x11,0x11,0x76,0xea,0xd,0xfc,0xc7,0xdf,0xdc, + 0xc7,0xe7,0xf,0xd7,0x9d,0xff,0x95,0x8,0x67,0x21,0x4a,0x70,0x8a,0x11,0xd6,0x10, + 0x6,0xc9,0xb4,0x76,0x4d,0x7d,0x57,0x42,0xee,0x7e,0xba,0x38,0x33,0x82,0xab,0x73, + 0x23,0x48,0xa7,0xd4,0x4b,0x91,0xd2,0x82,0x20,0xc0,0xb7,0x2f,0xcf,0xe0,0xf2,0x99, + 0x11,0xe4,0x33,0x19,0xe4,0xb2,0x29,0xe4,0x33,0xa9,0x97,0xbe,0x87,0xbf,0xe9,0xf3, + 0xac,0x4,0xed,0xf8,0x14,0x9f,0x3d,0x5c,0xc7,0xef,0xee,0x2e,0xe1,0xeb,0x67,0x5b, + 0xbc,0x5b,0x6f,0xe2,0xf0,0xa4,0x85,0x9e,0x6d,0x44,0xc9,0xc9,0xd1,0x60,0xe1,0x73, + 0x5d,0x2e,0xd9,0x92,0xd1,0x38,0x70,0x5,0x9d,0x81,0x20,0x2c,0xf7,0x8a,0x43,0x59, + 0x39,0x82,0xd0,0x30,0x49,0x8b,0xc8,0x3,0xad,0x43,0xf,0x35,0xbb,0xc,0x26,0xd, + 0xa9,0x7,0x81,0x3e,0x4b,0x2,0xcd,0xe1,0x60,0x4,0x41,0x10,0x28,0xdd,0x14,0x4, + 0x8,0x1b,0x8,0x22,0xfd,0xfd,0x8c,0xc1,0x8c,0xb,0x58,0xf1,0xd3,0x45,0xc9,0x21, + 0xa2,0xe4,0xd8,0x64,0x3e,0x3,0x9c,0x63,0x2e,0x22,0x49,0xef,0x71,0xc4,0x1a,0xd6, + 0xe3,0x91,0x1,0x9e,0xaa,0xd4,0xc8,0xcf,0xd3,0xce,0x24,0x42,0x8,0x97,0x48,0x32, + 0xdf,0x29,0x32,0xab,0xc7,0x95,0xcf,0xe,0x50,0xa6,0x3e,0x4a,0x68,0xdf,0xe8,0x83, + 0x21,0x33,0xd1,0x7d,0x39,0x1c,0xa2,0x12,0x65,0x8f,0x84,0xe3,0x5a,0x4,0x16,0x3b, + 0x6b,0xcf,0xc,0x46,0x3b,0xc2,0xb1,0x66,0xa5,0x87,0xd5,0x5f,0x91,0x5e,0x8b,0x59, + 0xc2,0x1b,0x87,0xef,0xa9,0xd0,0xf1,0x8a,0x43,0xc9,0x1a,0x64,0xa1,0xb7,0xd3,0x38, + 0x19,0xf6,0xba,0x47,0x29,0x94,0x1e,0x90,0x20,0x11,0x8f,0x4a,0xc8,0x66,0x52,0x54, + 0x2b,0x17,0x30,0x52,0x29,0xd2,0xe8,0x60,0x9,0xc3,0xd5,0x2,0x8d,0x56,0x6,0x30, + 0x5a,0x2d,0xd1,0x68,0xb5,0x88,0xa1,0x72,0x1,0xb9,0x6c,0x1a,0x27,0xa7,0x5d,0x34, + 0x5a,0x2d,0x9c,0x34,0x3b,0x74,0xd4,0x6c,0x63,0x65,0xfb,0x80,0x3f,0xbe,0xb7,0x4a, + 0x8b,0x1b,0x7,0x7c,0xdc,0x6c,0xfb,0x3b,0x75,0xa1,0x3,0x4c,0x6c,0xa8,0x74,0x79, + 0xca,0xa4,0x15,0xa6,0x47,0xcb,0xb8,0x36,0x37,0x46,0x97,0xce,0x8c,0x62,0x7a,0xb4, + 0x42,0xc5,0x5c,0x1a,0xad,0x6e,0xf,0xd7,0x16,0xc6,0xf9,0xce,0xd3,0x4d,0xfe,0xf4, + 0xfe,0xa,0xef,0x1f,0xb7,0x34,0x89,0xd3,0x48,0xd3,0xdc,0x29,0x21,0xa7,0x92,0x98, + 0x45,0x2b,0x9,0x58,0x8f,0x25,0xb7,0xdd,0xd0,0x1d,0x8,0xe5,0x62,0x96,0x5e,0x39, + 0x37,0x49,0xef,0x5c,0x9f,0xa5,0x77,0x6f,0x2e,0x60,0x6a,0xb8,0x4c,0xf9,0x9c,0xb3, + 0x79,0x9c,0x1e,0xad,0xd0,0x48,0xb5,0xc4,0xd3,0x63,0x83,0xfc,0xeb,0x2f,0x16,0xf9, + 0xd9,0xc6,0x3e,0xba,0xdd,0xc0,0x76,0x8b,0x64,0xf3,0xab,0x3c,0xdf,0x6a,0x32,0xee, + 0x79,0x91,0xb4,0xd0,0xa8,0x7c,0x9d,0xc9,0x57,0xb,0x47,0xe8,0x0,0x64,0xaa,0x2, + 0xbb,0x43,0x9a,0x10,0x30,0x53,0xe3,0xb4,0xc3,0x8b,0x1b,0x75,0xda,0xad,0x37,0xf9, + 0xf0,0xa4,0x45,0xab,0x3b,0x47,0x7c,0x7e,0x6a,0x88,0x66,0xc7,0x2a,0x18,0x1f,0x2a, + 0x63,0xb4,0x52,0x40,0x36,0x93,0x8e,0x4d,0x1c,0xff,0x5c,0xfb,0xca,0x17,0x7d,0x5e, + 0x3f,0xe7,0x2e,0x59,0x2c,0xb2,0x99,0x34,0x72,0x59,0xf7,0xbd,0x87,0x2b,0x45,0x4c, + 0xe,0x95,0x31,0x90,0xcf,0xd2,0x50,0xa5,0x88,0xdf,0xdd,0x59,0xc2,0xe3,0xd5,0x3d, + 0x9c,0xb4,0x3a,0x6c,0x3,0x6e,0x58,0xda,0x26,0x42,0xd2,0xda,0x23,0xee,0x53,0xca, + 0xb,0x2a,0xf3,0x9d,0x94,0xcd,0x9e,0x4b,0xd9,0xed,0x3b,0x33,0x63,0x7c,0x68,0x0, + 0xd7,0x16,0xc6,0x50,0x1d,0xc8,0x27,0xc2,0xeb,0x72,0xc7,0xda,0xeb,0x5,0x78,0xb8, + 0xba,0x8b,0xaf,0x9f,0x6d,0xf1,0xd1,0x49,0xcb,0x93,0x28,0x5a,0x48,0x91,0x39,0xe2, + 0xc7,0xa4,0x6f,0xc6,0x40,0x23,0xed,0x81,0x48,0xf1,0x33,0xd5,0xdb,0x24,0xee,0x45, + 0x5c,0xef,0x60,0x27,0x78,0x96,0x92,0x34,0x72,0x89,0xc8,0x26,0x3e,0x50,0x69,0xcb, + 0x77,0x45,0xd2,0x96,0x47,0x4,0xa,0x91,0xc9,0xa0,0x1f,0x1d,0x2c,0xd2,0xb7,0x2e, + 0x4f,0xe1,0xed,0x6b,0xb3,0x98,0x9b,0xa8,0xc6,0xa6,0xdf,0xa8,0xc6,0x7a,0x6b,0xff, + 0x18,0x9f,0x3f,0xda,0xc0,0xd7,0x21,0x53,0xdb,0x23,0x35,0xb1,0xcd,0xcc,0xf0,0x30, + 0x4e,0x5b,0x14,0x2c,0x4a,0x0,0x5b,0xdc,0xec,0xc,0x4f,0x1c,0x41,0xac,0x22,0x51, + 0xbd,0xe7,0xa6,0x86,0x70,0x75,0x7e,0xc,0x99,0xb4,0x7a,0xa9,0xa6,0x91,0x99,0x51, + 0x2e,0x66,0x31,0x58,0xca,0xc5,0xf8,0x1e,0x12,0x7d,0xe8,0xb7,0x1f,0x97,0x64,0xb7, + 0xe8,0xb3,0xb1,0x77,0xd4,0xc4,0xfa,0x4e,0x1d,0xab,0xbb,0x47,0x78,0xba,0xb6,0x8f, + 0xbb,0x4b,0xdb,0x7c,0xfb,0xd9,0x16,0xb6,0xf6,0x4f,0xc,0x64,0xc6,0xb0,0xc6,0x9c, + 0x6,0x94,0xb0,0x8c,0x73,0x63,0x78,0xc5,0x42,0x1c,0xc3,0x30,0x9a,0x71,0xb3,0xfb, + 0x36,0x10,0x79,0x10,0x4e,0xe0,0x5a,0xf7,0xc8,0xcc,0x8a,0x89,0x42,0x83,0x77,0x4, + 0xa1,0x7c,0x8d,0x42,0x34,0x3e,0xd0,0x9e,0xd,0x81,0x6,0xef,0xc3,0x71,0x3b,0x94, + 0x89,0x84,0xf,0x81,0xa,0xe5,0x93,0x1c,0xf9,0xde,0x64,0xc8,0x4a,0xcc,0xac,0x24, + 0xa7,0xc9,0x1a,0x96,0xb2,0x6f,0xb8,0xc1,0x6e,0x6,0x14,0xb2,0x9,0xc8,0x15,0x26, + 0xa2,0x84,0xcd,0x28,0x2a,0x8e,0xfe,0x81,0x7a,0x36,0xf,0xdd,0x9,0x95,0x4c,0xff, + 0xaa,0x5c,0x51,0x87,0xb8,0xa9,0x88,0x12,0xba,0x8a,0x88,0xf3,0x95,0xb5,0x4f,0x56, + 0x62,0xf2,0x93,0x1b,0x51,0xc4,0x24,0x71,0x91,0x0,0x9,0x55,0x26,0xdf,0x91,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xc9,0xed,0xf1,0xb4,0x4e,0x8e,0x52,0x46,0xe4, + 0xf9,0xc7,0x3a,0x41,0xb9,0x2d,0xe6,0x60,0x22,0x95,0x52,0x4a,0xf4,0xe1,0xca,0x1a, + 0xc4,0x84,0x5,0xd8,0x4c,0xe9,0xa,0x50,0x44,0x4a,0xc7,0x2e,0x85,0x4b,0x62,0x32, + 0xd,0x83,0x47,0x86,0xb3,0x4f,0x99,0xcd,0x53,0xd7,0xe7,0xf,0x59,0x77,0x5b,0x6, + 0x21,0x97,0x4e,0x61,0x7e,0xa2,0x4a,0x57,0xe7,0xc7,0xe8,0xd5,0xf3,0x13,0x74,0xe3, + 0xdc,0x4,0xe6,0x27,0x6a,0x94,0x4d,0xab,0xc4,0x2c,0x5f,0xe9,0xa6,0xb5,0x5f,0x6f, + 0x52,0x31,0x9f,0xe5,0x5f,0x7c,0xf6,0x14,0xf7,0x97,0xb6,0x99,0x59,0x18,0xd7,0x32, + 0x33,0xf7,0xb1,0x9d,0x90,0x8d,0xd5,0xe4,0x70,0x99,0x7e,0xf2,0xe6,0x79,0xfc,0xd1, + 0xb7,0x2e,0xd0,0xb5,0xf9,0x31,0x6f,0xdb,0xd9,0xed,0x76,0xe9,0xde,0xd2,0xe,0x1f, + 0x35,0xdb,0xfc,0xfb,0x7b,0x2b,0xec,0x8c,0xb,0x14,0x3b,0x7c,0xdb,0xe9,0xe4,0xd8, + 0x92,0xed,0x4,0x2,0xef,0xf4,0xcd,0x12,0x75,0x21,0x7,0x1b,0x67,0x70,0x75,0x61, + 0x9c,0xfe,0xe7,0x9f,0xbe,0x4e,0xaf,0x5d,0x9c,0xa0,0x9c,0x28,0x80,0xe6,0x6d,0x7c, + 0x68,0x0,0x13,0xc3,0x65,0xba,0x71,0x6e,0x92,0x3a,0xbd,0x20,0x68,0xf7,0x7a,0x58, + 0xde,0xaa,0x87,0x7e,0x9e,0x1a,0x25,0x50,0xe6,0x11,0x26,0x84,0x3a,0x6a,0x82,0x19, + 0xb9,0x5d,0x7,0xc1,0x2,0x2b,0x16,0xe2,0x3d,0x8e,0x66,0x92,0x93,0x4f,0x4b,0x85, + 0xb3,0x36,0x26,0x17,0x96,0x65,0xa5,0xca,0x7c,0xd4,0xec,0xd0,0x27,0xf,0x56,0xf9, + 0xb3,0x87,0xab,0x18,0xa9,0x94,0x70,0x75,0x7e,0xc,0xdf,0xbf,0x31,0x47,0xaf,0x5d, + 0x98,0xc0,0xd9,0xc9,0x1a,0x32,0xe9,0x74,0x5f,0x9,0xd0,0xff,0xdf,0xa9,0xfd,0x45, + 0x85,0xbf,0x9f,0xa4,0xce,0xd8,0xd3,0x7e,0xfb,0xca,0xc,0xae,0xcc,0x8d,0xa2,0x52, + 0xca,0xd1,0x3f,0x7d,0xfa,0x84,0x6f,0x3d,0xdb,0xa6,0x6e,0xb7,0xcb,0xca,0x9e,0x32, + 0x9e,0xca,0x15,0x5e,0x1a,0xb2,0xc7,0x92,0x86,0xbc,0xaa,0x62,0xcc,0xd5,0x9e,0x2c, + 0x52,0x56,0x46,0x44,0x93,0xc3,0x83,0xb8,0x71,0x76,0x82,0xca,0x85,0x5c,0xdf,0x55, + 0x84,0xf9,0x6f,0x37,0x60,0x7c,0xf9,0x78,0x3,0x5f,0x3c,0xd9,0x44,0xe0,0xd,0xc8, + 0xfe,0x74,0x6c,0x8e,0x70,0x1b,0x99,0x4c,0xc6,0xf,0x87,0x43,0x7f,0x21,0x67,0xd4, + 0x4d,0x14,0x4,0xae,0xe0,0x29,0x38,0x28,0x82,0xa4,0x5a,0x5c,0x64,0x36,0x93,0xe5, + 0x5a,0x90,0x49,0x7f,0x35,0xb1,0x7e,0xce,0x6f,0x1b,0xce,0xee,0x56,0xc,0x36,0x4, + 0xe0,0xcd,0xcb,0xd3,0xf8,0xf7,0x3f,0xb9,0x41,0xe7,0xa7,0x86,0x12,0xad,0x49,0xe5, + 0x33,0xde,0xe9,0xf6,0xf0,0xe1,0xd7,0xcb,0xf8,0xd5,0x17,0xcf,0xb8,0x7e,0xdc,0x42, + 0x54,0xd3,0xe4,0x13,0xf4,0xfa,0xc8,0x15,0xed,0xa5,0x31,0x5a,0x61,0x49,0x8c,0xf1, + 0xcd,0x48,0xcc,0x67,0x67,0xd2,0xa,0xb,0x93,0x35,0x5c,0x98,0x1e,0x46,0x26,0xa5, + 0x5e,0x8a,0xe4,0x99,0xf4,0x9a,0x45,0x5f,0xbf,0x97,0xbd,0x4f,0xe5,0x35,0x38,0x3c, + 0x3e,0xc5,0xad,0xa7,0x9b,0xf8,0xdd,0xd7,0xcb,0xf8,0xed,0xad,0x25,0xac,0xee,0x1e, + 0x85,0x1,0x3c,0x76,0x1e,0xb7,0xb7,0x95,0x73,0x40,0x74,0x1,0x80,0xae,0xb0,0x8b, + 0x34,0x3d,0x36,0x70,0x39,0x99,0x9,0x5e,0x4f,0xe5,0x1a,0x32,0x27,0x36,0x6c,0x76, + 0x4,0xfa,0xf4,0xd1,0x24,0x38,0xad,0x45,0xf,0xdc,0x54,0xe,0x27,0x87,0xd4,0xb0, + 0xbc,0x6e,0x2a,0x98,0x61,0x2d,0x63,0x35,0x24,0x40,0x50,0xd6,0xb7,0x8a,0x5,0x81, + 0x98,0x84,0x47,0x81,0x78,0x5a,0x1c,0xf8,0x43,0xf1,0xb5,0xb5,0xaf,0xd4,0x50,0x7e, + 0x43,0x96,0x28,0x42,0x44,0x44,0x3c,0x18,0x2f,0xea,0x69,0xff,0x66,0x52,0x5e,0xc4, + 0xa9,0x99,0xc3,0x1d,0x9f,0x29,0xce,0xc3,0xf7,0x3c,0x41,0x94,0x8c,0x72,0xa7,0xbe, + 0xa,0x38,0x24,0x96,0xf7,0x8,0xb7,0x5a,0x47,0x3b,0x46,0x68,0x38,0x82,0xb,0x6b, + 0x36,0xe0,0x9a,0x4d,0xa0,0x6c,0xd2,0x2,0xa9,0x94,0x95,0xa5,0x29,0xa3,0x9d,0x62, + 0x5,0xa5,0x7,0x6d,0xc5,0xa1,0xb2,0x4d,0x59,0x6b,0x57,0xf3,0xb5,0x8c,0x63,0x44, + 0xb8,0x50,0x17,0x32,0x35,0xb6,0x42,0x40,0x56,0x26,0x5f,0xd5,0xc6,0xdc,0x13,0x11, + 0x70,0x76,0xaa,0x46,0xd7,0xe7,0xc7,0xe9,0xca,0xfc,0x28,0x4d,0x8d,0x94,0x31,0x5e, + 0x29,0x61,0xa8,0x52,0xa2,0xe1,0xc1,0x2,0xf2,0xd9,0x74,0xec,0xb7,0x4e,0xea,0x64, + 0x8b,0xf9,0x34,0x6,0x8b,0x79,0x14,0xf3,0x59,0x28,0xa5,0x28,0x60,0xc7,0x6a,0x65, + 0x52,0xf2,0x60,0x8d,0x10,0x11,0xc3,0xd7,0x6b,0xac,0x56,0xc2,0x77,0xae,0x9f,0xa1, + 0x3f,0x79,0xeb,0x12,0x9d,0x9f,0xaa,0xc5,0x1e,0xae,0x54,0x2a,0x85,0xd9,0xd1,0xa, + 0xfd,0xc1,0x8d,0x39,0xb4,0x3a,0x5d,0xdc,0x7a,0xba,0xc9,0x41,0x90,0xa0,0x37,0x93, + 0xa,0x4,0xa2,0xc8,0xd1,0xee,0xeb,0xe1,0x24,0xec,0x32,0x3e,0x32,0x40,0x3f,0x7c, + 0x75,0x81,0x7e,0xf8,0xda,0x2,0xae,0x2d,0x8c,0x51,0x21,0x97,0xed,0xab,0x7b,0x5, + 0x80,0x6a,0x29,0x87,0x77,0x6f,0x2e,0xd0,0x49,0xb3,0x83,0xb5,0x9d,0x7b,0x1c,0x7a, + 0x5a,0x93,0x8b,0xd6,0x50,0x9e,0x6,0x2e,0x34,0x65,0x32,0xd7,0x84,0x8c,0xd1,0x3, + 0x85,0x21,0x32,0x92,0x8a,0x12,0x23,0x62,0x4a,0xed,0x7,0xf9,0x92,0x2e,0x57,0xda, + 0x1d,0xd8,0x63,0x4a,0x9,0x33,0xb6,0xe,0x4e,0xb8,0xf3,0x74,0x93,0xb6,0xf,0x8e, + 0xf9,0x37,0xb7,0x9f,0x63,0x6a,0xb8,0x8c,0xf9,0x89,0x2a,0x9d,0x9d,0x1a,0xc2,0xc2, + 0x44,0xd,0x13,0x43,0x3,0x7d,0x23,0x1d,0x5f,0x44,0x14,0xfa,0x97,0x80,0xe9,0x93, + 0x76,0xb6,0xe5,0x62,0xe,0x3f,0x79,0xe3,0x1c,0xd2,0xa9,0x14,0x6d,0xd7,0x1b,0xbc, + 0xbc,0x75,0x24,0x5d,0xb,0x9c,0xc9,0x94,0x34,0x75,0x15,0x4c,0x19,0xeb,0x34,0x24, + 0xe5,0x95,0xfe,0xbf,0x95,0xab,0x34,0x2,0x80,0xa9,0xe1,0x1,0xbc,0x72,0x76,0x1c, + 0x83,0xa5,0xe4,0x64,0x35,0x39,0xe5,0x35,0x5a,0x5d,0xdc,0x5f,0xda,0xc1,0xc3,0xd5, + 0x5d,0x4,0xbd,0x20,0xb2,0x8e,0xf3,0x55,0x5c,0x2e,0xb5,0xca,0x7c,0x73,0x66,0xe9, + 0x4b,0x4d,0x86,0x32,0xa9,0xa3,0xcd,0x28,0xca,0xb1,0x34,0x37,0x90,0x50,0x67,0x92, + 0x18,0xa,0x44,0xa4,0x3b,0xc1,0x5a,0x37,0x43,0x32,0x29,0x45,0x17,0x0,0xe4,0x73, + 0x19,0xbc,0x7b,0x73,0x9e,0xfe,0xf8,0xcd,0xb3,0x74,0x71,0x66,0x4,0x85,0x5c,0xba, + 0x2f,0xaf,0xc2,0xbc,0xfe,0x1b,0x7b,0x27,0xf8,0xfd,0x83,0x35,0x7c,0xfa,0x68,0x1d, + 0xad,0x5e,0xe0,0xa0,0xf3,0x8,0x61,0xff,0x45,0x77,0x87,0x69,0xa2,0x59,0xec,0xdd, + 0x99,0x44,0xe0,0x5a,0x24,0xee,0x9a,0x99,0x30,0x31,0x54,0xc6,0xe4,0x48,0x19,0xa5, + 0x7c,0xe6,0xa5,0x88,0x9c,0xf2,0x3c,0x4a,0x92,0x1b,0xf6,0x5b,0x9f,0xf4,0x2b,0xf4, + 0xf5,0x93,0x16,0xee,0x3e,0xdf,0xc6,0x83,0x95,0x1d,0x3c,0x5c,0xd9,0xc7,0xda,0x4e, + 0x1d,0xab,0x7b,0x47,0xd8,0xd8,0x3d,0xe2,0x5e,0xe0,0xdd,0xcb,0x9,0xf,0x8f,0xc9, + 0x1b,0xd7,0xe0,0xb8,0x38,0x63,0x34,0xb6,0x16,0x90,0x21,0xc9,0x21,0xcc,0x37,0x87, + 0x76,0x7f,0xf3,0x26,0x77,0x20,0x0,0x14,0x33,0x71,0x10,0x26,0xf2,0x19,0xe9,0x5a, + 0xc0,0x0,0x69,0x63,0x99,0xc0,0x85,0xfb,0x58,0x97,0x33,0xeb,0xe5,0xcf,0xee,0xb8, + 0x1,0x5b,0x22,0x47,0x58,0xa8,0x6d,0xb3,0x29,0x4c,0x60,0x62,0xfa,0x8b,0xa4,0x78, + 0x78,0xaf,0xa5,0x93,0x4c,0xf0,0x88,0x73,0x64,0x4c,0x2e,0x1e,0xfd,0x73,0xa4,0xcc, + 0x5b,0x63,0x19,0x52,0xee,0xb7,0x60,0x2f,0xaf,0x55,0x5c,0x48,0x95,0x2c,0x65,0x8b, + 0x5a,0xd4,0x71,0x5c,0xdb,0x4,0x9f,0x16,0x20,0xf3,0xe0,0xdd,0xd1,0x6a,0xed,0x96, + 0x1,0xcb,0x66,0x27,0xb1,0x80,0xf,0xf7,0xb5,0x66,0x73,0x94,0xd2,0x73,0x37,0x5b, + 0x2,0x1c,0xc,0x6b,0xdd,0x4e,0xd7,0x1a,0x6e,0xa7,0xb0,0xb8,0x2b,0x82,0xd2,0x11, + 0xa9,0xca,0x4a,0xce,0x74,0x51,0xa7,0xd0,0x45,0x4e,0x49,0x56,0xbc,0x10,0x78,0xbb, + 0x85,0x22,0x69,0xc7,0x39,0xfd,0xcb,0xe5,0xd3,0x69,0x2a,0x95,0x32,0x34,0x3f,0x5e, + 0xc3,0xab,0xe7,0x27,0xe8,0xf,0x5e,0x99,0xa3,0x57,0xce,0x8e,0x53,0x21,0x97,0xe9, + 0xb,0x9b,0xbe,0x68,0xf2,0x6a,0xb6,0x7b,0xa8,0x9f,0xb4,0xd0,0x38,0xed,0xf8,0x9d, + 0x8c,0x83,0x8,0x22,0x2b,0x10,0xd7,0x3e,0x15,0xf2,0x59,0x7a,0xe3,0xd2,0x34,0xbe, + 0x7f,0x63,0x9e,0xae,0xcc,0x8d,0x7a,0xf,0xab,0x3c,0x60,0xf3,0xd9,0x34,0xae,0xcc, + 0x8d,0xd1,0xe2,0xe6,0x21,0xee,0x3c,0xdb,0x6,0x2b,0xf3,0x5c,0x40,0xb0,0x67,0xcd, + 0x2e,0x9d,0x2c,0xe5,0x9d,0xc5,0x8,0x40,0xbe,0x39,0x28,0x8,0x8c,0x99,0xd1,0x2a, + 0xde,0xbc,0x32,0x45,0xff,0xea,0x3b,0x17,0xe8,0x8d,0x8b,0xd3,0xde,0xf7,0x95,0xdf, + 0x5f,0x32,0x80,0x99,0x19,0xaf,0x2c,0x8c,0xd3,0xf3,0x8d,0x3,0xfc,0xcd,0x47,0xf, + 0x8,0xed,0x1e,0xcb,0x71,0xc3,0x22,0xf,0x6,0xf0,0x51,0x64,0x2d,0x3f,0x9d,0xa9, + 0xa2,0xb5,0x4b,0x62,0x93,0x6b,0x47,0x1e,0xad,0x88,0xdc,0xee,0x3f,0x3a,0xa9,0x3a, + 0x46,0xbc,0xae,0xe8,0xec,0xec,0x8d,0x6c,0x26,0x1e,0xb0,0x7f,0xd4,0xe4,0xfd,0xa3, + 0x53,0xdc,0x5d,0xda,0x25,0x45,0x84,0x2b,0x67,0x46,0xf8,0xda,0xfc,0x18,0x5d,0x9d, + 0x1f,0xc5,0xd9,0xc9,0x2a,0xc6,0xaa,0x3,0xc8,0x67,0xd3,0x48,0xa7,0x53,0xc8,0x28, + 0x42,0x2e,0x9b,0xb2,0xba,0xdc,0x7e,0x7e,0xf1,0xb2,0xe0,0x7f,0xd3,0xde,0xf9,0x45, + 0xc5,0x3d,0x7a,0x6f,0x31,0x33,0xa6,0x46,0x6,0xf1,0xbd,0xeb,0x67,0x70,0x6f,0x79, + 0x7,0xbd,0xde,0xa,0xad,0xef,0x1d,0x99,0xeb,0x65,0xbc,0xe,0xc4,0xc8,0xa0,0xf1, + 0x5e,0xc9,0x71,0x74,0x44,0x1c,0xa2,0xd8,0x34,0xe1,0x7,0x3c,0xa7,0x55,0xa,0x93, + 0x23,0x83,0x34,0x33,0x3a,0x98,0xa8,0xd3,0x97,0x3f,0xe7,0x69,0xab,0x83,0xe5,0xad, + 0x3,0x2c,0x6f,0xd5,0xb9,0xdd,0x9,0x1c,0xec,0x66,0xa3,0x50,0xd,0xd,0x49,0x16, + 0x3b,0xa5,0x19,0x9b,0x1c,0xe5,0x85,0xb2,0xf3,0x87,0x65,0xdf,0x68,0xc7,0x5f,0xe1, + 0xc1,0xf9,0x17,0x2a,0xcf,0x14,0x4a,0xdb,0x97,0x92,0xc1,0xd8,0x58,0x59,0x93,0x44, + 0x63,0x8e,0x6b,0x37,0x3d,0xb9,0x6c,0x6,0x37,0xcf,0x8d,0xd3,0x9f,0x7e,0xe7,0x2, + 0xbd,0x7a,0x6e,0xc2,0x33,0x4f,0x91,0xaf,0xa1,0x74,0x3e,0x5b,0xde,0xae,0xe3,0xc3, + 0x7b,0x2b,0xb8,0xfd,0x74,0x8b,0x9b,0xad,0xae,0xb7,0x69,0x35,0x5,0xc0,0x77,0xff, + 0xf7,0x2f,0x33,0xb3,0x33,0xe9,0x62,0x9f,0xb1,0xef,0x78,0x8a,0x8c,0x10,0x51,0x16, + 0x1e,0x5,0x43,0x83,0x39,0x9c,0x9f,0x1e,0xc2,0x70,0xb9,0xe0,0x31,0xef,0x5f,0xe4, + 0xa9,0x1f,0x3d,0x8f,0x5e,0x24,0xc9,0x34,0x9f,0x23,0xef,0xed,0x5e,0x2f,0x40,0xab, + 0x13,0xe0,0xe4,0xb4,0x8d,0xfd,0xe3,0x26,0x16,0x37,0xf,0xf0,0xf1,0xfd,0x35,0x7c, + 0xfe,0x68,0x1d,0x8f,0xd6,0xf6,0xd,0x91,0x91,0xcd,0x95,0x77,0x6,0x58,0x62,0x6e, + 0x65,0xb6,0xa8,0xa4,0xd7,0x97,0x87,0x95,0xdd,0xea,0xc1,0x45,0xd7,0xce,0x6c,0x82, + 0x55,0x42,0x48,0x31,0x70,0x91,0xa7,0xa4,0x9d,0xe1,0x82,0x40,0xe7,0xb4,0x4,0xa1, + 0xef,0x71,0xc0,0xc4,0x14,0x32,0xdc,0x29,0xb0,0xf6,0xb0,0xac,0x29,0x95,0x26,0xd1, + 0x8f,0x15,0x6b,0x27,0x42,0x9b,0xda,0x66,0x7f,0x20,0x63,0x93,0x2f,0x87,0x61,0xc1, + 0xe4,0x75,0xcf,0xf,0x47,0xf8,0xe,0x46,0x81,0x61,0x37,0x97,0x32,0x7c,0x85,0xe2, + 0x19,0xf3,0x24,0x88,0x93,0x24,0xc1,0x50,0x86,0x34,0x6a,0x93,0x63,0x5e,0x5a,0x4e, + 0x5d,0x51,0xf6,0xa4,0xef,0x4c,0x15,0x21,0x5e,0x88,0x94,0x15,0x91,0x82,0x6a,0xdf, + 0xa7,0xa8,0x1c,0x2b,0x69,0x27,0x4b,0x2e,0x7d,0x39,0x1e,0x7a,0xaa,0xbc,0xc9,0xdc, + 0xa3,0xe1,0x92,0xe5,0xc0,0x11,0xa7,0x42,0x28,0x9c,0x4c,0x41,0xd6,0xa5,0x5e,0xdb, + 0xaf,0x2b,0xcd,0x6d,0xb1,0x90,0xbb,0x8e,0x39,0x57,0xba,0x23,0x37,0x6d,0x41,0x68, + 0x79,0x23,0x2,0x5b,0x74,0xc8,0xa,0x99,0x1,0xcb,0xac,0x97,0x75,0xe3,0x41,0xf9, + 0x4c,0xa,0x57,0xe6,0xc6,0xe8,0xcf,0xbf,0x7b,0x49,0xdd,0x38,0x37,0x4e,0xa3,0x95, + 0x12,0x4a,0xf9,0xc,0xa,0x9,0x5a,0xe6,0xe8,0x81,0xdb,0x6f,0x57,0xda,0xee,0x74, + 0x71,0x77,0x69,0x1b,0x4f,0xd6,0xf,0x10,0x90,0xf0,0xdb,0xd6,0x87,0x56,0xe8,0xde, + 0x15,0x69,0xb6,0xf4,0xcb,0x54,0x2b,0xe5,0xf1,0xd3,0x6f,0x9d,0xa3,0xb7,0xaf,0xce, + 0x24,0x3e,0x80,0x6e,0xa6,0x61,0xe4,0x32,0x29,0xe4,0xb2,0xa9,0xc8,0xd9,0xec,0x4d, + 0xdd,0x31,0xbd,0xe,0x79,0xc7,0x8e,0xff,0x42,0x9e,0x99,0xa8,0xd2,0xf,0x5f,0x5d, + 0xc0,0xbf,0xfb,0xfe,0x35,0x9a,0x1a,0x1e,0x88,0xfd,0xee,0xdc,0x87,0xb9,0xad,0x94, + 0x42,0xa9,0x90,0x42,0xb5,0x5c,0x80,0xa2,0x94,0xd3,0x8c,0x47,0x48,0x42,0x6e,0x1b, + 0xee,0xfc,0x90,0x5d,0x67,0xe8,0x24,0x77,0x4,0x6,0x2,0x3,0xdf,0xd9,0x75,0x81, + 0x90,0x33,0xfb,0xac,0x68,0x2f,0x9,0x90,0x9c,0x7c,0x82,0xc3,0x4c,0xb1,0x30,0x93, + 0xc9,0x4d,0x69,0xa1,0xc6,0x85,0x81,0x47,0xab,0x7b,0x58,0xda,0x3e,0xe2,0x5f,0x7f, + 0xb5,0x88,0x52,0x31,0x4b,0x23,0xe5,0x12,0x2e,0xcc,0xd4,0x70,0x6e,0x72,0x8,0xb3, + 0x63,0x15,0xcc,0x4f,0x54,0x31,0x51,0x2b,0xc6,0xe,0x50,0xd9,0xe0,0xf4,0xbb,0x3f, + 0xfe,0x6b,0xde,0xe4,0xd7,0x35,0x87,0xec,0x68,0xad,0x84,0xff,0xf6,0x7,0xd7,0xa9, + 0xd3,0xd,0xf8,0xef,0x3f,0x7a,0x64,0x7d,0x50,0x59,0xa4,0xe7,0x59,0x1a,0x84,0xf4, + 0x88,0x88,0x7a,0x4a,0xc7,0x49,0x99,0x96,0x16,0x97,0xcf,0xa4,0x70,0x76,0xb2,0x86, + 0xa9,0xa1,0xf2,0xb,0xf9,0x4,0xe6,0x67,0x5b,0xde,0xa9,0xe3,0xf3,0xc7,0x9b,0x38, + 0x68,0x9c,0x5a,0xab,0x5e,0x69,0x7,0x68,0xae,0x7d,0x98,0x30,0x1c,0xc6,0xc0,0x9, + 0xb8,0x39,0x7c,0xf1,0x2,0xb8,0x50,0x2d,0x83,0x7a,0xb2,0xdc,0x47,0x3,0xf1,0xa0, + 0x49,0x7d,0xe4,0x8a,0x1c,0x5e,0x23,0xad,0x21,0x21,0x44,0xb7,0xa6,0xf4,0xca,0x9f, + 0xb7,0xb2,0xd9,0x34,0xfe,0xe2,0x9d,0x4b,0xf4,0xa3,0xd7,0x16,0xe8,0xfa,0xfc,0x28, + 0xaa,0x3,0x79,0x6f,0x32,0x4f,0x6a,0xac,0x4e,0xdb,0x5d,0xfc,0xee,0xee,0xa,0xfe, + 0xf7,0x7f,0xba,0xc5,0xab,0x3b,0x47,0x90,0xe1,0x21,0x14,0xc1,0x2b,0x89,0xbd,0xcd, + 0x86,0xe8,0x5c,0x1c,0xf9,0x90,0x12,0x64,0x50,0x6e,0xad,0xa9,0x20,0xd,0x3e,0xc6, + 0x6b,0x65,0xbc,0x7a,0x6e,0x2,0xb5,0x81,0xc2,0xbf,0xf8,0xfa,0x27,0x89,0x15,0xcf, + 0xcc,0x38,0x6c,0xb4,0x71,0x67,0x71,0xb,0x9f,0x3e,0x5c,0xc3,0xed,0xa7,0xdb,0x58, + 0xde,0xa9,0xa3,0xd9,0xee,0xa2,0xd9,0xea,0x3a,0x3e,0x95,0xcc,0xac,0xa0,0x88,0xb0, + 0xcb,0x65,0x87,0x58,0x6b,0xa,0x9b,0x92,0x66,0x7d,0xd5,0x49,0x7b,0xb4,0xdb,0xc8, + 0x33,0xed,0x4,0x17,0xa6,0xa8,0xd9,0xf4,0x3d,0x6d,0xef,0x6a,0x24,0x6a,0xe1,0x18, + 0x6e,0xe4,0x66,0x30,0xc0,0xa7,0x6,0xd5,0x35,0xf8,0xe,0x5,0xa,0xc9,0x19,0x1c, + 0xfe,0x5b,0x65,0x3b,0x6e,0x97,0x83,0x4d,0x56,0x61,0x21,0x83,0x9f,0x24,0x55,0x8c, + 0x22,0x6b,0x10,0xc7,0x85,0x10,0xcc,0x4c,0x6f,0xfc,0x66,0x2f,0xd7,0x24,0x9e,0x31, + 0x4f,0x11,0x7f,0x6d,0x19,0xa4,0x45,0x9e,0xd3,0x11,0xb1,0xf4,0x72,0xb7,0xf,0x83, + 0xf,0xdf,0xc4,0xb2,0x9d,0x25,0x1c,0x46,0x11,0x5b,0x3b,0xc9,0x42,0xd2,0xa3,0x80, + 0x95,0x10,0x7a,0x34,0x6c,0x86,0xdf,0xb3,0x38,0xa8,0xc8,0x18,0x84,0x90,0x51,0x51, + 0x99,0x24,0x35,0x49,0x64,0x31,0x16,0x64,0x46,0x4e,0x96,0x52,0x8a,0xcc,0xb2,0x82, + 0xf4,0xfb,0xca,0x4c,0xdf,0xa4,0xf4,0x39,0xad,0xf7,0xe5,0xa1,0x22,0x5d,0x53,0xe2, + 0x48,0xd3,0xee,0xf4,0x5e,0x5d,0x14,0x74,0x67,0xc1,0x22,0xb1,0x37,0xca,0x65,0x14, + 0x16,0x26,0x6b,0x74,0x75,0x6e,0x8c,0x5e,0xbb,0x30,0x41,0x6f,0x5f,0x3b,0x43,0x53, + 0xc3,0xe5,0xd8,0x4e,0x3c,0x2a,0x4b,0x8a,0xea,0x52,0xe5,0xdb,0x49,0xb3,0x8d,0x9d, + 0xc3,0x6,0x3e,0x7b,0xb4,0x86,0x67,0x9b,0x7,0xe8,0x72,0x10,0xe1,0xc8,0xcb,0x46, + 0x87,0x22,0xb4,0x38,0xc6,0x50,0xb9,0x88,0x1b,0xe7,0x27,0x70,0x71,0x66,0x4,0xc5, + 0x7c,0xd6,0x23,0xa8,0xc4,0x27,0x38,0x60,0x65,0xbb,0x8e,0xf5,0xdd,0x13,0x71,0x87, + 0x52,0x4,0x2a,0x62,0x13,0xf4,0x11,0x67,0x62,0x8a,0xf,0x67,0x33,0x29,0x9a,0x1f, + 0xaf,0xe2,0x7,0xaf,0xce,0xe1,0xdd,0x9b,0xf3,0x74,0x66,0xbc,0x92,0x88,0x46,0xc8, + 0xc2,0x26,0x89,0x52,0xe6,0xdb,0x1b,0x96,0x30,0xd9,0xd6,0x57,0xec,0x68,0xad,0x67, + 0x35,0x83,0x35,0xbc,0x26,0x44,0xef,0x4e,0xcb,0x64,0xee,0x35,0x65,0xfc,0x76,0x59, + 0x30,0xf4,0xad,0xb9,0x27,0x33,0xc2,0xf3,0x9a,0xc5,0xfa,0x96,0x85,0x23,0x8b,0x75, + 0x52,0xa3,0x18,0x3d,0xc0,0xaa,0x82,0xda,0x3d,0x46,0xa7,0xd9,0xc6,0x51,0x13,0xa0, + 0xc3,0x26,0x3f,0xdf,0x38,0xa4,0x8d,0xfd,0x13,0x3c,0x59,0x3f,0xc0,0x64,0x6d,0x0, + 0xa3,0xd5,0x12,0x86,0x7,0xb,0x18,0x2a,0x17,0x50,0x2e,0xe6,0x50,0xca,0xa7,0x31, + 0x50,0xc8,0xa1,0x98,0xcf,0xa0,0x98,0x4d,0xa3,0x54,0xc8,0x20,0x97,0x49,0x7b,0xf7, + 0x43,0x12,0x7b,0x3e,0xda,0x0,0xf4,0x83,0x37,0xa3,0xbe,0xd8,0x44,0x84,0x62,0x2e, + 0x83,0xab,0x73,0xa3,0xb8,0x72,0x66,0x84,0x7e,0xf7,0xf5,0x2a,0x1f,0x1c,0x35,0xbd, + 0x2f,0x1c,0x6d,0xa0,0x9d,0x81,0x45,0xbf,0x42,0xee,0xdb,0x5a,0x11,0x42,0x17,0xb2, + 0x8b,0xb3,0xc3,0x34,0x3e,0x34,0xd0,0xb7,0x61,0x95,0x3f,0xfb,0xea,0xce,0x11,0x3e, + 0x79,0xb0,0x86,0xfd,0xe3,0xb6,0x48,0xe3,0x14,0xec,0xf6,0xd8,0xa4,0xed,0x84,0xb9, + 0xa4,0x53,0x5b,0xb4,0xe9,0x10,0x2b,0x10,0x5,0xde,0x81,0xc7,0xba,0xe,0xb3,0xe7, + 0xce,0xcc,0x16,0x65,0x60,0xb1,0x3d,0x52,0xd6,0x51,0x82,0x99,0xc3,0x38,0x63,0x37, + 0xca,0xdb,0x45,0x4c,0x3a,0x45,0x74,0x66,0xac,0x82,0xd7,0xce,0x4f,0xd2,0x8f,0x5f, + 0x3f,0x4b,0x37,0x17,0xc6,0x30,0x50,0xcc,0x7a,0xc8,0x97,0xf9,0x1d,0xe5,0x3d,0x7e, + 0x78,0xd2,0xc2,0x7,0x5f,0x2f,0xe3,0xfd,0x5b,0x4b,0xfc,0x7c,0xab,0x1e,0x9e,0x6c, + 0xe4,0xfb,0x2c,0x24,0x60,0x1e,0x1e,0x9b,0x88,0x5,0x28,0xb,0x19,0x89,0x19,0xdb, + 0xc0,0xfb,0xc6,0x38,0xc4,0xc0,0x58,0xb5,0x84,0x1b,0x9a,0xa4,0x68,0x5e,0x87,0xff, + 0x1a,0x4,0xe8,0x45,0xa8,0xd0,0x51,0xa3,0x85,0xfd,0xe3,0x53,0xec,0xd6,0x9b,0xd8, + 0xd8,0xb,0xd,0x9a,0x1e,0xae,0x86,0x1a,0xfb,0x67,0x1b,0x87,0xa1,0x80,0x82,0x22, + 0x6a,0x27,0x8b,0x32,0xb,0x2b,0x5f,0x57,0xe0,0x4d,0x51,0xb5,0x9f,0x20,0xcc,0xc5, + 0xcc,0x3,0x6d,0xf5,0xe1,0xa1,0xbf,0xb1,0x91,0xb3,0x69,0xa8,0x8e,0x55,0xe8,0x8, + 0x17,0x3e,0xc5,0xa1,0x79,0x8c,0xb6,0x77,0x25,0x36,0x4,0x39,0xed,0xff,0x6f,0xa6, + 0x79,0xdd,0x39,0x99,0x6c,0xb,0x8d,0xcf,0x68,0x8f,0x22,0xcb,0x16,0x77,0x63,0x8c, + 0x45,0x2,0x63,0x91,0xf4,0xce,0xe5,0x33,0x6a,0x93,0xe,0x2f,0x15,0xc1,0xb2,0x38, + 0x95,0x8a,0xec,0x4a,0x22,0x48,0xba,0x3,0xd2,0x94,0xad,0xa1,0x32,0xc4,0x8b,0xe0, + 0xdf,0x53,0xa4,0x2c,0x29,0x8e,0xc0,0x91,0xc3,0x5a,0xba,0xa,0xb2,0x2f,0xa,0x8f, + 0x7,0xc3,0xa9,0x48,0xd6,0x97,0x64,0x6c,0xda,0xdd,0x3c,0x5c,0xe5,0x17,0x39,0x71, + 0x24,0x1e,0x48,0x73,0x90,0x3a,0xe2,0x92,0x70,0x82,0x83,0x95,0xa0,0x85,0x93,0xb9, + 0xb2,0x2d,0xb7,0x2e,0xba,0x29,0x2b,0x43,0xd3,0x9,0xdd,0x3a,0x6c,0x25,0xfc,0xaf, + 0x81,0xdd,0x59,0xc8,0xd5,0xc2,0x2f,0xa5,0xf3,0xce,0xd,0x95,0x94,0x84,0xaf,0x26, + 0xd9,0x10,0x45,0x3b,0xb5,0x9e,0x9f,0x1d,0xa1,0x3f,0x7b,0xeb,0xa2,0xfa,0xfe,0x8d, + 0x39,0x5a,0x98,0xac,0x7d,0x23,0x43,0xb9,0xdf,0x81,0xdc,0xeb,0x5,0x68,0x75,0xbb, + 0x38,0x6e,0xb4,0xb1,0xbe,0x77,0x8c,0xdf,0xdc,0x5e,0xc2,0x7,0x5f,0x2f,0xf3,0xd6, + 0x7e,0xc3,0x5f,0x26,0xc6,0xb8,0x8,0x52,0x61,0x10,0x2,0xcc,0xd7,0xe7,0x47,0xf1, + 0xee,0xcd,0x39,0x1a,0x28,0x66,0x13,0xf,0x18,0x79,0xd8,0x36,0x5b,0x5d,0x7c,0xf1, + 0x64,0x93,0xef,0x2c,0x6e,0x1,0x81,0x5b,0x2e,0x30,0x4b,0xe1,0x32,0xc5,0x64,0x70, + 0x1c,0x53,0x50,0x86,0x2c,0xda,0x1f,0xbc,0x3a,0x87,0xbf,0x7a,0xe7,0x32,0x4d,0x8f, + 0xc,0xbe,0xb4,0x1,0x4b,0xf4,0xc0,0xef,0x6,0x9e,0x47,0xbf,0x7e,0xbe,0xf4,0x2d, + 0xab,0xcc,0x3e,0x26,0xc4,0xdd,0x29,0x30,0x9b,0x52,0x12,0xd4,0x29,0x5,0x97,0xf1, + 0x42,0x7e,0x9b,0xe8,0x49,0xa6,0x15,0xd9,0x65,0x2b,0x91,0x73,0xc1,0x25,0x15,0x4d, + 0x85,0x3,0x47,0xf3,0x50,0xc9,0xef,0x9d,0xbd,0xdc,0x1,0x2,0x56,0x76,0xeb,0x58, + 0xd9,0xad,0xcb,0x79,0x12,0xb5,0x81,0x3c,0xc6,0x6a,0x3,0x38,0x33,0x36,0x88,0xc9, + 0xa1,0x1,0x4c,0xf,0x97,0x31,0x3e,0x54,0xc2,0xd4,0xd0,0x0,0xc6,0x87,0xca,0x18, + 0xc8,0x67,0x90,0x4e,0xa9,0xbe,0xd7,0xa5,0x5f,0x51,0xef,0xf7,0x16,0x25,0x5d,0x12, + 0x11,0xe6,0x27,0xaa,0x78,0xfd,0xc2,0x4,0x3e,0x7d,0xb4,0x8e,0xc3,0x93,0x53,0xc3, + 0xed,0x24,0x4b,0x98,0x96,0x9b,0x9b,0x68,0x6a,0x2d,0xb,0x52,0x5c,0xd4,0xa1,0x8d, + 0x80,0x72,0x31,0x4b,0x17,0x67,0x86,0x31,0x5e,0x2b,0x25,0xae,0xe,0xa2,0xf7,0xc1, + 0xca,0x56,0x1d,0x5f,0x3d,0xdb,0xe4,0xe3,0x66,0x3b,0xe2,0x4f,0xa7,0x24,0xec,0xe8, + 0x9c,0xec,0xec,0x49,0x6e,0xb7,0x6e,0x9a,0x1,0xcd,0xc6,0xc,0x89,0xc8,0xb1,0xbf, + 0x3d,0x7b,0x68,0xb2,0x1e,0xf4,0x24,0x5d,0x35,0xc2,0x7a,0xad,0xcc,0xfe,0xdd,0xb5, + 0xf0,0x96,0x13,0xa0,0x6f,0xf4,0x4c,0x5a,0xd1,0xd4,0x50,0x19,0x7f,0xfa,0xd6,0x5, + 0xfa,0xab,0x77,0x2e,0xd1,0xc8,0x60,0x1,0xe9,0x74,0x2a,0xd6,0x94,0x47,0x57,0x27, + 0x40,0x68,0x94,0xf2,0xd7,0xbf,0xfa,0x9a,0xbf,0x5e,0xdc,0x36,0x96,0x3e,0x16,0x31, + 0x22,0x90,0x47,0x36,0xb5,0xa7,0xbd,0x8,0x7b,0xf3,0x1d,0x21,0x34,0x20,0x41,0x31, + 0x5f,0xce,0x58,0xef,0x65,0xce,0xd2,0x89,0xa1,0x1,0x5c,0x9c,0x1d,0x46,0xb9,0x98, + 0xfd,0x67,0x3d,0x93,0xff,0x9c,0xb7,0xc3,0x93,0x16,0xbe,0x7c,0xbc,0x81,0xdf,0xdd, + 0x5b,0xc5,0xad,0xa7,0x5b,0x58,0xdf,0x3b,0x46,0x2f,0x70,0xc9,0xcb,0xb6,0x2f,0x62, + 0xb9,0x57,0x60,0x1d,0x74,0xa3,0x3c,0x29,0x22,0xb,0x56,0xb5,0x70,0x9e,0x60,0x76, + 0xc1,0x2a,0x32,0x51,0x59,0x17,0x64,0x63,0xf9,0xea,0x1c,0xe0,0xb4,0x40,0xdc,0xb1, + 0xdc,0x39,0xfc,0x38,0x21,0xd0,0xde,0xed,0xa1,0xa5,0xab,0x7e,0x45,0x38,0x80,0xcd, + 0xd9,0xe,0xf5,0xed,0x8a,0x39,0x8,0x2c,0x45,0x87,0x99,0xc8,0x57,0xf1,0x32,0x9b, + 0x4,0x6e,0xc8,0x90,0x33,0x8e,0x12,0xd5,0x64,0x73,0x26,0xce,0x8,0x12,0xd7,0xc6, + 0x1f,0xe7,0x1d,0x81,0x93,0x38,0x42,0x5b,0x27,0x3f,0xd6,0xdc,0x6f,0xf1,0xcc,0x59, + 0xe7,0x9e,0x39,0x4b,0x8a,0x33,0xce,0x9f,0x2a,0xc6,0xb0,0x73,0x18,0xbe,0x47,0x6a, + 0x26,0x27,0x4,0x26,0x16,0x58,0x89,0x35,0x29,0x62,0x38,0x8e,0x99,0x74,0x85,0xb3, + 0xd4,0x5a,0x21,0xf4,0x22,0xeb,0xff,0x66,0x1d,0x2f,0x34,0x2e,0xa2,0x8c,0xf,0xbb, + 0x7e,0xfe,0x94,0xd9,0x73,0xb,0x83,0x18,0x3,0xb3,0x93,0x49,0x68,0x20,0x3b,0x89, + 0x2b,0x63,0x28,0xa3,0x44,0xf8,0x8a,0x2d,0xe6,0x9e,0x53,0x94,0x9c,0xce,0x25,0xd1, + 0x37,0xfc,0xf4,0x5a,0x39,0x47,0x3f,0x7e,0xfd,0x2c,0x7d,0xe7,0xca,0x34,0x5d,0x3e, + 0x33,0x42,0xd3,0xc3,0xe5,0xbe,0x26,0xb,0x49,0xd3,0xc9,0xce,0x61,0x3,0xab,0x3b, + 0x75,0xac,0xed,0x1e,0x63,0x6d,0xf7,0x8,0xdb,0x87,0xd,0xd4,0x1b,0x2d,0x34,0x4e, + 0x43,0xdf,0xee,0xd5,0xdd,0x23,0x6c,0xee,0x9f,0xa0,0xd5,0x9,0x3c,0x6d,0x7e,0x8c, + 0xde,0x68,0xaf,0x67,0xf8,0x39,0x69,0x5,0x5c,0x9d,0x1b,0xa7,0xef,0x5c,0x99,0x45, + 0xa5,0x98,0x8b,0x91,0x90,0x64,0x53,0xd1,0x38,0xed,0xe0,0xe1,0xea,0x1e,0x1e,0xae, + 0xec,0x62,0xa7,0x7e,0x2a,0xc8,0xbf,0xf0,0xac,0x55,0xbd,0xda,0xe6,0x71,0x21,0xc2, + 0x1f,0x2a,0x9b,0x56,0xb8,0x3a,0x3f,0x86,0x3f,0x7e,0xe3,0x2c,0x7d,0xef,0xfa,0x2c, + 0xa6,0xf4,0xb5,0xf8,0xe7,0xe8,0xb4,0x43,0xb8,0x32,0x6c,0x30,0xf6,0xea,0xd,0xaf, + 0xa0,0x7b,0xb8,0xaf,0xe1,0x41,0x69,0x8b,0x44,0x56,0x1,0x9c,0xd3,0x6,0xb1,0xc, + 0x75,0x84,0x4d,0xc3,0x21,0x89,0x50,0xd9,0x7d,0x57,0xd8,0x7c,0x2a,0x9b,0xf8,0x1e, + 0xf3,0x1b,0x25,0x49,0x6c,0x26,0x6d,0x10,0x65,0xb2,0x48,0x49,0xb8,0x79,0x13,0x45, + 0x30,0x69,0xcf,0x2,0xc2,0x74,0xe1,0x7b,0x47,0xa7,0x38,0x3e,0xed,0x60,0xfb,0xf0, + 0x4,0xa5,0x5c,0x16,0xa5,0x42,0x6,0xa5,0x5c,0x6,0xf9,0x5c,0x6,0xa5,0x7c,0x6, + 0x3,0x85,0x2c,0x2a,0xc5,0x1c,0xaa,0x3,0x39,0xc,0x16,0x73,0x18,0x2c,0xe5,0x30, + 0x58,0xc8,0xa1,0x52,0xca,0xa1,0x98,0xcb,0xa0,0x56,0x2e,0x60,0xa0,0x90,0x49,0xe4, + 0x62,0xf4,0xbb,0xb6,0x51,0xa2,0xd2,0xfc,0x78,0x15,0xdf,0xba,0x3c,0x45,0x8f,0xd7, + 0xf7,0xb9,0x7e,0xd2,0x76,0xdb,0x36,0x52,0x8e,0x6d,0x15,0xc9,0x26,0x25,0x44,0x61, + 0x6b,0xb3,0x58,0x96,0x4,0x1a,0x46,0x3e,0x9b,0xc1,0xe5,0xd9,0x11,0x8c,0x55,0x4a, + 0x2f,0xe4,0x89,0x74,0xba,0x3d,0x6c,0xee,0x9f,0x60,0x79,0xe7,0x8,0x47,0x8d,0x76, + 0x3c,0x3b,0x17,0x9e,0x9b,0x50,0x4,0x1e,0xb4,0x96,0x8b,0xfa,0xc7,0x61,0xf7,0x1f, + 0x65,0xc8,0xc6,0xe4,0x1b,0x1d,0x92,0x58,0xb6,0x9b,0xfd,0x82,0x4,0xda,0x3c,0x2b, + 0x2e,0x21,0x44,0xd5,0x3f,0xca,0xf4,0xc8,0x0,0x5e,0x3f,0x3f,0x41,0xdf,0xbd,0x3a, + 0x8b,0x1b,0x67,0xc7,0x68,0x5c,0x18,0xab,0x7c,0x53,0xc0,0xc9,0x7b,0xb7,0x9e,0xe3, + 0x9f,0x3e,0x5f,0xe4,0xa7,0xeb,0x7,0xdc,0xe9,0xb1,0x60,0x74,0x38,0xc6,0x36,0x9, + 0x67,0x2f,0x39,0x3c,0xb1,0x74,0xb0,0x91,0xa8,0xa5,0x16,0xe8,0xc9,0xb6,0x32,0x52, + 0x42,0x18,0x60,0xa4,0x88,0xa8,0x36,0x90,0xc7,0xe4,0x70,0x19,0x95,0x52,0x2e,0x51, + 0x15,0xf1,0x2f,0x5,0xbb,0x2b,0x15,0x2a,0x16,0x16,0xb7,0xea,0x58,0xd9,0x3d,0x6, + 0x18,0xd1,0x55,0xaa,0x54,0x93,0xc0,0xbd,0xa,0x70,0x66,0x41,0x2c,0x86,0x56,0x6d, + 0x61,0xca,0x96,0x4a,0x21,0xdd,0xef,0x5c,0x9c,0xa9,0xf6,0x79,0x61,0xc3,0x20,0xd0, + 0x45,0x3d,0x94,0xc2,0x98,0xec,0x73,0x3d,0xbd,0x87,0x5f,0x8e,0x58,0xef,0xd7,0x99, + 0xc8,0xb1,0xe1,0xd9,0x4c,0xe1,0x6,0xd5,0xf,0x1b,0x2f,0x6f,0x32,0x27,0x29,0x8f, + 0x65,0xf6,0x6c,0x15,0xc9,0x6a,0xbd,0x85,0xbd,0xb5,0x20,0x91,0xa9,0x8,0xdf,0x89, + 0xe4,0x4,0x4c,0x24,0x32,0xcf,0x59,0x24,0x27,0xc6,0x1c,0x33,0x1c,0x91,0x40,0xc0, + 0xea,0xc6,0x32,0xd6,0xd3,0xab,0xdb,0x3c,0x74,0xf2,0x5,0xe0,0x2c,0xe3,0x84,0x2c, + 0xbe,0xaf,0x22,0x50,0x91,0xf9,0x7c,0x3f,0x81,0xdd,0xb7,0x36,0x25,0xb1,0xd3,0x12, + 0xb6,0x15,0x4a,0x79,0x9a,0x66,0xb2,0x8a,0x31,0x44,0x82,0xb2,0x52,0x9a,0x67,0xae, + 0xef,0x80,0x94,0xf1,0xc,0x21,0x6d,0x1e,0x63,0x64,0x67,0x5a,0x6f,0xe,0x41,0x72, + 0x13,0xc5,0x9c,0x28,0x61,0x7f,0xee,0xb2,0x44,0x48,0x3c,0xe9,0x9e,0xfb,0xbb,0x79, + 0xb8,0x33,0xe9,0x14,0x46,0x2b,0x5,0x7a,0xf5,0xfc,0x4,0xfd,0xd5,0x3b,0x97,0xe8, + 0xfa,0xfc,0x18,0x99,0x4e,0x3d,0x6a,0x69,0xe8,0x3b,0x7a,0x75,0xd1,0x68,0x77,0xd1, + 0x38,0xed,0x60,0xef,0xa8,0x81,0xa7,0x6b,0x7,0x78,0xb2,0xb1,0x87,0x67,0xeb,0x7, + 0x78,0xba,0x76,0x80,0xb5,0xbd,0x63,0x74,0x7a,0x3d,0x91,0x27,0x65,0xbf,0x88,0x20, + 0xbf,0x59,0x87,0xc,0x78,0xd6,0xf8,0x9a,0x74,0x9f,0x49,0x2b,0xcc,0x8c,0xc,0xd2, + 0x85,0x99,0x21,0x8c,0xd5,0x4a,0x1e,0x94,0x9d,0x74,0x0,0x3d,0x59,0xdf,0xc7,0x47, + 0xf7,0x56,0xb1,0xb2,0x7b,0x62,0xd,0xdd,0x10,0x63,0x5e,0x46,0x36,0x7c,0x4,0x8f, + 0x84,0x97,0x22,0xc2,0xc5,0xd9,0x61,0xfc,0xf8,0xf5,0x79,0x7a,0xf7,0xc6,0x1c,0x66, + 0xc7,0x6,0x13,0x77,0x6b,0x2f,0x73,0x28,0x74,0x7b,0x3d,0xac,0xee,0xd6,0xb1,0xb1, + 0xdf,0x8,0x3d,0x8c,0x8d,0x59,0x88,0xa4,0x57,0xc0,0xa5,0xc5,0xf9,0xe6,0xb2,0x64, + 0x38,0x71,0x2c,0xf8,0xce,0xb2,0x23,0x65,0x41,0xe6,0x34,0x11,0xa1,0xf2,0x1e,0x63, + 0x6f,0x70,0x37,0xe0,0x87,0x72,0x71,0x5b,0xee,0xf6,0x90,0x50,0x19,0x25,0x38,0xdc, + 0x23,0x62,0xb9,0xe9,0x8a,0x4a,0xbb,0x1b,0x60,0xb7,0xde,0xc2,0x2e,0x5a,0x9,0x82, + 0x13,0xc6,0x40,0x21,0x83,0x91,0x4a,0x9,0xa3,0x95,0x2,0x6a,0xe5,0x2,0x46,0xca, + 0x5,0xd4,0xca,0x79,0x54,0x4a,0x79,0xc,0xf,0xe6,0x31,0x5e,0x1b,0xc0,0x58,0xa5, + 0x88,0x6a,0x39,0x8f,0x6c,0x2a,0xa5,0xd3,0x3f,0xe9,0x1b,0xa7,0x74,0xd3,0xd0,0x8d, + 0xf,0x95,0x70,0xf5,0xcc,0x8,0xca,0xc5,0x3c,0x81,0xea,0xec,0xb2,0xb3,0x25,0x82, + 0x9e,0xb0,0x63,0x93,0x8d,0x95,0x3f,0x76,0xd8,0xbd,0x6d,0xb5,0x9c,0xc7,0xf4,0x48, + 0x19,0x25,0xdd,0x74,0xf4,0x73,0xb8,0x3b,0x6a,0x76,0x70,0xe7,0xf9,0x36,0x9e,0x6f, + 0xd5,0xc5,0xc5,0x57,0x3e,0xc9,0x93,0x3d,0x2e,0xbd,0x3d,0xd3,0xd9,0xa6,0xf1,0xb2, + 0x64,0x32,0xda,0x30,0xb8,0x58,0xc2,0x40,0xd4,0x72,0x83,0x64,0x79,0x24,0x8a,0x4, + 0xd7,0xb8,0x3e,0xf,0x40,0x36,0x97,0xa6,0xf1,0x6a,0x9,0x6f,0x5f,0x9d,0xa1,0xef, + 0x5f,0x9f,0xa5,0xef,0x5d,0x9f,0x49,0x8c,0xf9,0x4c,0x7a,0xb6,0x5a,0x9d,0x1e,0x16, + 0x37,0xe,0xf0,0x5f,0xbe,0x58,0xe4,0xf7,0xbf,0x7a,0xce,0xf5,0x46,0x1b,0x91,0x54, + 0x75,0xf7,0xbb,0x12,0x23,0x9a,0x6f,0xc9,0x90,0xd2,0x60,0x4b,0x54,0x94,0xc,0xe, + 0x93,0xe3,0x20,0xac,0xa0,0xe4,0x34,0x4f,0xc8,0xe7,0xd2,0x38,0x37,0x3d,0x84,0xe9, + 0xe1,0x72,0x6c,0xf5,0x17,0xcd,0x1d,0x4f,0x5a,0x1,0xf6,0xe3,0x78,0x24,0x21,0x48, + 0xf9,0x4c,0x1a,0xe3,0xd5,0x12,0x66,0x47,0xca,0x58,0xdd,0x3e,0xc2,0xd1,0x69,0x3b, + 0xe4,0x9a,0x8b,0x9f,0x47,0xd9,0x4a,0x6c,0xfc,0xa1,0x64,0x8a,0x10,0xb3,0x74,0x3a, + 0x52,0xd6,0xff,0xc0,0x90,0x1c,0x54,0x38,0x51,0x33,0x84,0xc7,0x78,0x10,0xa6,0xab, + 0x5,0x2e,0x5d,0x2d,0xfc,0x82,0x81,0x99,0xd4,0x9d,0x84,0x8d,0xc8,0x34,0x0,0x81, + 0x25,0x24,0x84,0xd6,0x83,0x2e,0x8a,0x17,0x6c,0x21,0x78,0xc7,0x44,0xf,0x23,0xcf, + 0x3c,0x37,0x4d,0xb6,0x56,0xaf,0xf2,0x9c,0xb4,0x16,0xd3,0x1c,0xad,0x89,0xe4,0x42, + 0xc7,0xbc,0x2b,0x61,0xd5,0xa2,0x76,0xdf,0xe4,0x37,0x7c,0x4,0xcf,0x21,0xe,0x88, + 0x36,0x63,0xe4,0x7,0xa,0x4a,0x14,0x95,0x84,0x97,0x3b,0xf7,0x11,0x90,0x59,0xb3, + 0x18,0x92,0xd4,0x29,0xf6,0xb9,0xea,0x76,0xea,0x96,0xbc,0x64,0x65,0x33,0x1a,0x7d, + 0xd6,0xb2,0x18,0x8,0x95,0x7e,0x88,0x95,0x43,0x34,0x59,0x59,0xca,0xbc,0x35,0x8f, + 0x62,0x8f,0x79,0x6e,0x25,0x68,0x66,0xda,0xd6,0x91,0xb0,0x21,0x8c,0xae,0xed,0xe3, + 0x54,0x78,0x77,0x84,0xbc,0x76,0xfd,0x99,0x51,0xa6,0xbb,0x4b,0x51,0xb3,0x39,0x2b, + 0x6c,0xcc,0x6a,0x6c,0xae,0x79,0x4a,0x11,0x16,0x26,0xaa,0xf4,0x97,0xdf,0xbd,0xa8, + 0x7e,0xf8,0xea,0x2,0x85,0x81,0x4,0xea,0x85,0x13,0x93,0xb9,0xd5,0x96,0x77,0xea, + 0xf8,0xe4,0xfe,0x1a,0x3e,0x7f,0xb2,0x81,0xc7,0x6b,0xfb,0x38,0x6a,0xb4,0xd1,0x6c, + 0x77,0xd0,0xed,0x85,0x11,0x8a,0x3d,0x23,0x61,0x61,0x3f,0x4b,0x5e,0x18,0xc4,0x3b, + 0xb3,0xc,0x5b,0xe4,0xd8,0x82,0x6,0x4,0x60,0xb4,0x5a,0xc2,0x1f,0xbc,0x72,0x6, + 0x33,0xa3,0xe5,0x44,0x98,0x36,0xfa,0x10,0x7e,0xfe,0x78,0x3,0x3f,0xfb,0xe4,0x9, + 0xe,0x4f,0x4e,0xe3,0x43,0x66,0xd4,0xc1,0x88,0x7d,0x9b,0x74,0x73,0xec,0xbc,0x71, + 0x69,0x8a,0x7e,0xf8,0xea,0x3c,0xfe,0xf8,0xcd,0x73,0x18,0xad,0x14,0xfb,0x1e,0x76, + 0x2f,0x3,0xb9,0xf7,0x2,0xc6,0xfa,0xde,0x31,0x36,0xf7,0x8e,0xd,0x81,0x82,0x41, + 0x46,0xe6,0x49,0x21,0x51,0x55,0xac,0x6e,0x38,0xa0,0x98,0xcd,0x91,0x34,0x7d,0x77, + 0xd6,0x66,0x48,0x82,0x1d,0x48,0x5c,0x44,0x6f,0x79,0xc4,0xa6,0x4c,0x18,0x9c,0x57, + 0x99,0x48,0x46,0x8,0x67,0x64,0x87,0xe3,0x33,0xa4,0x19,0x94,0x53,0x86,0x40,0x28, + 0x35,0x64,0xc5,0x90,0xbe,0xe,0x10,0xad,0x1a,0x93,0xc2,0xc9,0x69,0xf,0xad,0xee, + 0x31,0x36,0xf7,0x4f,0xa0,0x94,0x42,0x26,0x15,0x82,0x4e,0x69,0x22,0xa8,0x94,0x42, + 0x2e,0x93,0xc2,0xf,0x6e,0x9e,0xc1,0x1f,0xbd,0xb1,0x80,0xb3,0x13,0x35,0xc,0x68, + 0x8b,0xd1,0x97,0xd5,0x4,0xe7,0x33,0x69,0x8c,0x56,0x4b,0xc8,0x66,0x52,0xa2,0x10, + 0x21,0x9e,0x21,0xe0,0x5d,0x46,0x11,0x16,0x11,0xf1,0x44,0x37,0x9f,0x5b,0x2a,0x64, + 0x69,0x6a,0xa8,0x8c,0x1,0x91,0x7b,0xdd,0xef,0xed,0xb8,0xd9,0xc2,0x27,0xf,0xd6, + 0xb1,0xb4,0x7d,0x28,0xe0,0xf5,0xe8,0x2e,0xc7,0xe1,0x30,0x32,0x88,0x85,0xac,0xdb, + 0x95,0x22,0x7,0x7b,0x3a,0x74,0x9a,0x88,0x22,0xf1,0x18,0xc9,0x4c,0x3e,0x7f,0xee, + 0x89,0x7a,0x5b,0x30,0x8a,0xb9,0xc,0xfd,0xc1,0x2b,0x67,0xe8,0x8f,0xdf,0x5c,0xc0, + 0x85,0xa9,0x1a,0x8d,0x55,0x4b,0xb1,0xb5,0xd5,0x8b,0x62,0x76,0x3f,0x7e,0xb0,0x86, + 0xff,0xe7,0x83,0x7,0x7c,0xfb,0xe9,0x36,0x1f,0x36,0x5b,0x6e,0x2d,0x24,0x8f,0x7d, + 0x4b,0x8a,0x93,0x33,0x83,0xc4,0x69,0xc9,0xf3,0xb4,0x83,0x7,0x47,0xd8,0x9f,0x9c, + 0xe5,0xe9,0x2e,0x6f,0x83,0x42,0x2e,0x8b,0xcb,0xb3,0x23,0x98,0x18,0x2a,0xbd,0x70, + 0x55,0xd3,0x4f,0x2f,0x9e,0x64,0x62,0xd4,0x8f,0x14,0x57,0x29,0xe5,0x70,0xf3,0xdc, + 0x38,0x86,0x6,0xb,0xb8,0x3c,0x3b,0x8c,0xbf,0x7e,0xef,0x1e,0xb6,0xe,0x9a,0x31, + 0xaf,0x71,0x37,0xd0,0x45,0x3c,0x4b,0xc4,0x9a,0xd7,0xba,0xc0,0x9,0xfb,0x54,0x69, + 0x6e,0x64,0x18,0xb1,0x6c,0xa2,0x52,0xd,0x57,0x35,0xd0,0x8b,0x7a,0x56,0x1c,0x84, + 0x3c,0x5,0x6,0x98,0x3,0x92,0x96,0xb0,0xfa,0xca,0x7,0x5a,0x96,0xa6,0x34,0xdf, + 0x46,0xbb,0xca,0x19,0xdd,0xbb,0x26,0x61,0xda,0x9d,0xb9,0x48,0xeb,0x66,0x8f,0xc7, + 0x14,0xa7,0xf1,0x79,0xea,0x2d,0xb3,0xbf,0x22,0x19,0x4e,0x22,0x12,0xf0,0xc,0x64, + 0x1f,0x11,0x8b,0xf8,0x13,0x78,0xc,0x1a,0x8d,0xb,0xd5,0xcc,0xf4,0xee,0x40,0x36, + 0xcd,0x72,0xb7,0xd1,0x5c,0x92,0xcd,0x9c,0xb8,0xad,0x85,0x10,0xe8,0x1,0x3e,0x49, + 0xc3,0xc0,0xef,0x22,0x15,0xd,0x11,0x82,0xa,0x27,0x13,0xec,0x9c,0xbd,0xa2,0x15, + 0x7f,0x8a,0x27,0xcd,0x4,0x30,0xeb,0xb9,0xda,0xec,0xc6,0xc3,0xb8,0x34,0xe3,0xec, + 0xa6,0x8b,0xb4,0x49,0x49,0x53,0x26,0xea,0x54,0xbb,0xc4,0x69,0xa6,0x3b,0x19,0xa3, + 0x19,0x3b,0x7b,0x29,0x2f,0x21,0xcd,0xfa,0xca,0x84,0xa7,0x72,0x75,0x20,0x47,0xd7, + 0xe7,0xc7,0xe8,0x3b,0x57,0xa7,0xe8,0xdd,0x57,0xe6,0x68,0x76,0x6c,0xb0,0x6f,0x24, + 0xa2,0xf9,0xd8,0xfe,0xd1,0x29,0x96,0x77,0xea,0x78,0xb2,0xb6,0x87,0x47,0xab,0x7, + 0x16,0xde,0x3e,0x38,0x6e,0x45,0x77,0x62,0x0,0x29,0x93,0xe8,0x64,0xad,0x70,0x9d, + 0x19,0x86,0xd0,0xb4,0x44,0x53,0xea,0xc5,0xc9,0x3b,0x5e,0x2d,0xe1,0xed,0x2b,0xd3, + 0x98,0x19,0xad,0xc4,0xa,0xaa,0xec,0xc2,0x4f,0x3b,0x5d,0x3c,0xdf,0x38,0xc4,0xbd, + 0xa5,0x1d,0xac,0xef,0x9f,0x38,0xbe,0x9f,0xf7,0xfd,0x5c,0x6,0x3a,0x5b,0x84,0xd3, + 0x91,0xd3,0xb2,0xe9,0x14,0x2e,0xce,0xc,0xe1,0xc7,0xaf,0x9d,0xc5,0x3b,0xd7,0x66, + 0x30,0x5a,0x29,0xc6,0xa,0x79,0x74,0x9f,0x98,0x24,0xa9,0x92,0x13,0x4f,0xb7,0x17, + 0x60,0x73,0xff,0x84,0xb7,0xea,0x4d,0x8,0x42,0x8c,0x4f,0xa,0x91,0xe5,0x9b,0x44, + 0x18,0x42,0xe4,0x94,0xd1,0xdf,0x8b,0x23,0x46,0x49,0x6c,0xf0,0x72,0xc4,0xd2,0xc4, + 0xf5,0xdf,0x5b,0x62,0x49,0x68,0x7a,0x6c,0x55,0x9b,0xa,0x2e,0xfa,0x56,0x49,0xe7, + 0x27,0x78,0xf0,0x19,0x47,0x5a,0x55,0x26,0xc4,0xe3,0x6b,0xe5,0xc1,0x28,0x8c,0x79, + 0xcc,0xcb,0xdb,0xed,0x5,0x61,0x54,0x25,0x7a,0x51,0x3d,0x2e,0x0,0xe0,0xa3,0xfb, + 0x6b,0xa8,0xe,0x14,0x30,0xa2,0x95,0x14,0xff,0x5c,0x36,0x72,0x3e,0x93,0x46,0x4a, + 0x91,0xab,0x89,0x81,0x1e,0x4,0x58,0x6e,0x5d,0xc8,0x13,0xfa,0x4a,0x8f,0x69,0x61, + 0xe8,0xe,0x22,0x20,0xa5,0x80,0x99,0x91,0x41,0x9c,0x19,0x1d,0x44,0x26,0xa5,0x12, + 0x35,0xf1,0xf2,0xb9,0xd8,0x39,0x6c,0xe0,0xde,0xd2,0x2e,0x36,0xf6,0x1b,0x36,0x59, + 0x1,0xcc,0x6c,0xd2,0x1,0x85,0x60,0x26,0xe2,0xc,0x68,0x50,0x67,0xe7,0xbd,0xe5, + 0x9d,0xaa,0x94,0x9c,0xf8,0xcc,0xf0,0x51,0x25,0xf2,0x3c,0x17,0x5,0xa5,0x9c,0x80, + 0xb1,0x4a,0x91,0xe6,0xc6,0x2b,0xb8,0x34,0x5d,0xa3,0xb7,0x2e,0x4f,0xe3,0x8d,0xb, + 0x93,0x24,0xd7,0x1c,0xf2,0x39,0x92,0x72,0x2d,0xb7,0x4b,0x3e,0xc5,0x57,0x4f,0xb6, + 0xf8,0xbf,0x7c,0xf1,0xc,0x9f,0x3e,0xd8,0xe0,0xa3,0x66,0x1b,0xe,0xce,0x95,0x21, + 0x70,0x24,0xf,0x61,0xb6,0x26,0x62,0x32,0xf2,0x8e,0x1c,0x63,0x4c,0x46,0x1b,0x9b, + 0x19,0xc3,0xde,0x3a,0x5e,0xa6,0xb0,0xdb,0xd3,0xe6,0xb2,0x69,0x5c,0x98,0x1e,0xb2, + 0xaa,0x83,0xa4,0x9,0x3c,0xe9,0x63,0xcd,0x56,0x7,0xed,0x6e,0xf,0xa5,0x5c,0x6, + 0xa9,0x94,0x8a,0x71,0x7f,0x92,0xa,0x7b,0x2a,0xa5,0x50,0xca,0x67,0x70,0xe5,0xcc, + 0x8,0x32,0x99,0x14,0x9a,0xed,0x1e,0x3e,0xbc,0xb7,0x86,0x87,0xab,0xbb,0x68,0x77, + 0x5,0x13,0xcb,0x79,0x9,0xd8,0x2,0x67,0x76,0x61,0x24,0x55,0x2c,0x66,0x2c,0xd, + 0xe0,0xed,0x96,0x6d,0x5c,0xb9,0x9,0xfe,0x0,0x99,0x1d,0x3c,0xeb,0x50,0x1f,0x3d, + 0x77,0x5b,0xbf,0x38,0x56,0xe1,0xfe,0x98,0x3,0xe3,0x41,0xa3,0x39,0x2d,0xa1,0xdf, + 0x9b,0xc9,0x38,0xb7,0x93,0x3c,0x2c,0x54,0xf,0xc9,0xcf,0x61,0xfb,0xa3,0xb3,0xb4, + 0xbf,0x76,0xad,0xba,0x97,0x9c,0xea,0x3d,0x2f,0x42,0x3c,0xcb,0xb1,0x50,0x71,0x73, + 0xe6,0xaa,0x58,0x52,0x1b,0x93,0xef,0x2b,0xc2,0xbe,0x46,0xd3,0x5d,0xe,0x7b,0xfd, + 0x94,0x9b,0xf4,0x75,0xf,0x9e,0x76,0x9e,0x86,0x7e,0x8c,0x34,0xc5,0x58,0x95,0x7e, + 0x97,0x42,0x71,0x17,0xed,0x98,0x22,0x9e,0x12,0xc2,0x36,0x8d,0x56,0x88,0xbc,0x67, + 0x56,0x7c,0x9,0x4d,0x65,0x63,0x16,0xe9,0x66,0xca,0x14,0x5c,0x63,0xe4,0x42,0x76, + 0x1f,0x2e,0x18,0xeb,0xc6,0x20,0x46,0x19,0xd2,0x1b,0xe9,0xe0,0x95,0xf0,0x9,0xb4, + 0x96,0x3d,0x44,0xd0,0xb2,0x35,0x17,0xea,0x2a,0xac,0x64,0x15,0x15,0xf3,0x69,0xfa, + 0xf6,0xe5,0x29,0xfa,0xa3,0x37,0xcf,0xd1,0xf,0x6e,0x9c,0xa1,0x6c,0x26,0x1d,0x7b, + 0x40,0xa2,0x9d,0x6f,0xb3,0xd5,0xc1,0x97,0x4f,0x37,0xf1,0xeb,0x5b,0x4b,0xf8,0xcd, + 0xed,0x25,0xec,0xd4,0x4f,0x1d,0xa4,0xe8,0x1d,0x56,0xd1,0x13,0x49,0xb4,0x81,0x91, + 0x50,0x72,0x7b,0x63,0x58,0x5,0x85,0x54,0xfa,0x31,0xc6,0x6a,0x3,0xb8,0x3e,0x3f, + 0x86,0x9a,0xb6,0xdc,0xec,0x97,0xa4,0xb4,0xb5,0xdf,0xc0,0x7b,0xb7,0x96,0xf0,0x78, + 0xfd,0x40,0x18,0x79,0xb0,0xff,0xfd,0x28,0x82,0x2,0x58,0xf2,0x78,0xf8,0xa7,0xcb, + 0xb3,0x23,0xf8,0xf1,0xeb,0x73,0xf8,0xd1,0x6b,0x73,0x18,0xab,0x96,0xfa,0xc2,0x75, + 0xfd,0xc8,0x81,0x49,0xa8,0x41,0x10,0x30,0x76,0xe,0x9b,0xd8,0xab,0x9f,0x72,0xe0, + 0x4,0x9d,0xce,0x37,0x43,0xeb,0x5c,0x14,0x52,0x42,0x66,0xce,0x1,0xc9,0x86,0x91, + 0x85,0x69,0xa2,0x48,0x99,0x52,0x1e,0xba,0xc4,0xe2,0x95,0x96,0x7d,0xa9,0xd1,0x31, + 0x29,0xf3,0xfb,0xb3,0xe5,0xe5,0x85,0x10,0x20,0x93,0xb,0xc4,0x46,0x3c,0xa6,0x40, + 0x10,0x4a,0x5d,0xc2,0xad,0xdb,0x8d,0x9a,0x6b,0xcc,0xfe,0x9e,0x4b,0x4e,0xbf,0xa4, + 0x12,0x24,0x2b,0xd2,0x35,0x12,0xc0,0xda,0xee,0x31,0x3e,0x7d,0xb8,0x86,0x77,0xae, + 0x4e,0x63,0x32,0x12,0x94,0xf1,0x32,0x48,0x48,0xab,0xd3,0xd5,0xc7,0x95,0x72,0xe5, + 0x8c,0x12,0xfc,0xc3,0x6d,0xae,0x83,0x8a,0xf9,0x48,0x90,0x73,0x86,0x40,0x8a,0x14, + 0xe6,0x27,0x2a,0x98,0x9f,0xa8,0x40,0xa5,0xe8,0x5,0x56,0xa0,0x8c,0xd3,0x76,0x17, + 0xab,0xbb,0xc7,0x58,0xda,0x3d,0x42,0x37,0x80,0x34,0x61,0xf3,0x24,0xae,0xfa,0x98, + 0x34,0x7e,0x8c,0xb2,0xff,0x31,0xb1,0xf,0x82,0xc6,0x23,0x8e,0x57,0x9b,0x9c,0xea, + 0x8e,0x58,0xb2,0x75,0x48,0xc9,0xfb,0x3c,0xea,0x61,0x4b,0x95,0x62,0xe,0x6f,0x5f, + 0x9d,0xa1,0x3f,0xbc,0x31,0x8b,0xb7,0x2e,0x4d,0x91,0x41,0x1b,0x92,0xdc,0xd3,0xa2, + 0xcf,0x7c,0x10,0x4,0x8,0x2,0xc6,0xfd,0xe5,0x5d,0xfe,0xf,0x3f,0xbf,0xc3,0x77, + 0x97,0xb6,0x75,0xe8,0x8a,0x2d,0x58,0xec,0xc7,0xb,0x31,0xfb,0x26,0x97,0x92,0x38, + 0x6c,0xe0,0x4c,0x5,0x23,0xc1,0x90,0xfe,0x79,0x6c,0x9c,0x60,0xa3,0x3e,0x7f,0x26, + 0x5e,0x51,0x3f,0xa3,0xa5,0x7c,0x6,0xf3,0x13,0x15,0x8c,0xd7,0x8a,0xdf,0x8,0x99, + 0x9b,0xfb,0xb3,0xdd,0xe9,0xe1,0xc9,0xc6,0x1,0x8e,0x9b,0x1d,0x4c,0xd4,0x8a,0x18, + 0x1a,0x28,0xa0,0x5c,0xcc,0x7e,0x23,0xf2,0x23,0xaf,0xc9,0xc2,0x58,0x5,0xff,0xe3, + 0x8f,0xaf,0x63,0x72,0x78,0x0,0xff,0xd7,0x7b,0xf7,0xf1,0x7c,0xab,0x8e,0xd3,0x76, + 0x4f,0xfe,0x7e,0x2,0x84,0x20,0x27,0xc4,0x87,0x67,0x67,0xaf,0x69,0x31,0x2a,0x4c, + 0x3a,0xd,0x3c,0x12,0x9c,0x78,0xd5,0x9d,0x63,0xa6,0x29,0xe5,0x52,0x8a,0xcd,0x70, + 0x5,0x3e,0x7c,0xfd,0x3,0xb6,0x44,0x3a,0xdb,0x50,0xeb,0xc1,0x41,0x5,0x3a,0xd1, + 0x4d,0xa7,0xa5,0x2b,0xc1,0xf9,0x32,0xaf,0x9e,0x82,0x88,0xc0,0x6,0x8c,0x14,0xc4, + 0x86,0x7,0xb0,0xaf,0xaa,0xf0,0x66,0x76,0x46,0x1c,0x32,0x8f,0xb,0x85,0x11,0x63, + 0x8c,0xc8,0x6b,0xcd,0xf1,0x8d,0x58,0x6c,0xb8,0x13,0x4a,0xef,0x74,0xd4,0xd2,0xd5, + 0xcb,0x51,0x14,0xb0,0x80,0xb5,0xee,0x22,0x69,0xb1,0xc5,0x91,0xd8,0x16,0x17,0x5d, + 0xe8,0x63,0x9d,0x10,0xe4,0x17,0xff,0x4f,0x1e,0xbb,0x9f,0x1c,0xcf,0x5d,0xcf,0xd0, + 0x92,0xcc,0x12,0x1a,0xc7,0x68,0x73,0x18,0x37,0xbf,0x2b,0x25,0x2c,0x60,0xad,0xeb, + 0x1b,0x4c,0xbe,0xb9,0xdd,0xa5,0x2b,0x4d,0x98,0xd3,0xb8,0x81,0x89,0x2e,0x62,0xab, + 0x4f,0x25,0x10,0xb0,0x30,0x51,0xa1,0xef,0x5e,0x9d,0xa5,0xef,0x5d,0x9f,0xa5,0x6b, + 0x73,0xa3,0xb6,0x98,0x27,0x11,0xdf,0x4c,0x8a,0xd2,0xed,0xc5,0x6d,0xbc,0x7f,0x7b, + 0x9,0xf,0xd7,0xf6,0xb0,0xbc,0x7d,0x84,0xdd,0xa3,0x53,0x50,0x44,0xe3,0x4d,0xe2, + 0xb0,0xf6,0x6b,0x3,0x79,0xf2,0x6,0x7f,0x8f,0x29,0xcc,0x77,0x4,0xa7,0x30,0x95, + 0x26,0x4c,0xd6,0xca,0x38,0x3f,0x55,0x43,0x29,0x9f,0x7e,0x21,0x49,0x7,0x0,0xd6, + 0xf7,0x4e,0xf0,0xfe,0xd7,0xcb,0x58,0xda,0xaa,0x47,0xa4,0x24,0x72,0x70,0x55,0xae, + 0xf3,0x87,0x33,0x44,0xc8,0xa6,0xd2,0xb8,0x38,0x5d,0xc5,0x4f,0xdf,0x5c,0xc0,0x1f, + 0xde,0x9c,0xb3,0x30,0xbb,0x24,0xde,0x45,0x39,0x4,0xcc,0x8c,0x67,0x1b,0x7,0x8, + 0x18,0x98,0x19,0x29,0x27,0x3a,0xe5,0x59,0x8f,0xe7,0xe3,0x53,0xec,0x37,0x5a,0x7e, + 0x1e,0x91,0xbb,0x48,0x61,0x40,0xa2,0x67,0x4b,0x24,0x7c,0x1b,0x24,0xf6,0x6d,0x3a, + 0x5f,0x56,0xbe,0xc6,0x53,0xe8,0x29,0xc9,0x63,0x4b,0x89,0xd0,0x20,0x67,0x1e,0x61, + 0x13,0x31,0xd8,0x2d,0x73,0xe4,0x82,0x53,0xbc,0x6b,0x3d,0x48,0x1d,0xfb,0x8e,0x28, + 0x8c,0x7e,0x30,0x8d,0x2a,0xf9,0x39,0x5,0xa6,0x31,0xb3,0xcf,0x51,0x94,0x15,0x6b, + 0xaa,0xbe,0x8a,0xbd,0x90,0x0,0xa9,0x97,0x82,0xda,0xa3,0x53,0x58,0xb3,0xd5,0xc1, + 0xd6,0x61,0x3,0xad,0x6e,0x20,0x49,0x32,0x64,0x76,0x9,0x3e,0xad,0xd6,0x17,0xa1, + 0x2b,0x47,0x1,0xf6,0x59,0xee,0x2a,0x64,0xcf,0x2f,0x4c,0x54,0x91,0x4a,0xb0,0x3b, + 0x35,0x6f,0xdd,0x5e,0xf,0xf,0xd7,0xf6,0xf0,0x60,0x75,0x1f,0x2d,0x7b,0xc0,0xbb, + 0x62,0xce,0x88,0x3,0x57,0x10,0x81,0x6f,0x76,0x0,0xa1,0x50,0xa3,0x26,0xd,0xe2, + 0x5c,0x3a,0x9f,0x99,0xc,0xd8,0x71,0x76,0x84,0xea,0x86,0x49,0x45,0x28,0x78,0x44, + 0x73,0xa3,0x65,0xdc,0x38,0x37,0x46,0xaf,0x9d,0x1b,0xc3,0xf9,0xc9,0x2a,0xcd,0x8c, + 0xc,0x62,0xa0,0x90,0xed,0x3b,0xc9,0x46,0x79,0x29,0x0,0xb0,0xb9,0x7f,0x82,0xf7, + 0x6e,0x2f,0xf3,0xfb,0x77,0x56,0xf8,0xc1,0xea,0x1e,0x1a,0xad,0x1e,0xcb,0x94,0x59, + 0x32,0x42,0x3a,0x72,0xd7,0x2c,0x60,0xf6,0x82,0xb3,0x7c,0x6f,0x30,0x43,0xe9,0xb3, + 0x61,0x85,0xce,0x38,0xd4,0x64,0x19,0x53,0xe4,0xd5,0x27,0xff,0x65,0x19,0xad,0x94, + 0x30,0x32,0x58,0x48,0x6c,0xb2,0xa5,0xcf,0x7a,0xb3,0xd5,0xc5,0xc3,0xd5,0x3d,0xdc, + 0x5f,0xdd,0xc3,0xe3,0xd5,0x7d,0xac,0xed,0x9f,0xa0,0xd3,0xe9,0xa1,0x5c,0xcc,0xe2, + 0xb5,0x85,0x71,0x7c,0xf7,0xda,0x34,0x16,0xc6,0x7,0x13,0x99,0xfc,0xd1,0xa8,0x54, + 0xad,0x2c,0xc6,0x40,0x21,0x8b,0xef,0x5d,0x9d,0xc1,0x60,0x31,0x8b,0x5f,0x7e,0xb9, + 0x84,0x4f,0x1f,0x6d,0x62,0xeb,0xb0,0x81,0x58,0xec,0x2b,0xe2,0x19,0xc,0x9e,0x53, + 0xb9,0x87,0x32,0xb3,0xe4,0x34,0x72,0x84,0x7a,0x2a,0x51,0x63,0x31,0x31,0x53,0x24, + 0xbe,0x54,0x81,0x10,0x18,0xc3,0x22,0x67,0x15,0x6b,0x29,0xe0,0xe6,0x36,0xd1,0xd3, + 0xa6,0xe7,0x7f,0x21,0x8c,0x61,0xac,0xbb,0x8b,0xf1,0xbe,0x8a,0x38,0xad,0x51,0x64, + 0x38,0x13,0x82,0xc9,0xe8,0x1a,0xd3,0x4f,0x42,0x89,0x5b,0xba,0x46,0xd3,0xa1,0x39, + 0xa6,0x20,0xa7,0x88,0xff,0xbb,0xfb,0x1a,0x69,0xfb,0x64,0x9,0x27,0x18,0x6b,0xaa, + 0xe4,0x99,0xc7,0xc8,0x7,0x3a,0x29,0x5b,0x4d,0x1f,0xa6,0xd4,0x27,0x4f,0x9d,0x89, + 0x92,0xba,0x11,0xb7,0x33,0x66,0x21,0xd6,0x53,0xe4,0x2,0x14,0x74,0xe2,0x7,0x89, + 0xf8,0xd2,0x30,0x30,0x4d,0x14,0xf2,0x50,0x43,0xce,0x26,0x7c,0x45,0x19,0xf1,0x93, + 0x8b,0x3e,0x35,0xff,0x2e,0x84,0xdf,0x4d,0xa4,0x13,0x81,0x52,0x61,0x81,0x4f,0x29, + 0xc2,0x68,0xb5,0x44,0xef,0xde,0x98,0xa7,0x3f,0x7a,0x63,0x81,0xae,0xcc,0xe,0x93, + 0x81,0x9f,0xa2,0xa4,0x12,0xe3,0xd1,0xbc,0x5b,0x6f,0xe2,0xfe,0xca,0x1e,0x7e,0xf9, + 0xd5,0x73,0xfc,0xe3,0xa7,0x4f,0xc3,0xae,0x94,0xd8,0x6f,0x84,0x90,0xd8,0x86,0xc5, + 0xff,0x26,0x76,0x4e,0x2b,0x24,0x3a,0x7c,0x10,0x90,0x49,0x67,0x70,0x7d,0x7e,0xc, + 0x17,0xa6,0x6b,0x48,0x29,0xe5,0x59,0x4f,0x4a,0xf9,0x50,0xaf,0x17,0xe0,0xf8,0xb4, + 0x8d,0x27,0xeb,0xfb,0x78,0xb0,0xb2,0x8f,0x4e,0x8f,0x23,0x3a,0x57,0xa7,0x44,0x70, + 0x84,0x32,0x16,0x84,0x34,0xc2,0xc2,0x44,0x5,0x3f,0xb8,0x39,0x8f,0x77,0xae,0xcd, + 0x60,0x66,0xc4,0x41,0x79,0x51,0x17,0x30,0x73,0x8,0xb6,0x3b,0x3d,0xac,0xef,0x9f, + 0xe0,0xb7,0x77,0x56,0x50,0x2c,0x64,0x30,0x34,0x10,0xa6,0xac,0x25,0x15,0xa2,0x5e, + 0xc0,0x61,0xe2,0x5c,0xb3,0xed,0xe9,0xec,0x61,0xd,0x45,0xfc,0x2c,0x1,0x8f,0x42, + 0xc4,0xde,0x8a,0xc7,0x6d,0x9f,0x84,0xa4,0x8d,0x62,0xad,0x2d,0x25,0x5c,0x6f,0xdf, + 0xfa,0x58,0xb0,0xa3,0xdd,0x27,0xa9,0x68,0xfa,0xa0,0x68,0x8b,0x5,0x49,0x9c,0x42, + 0xb7,0x31,0x4f,0x4b,0x1f,0xad,0x55,0x7d,0x27,0x1f,0x44,0xf9,0x26,0xee,0xfe,0x18, + 0xab,0x94,0x70,0x7e,0xaa,0x86,0x81,0x42,0xee,0xa5,0xf7,0xe7,0xe6,0x35,0xd9,0x3a, + 0x6c,0xe0,0xee,0xd2,0x2e,0x8e,0x4e,0xdb,0x31,0x64,0xc1,0xa2,0x13,0x49,0xa2,0x44, + 0xc1,0xe0,0x85,0x95,0x66,0x1b,0xdf,0x80,0x34,0x66,0x86,0xcb,0x98,0x19,0x2d,0x5b, + 0x47,0xbc,0x24,0x1d,0x7a,0xc0,0xc0,0xbd,0xe5,0x5d,0xdc,0x5d,0xda,0x45,0x60,0xd0, + 0x8,0xdf,0xe3,0x9a,0x20,0x23,0xa,0x7c,0x60,0x9d,0xed,0x4a,0xc8,0x8,0xcf,0x6d, + 0x54,0x84,0xcb,0x40,0x37,0xc3,0x30,0x94,0xf2,0x5d,0xd,0xd9,0x77,0xde,0xca,0x65, + 0xd2,0x94,0xcb,0x28,0x4c,0x8f,0x94,0xf1,0xda,0xd9,0x31,0xfa,0xfe,0x2b,0xb3,0xf8, + 0xf6,0xc5,0x49,0x92,0x9c,0x98,0x24,0x48,0xda,0x3c,0x4b,0xe6,0xef,0x4e,0xdb,0x1d, + 0xac,0xed,0x9d,0xe0,0xab,0xa7,0xdb,0xfc,0xb7,0xbf,0x7f,0xc2,0x77,0x9e,0xef,0xb0, + 0x98,0xa6,0xd8,0x1,0x5,0x7a,0x25,0x23,0xa4,0x81,0xd6,0x23,0xc1,0x63,0x84,0x47, + 0xd9,0x95,0xae,0x8c,0x5a,0x19,0x90,0xc0,0x4d,0x2c,0x92,0xc8,0x3a,0x78,0x40,0x1f, + 0x84,0x23,0x83,0x79,0x4c,0xf,0xf,0xa0,0x98,0xcd,0x24,0xaa,0x1d,0xe4,0xef,0xb3, + 0x7f,0x7c,0x8a,0xf,0xee,0xad,0xe1,0xfd,0x3b,0x2b,0x78,0xb0,0xb2,0xe7,0x20,0x2b, + 0x6,0xd6,0x76,0x4f,0xd0,0xe5,0x0,0x8d,0xd6,0x38,0x16,0xc6,0x6b,0x28,0xe6,0xd2, + 0x90,0xa1,0x73,0xde,0xeb,0x1b,0x89,0xc9,0x1d,0xaf,0x95,0xf0,0x93,0xda,0x2,0xd2, + 0x2a,0x85,0x54,0x2a,0x85,0xcf,0x1f,0x6f,0x62,0x63,0xff,0x4,0xbd,0xc0,0x71,0x0, + 0x48,0x42,0xc6,0x5e,0xbe,0x3b,0xe2,0xce,0x71,0x5a,0x78,0x4e,0x81,0x1f,0x7,0xe6, + 0xa0,0x70,0xa7,0x5c,0x95,0x83,0x91,0x85,0x33,0x34,0xab,0xe,0x2a,0x9c,0xd4,0x11, + 0x28,0x80,0x2,0x2d,0x7d,0xd,0x5c,0x40,0x18,0xfb,0x50,0x54,0x38,0xc4,0x9b,0xee, + 0x41,0xf9,0xcf,0xa7,0x8c,0x1b,0x67,0x47,0x54,0x83,0x35,0xfe,0x8a,0xa,0x8d,0xc9, + 0x5,0x41,0xab,0x38,0xad,0xc3,0xdf,0xa7,0x73,0x84,0xd,0xe2,0xef,0xe6,0x39,0x26, + 0x73,0xa7,0xd8,0x7a,0x3c,0x2d,0x40,0x67,0xb,0xc4,0x87,0x1,0x2d,0x4e,0xd,0xef, + 0xd4,0x40,0x92,0x90,0xe4,0x33,0x34,0x20,0x8,0xe9,0x49,0x26,0xf2,0x4c,0x11,0xdb, + 0x57,0x87,0xfd,0x92,0x8d,0x2a,0x24,0xab,0x42,0xb6,0x98,0x7a,0x88,0x53,0x99,0xf4, + 0x4,0x3b,0x7d,0xb,0xc8,0x3d,0x84,0xd7,0x39,0x2c,0xea,0x4a,0xf,0xe3,0x8a,0xd9, + 0x5,0xa0,0x92,0x4b,0x5c,0x95,0x60,0x23,0x48,0x69,0x22,0x1c,0x3,0x17,0x67,0x87, + 0xe9,0xdf,0x7d,0xff,0xb2,0x7a,0xfd,0xdc,0x4,0xcd,0x8c,0xc,0x58,0xcd,0x69,0x3f, + 0x28,0xf9,0xe1,0xea,0x3e,0xde,0xbb,0xbd,0x84,0xf7,0x6e,0x2f,0xe3,0xd9,0xe6,0x21, + 0xda,0x7a,0x2,0xf2,0x7c,0x87,0x11,0xd7,0xee,0xfb,0xb7,0xab,0x5f,0xd8,0x23,0xb7, + 0x72,0x8c,0x4c,0x62,0x3e,0x2b,0x9b,0x51,0xb8,0xb1,0x30,0x86,0x4b,0x33,0xc3,0x89, + 0xe4,0x37,0xf3,0x73,0xb7,0x3a,0x3d,0x7c,0xfc,0x70,0x1d,0x5f,0x3e,0xdd,0xd4,0xf, + 0x95,0x13,0x59,0x98,0x31,0x89,0xd9,0xef,0x88,0x1d,0x1e,0xb,0x5c,0x98,0xac,0xe0, + 0x7,0x37,0xe7,0xf0,0x97,0x6f,0x5f,0xc0,0xb8,0x66,0xd1,0x47,0xf7,0xe3,0xd1,0xef, + 0xff,0xc5,0xd3,0x2d,0xfc,0xc3,0x27,0x9,0xe9,0x44,0x0,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x4f,0xf1,0xdb,0xaf,0x97,0x71,0xe5,0xcc,0x8,0xde,0x38,0x37,0x8e, + 0x4a,0x29,0xa7,0x3,0xba,0x38,0xb6,0x22,0x3e,0x6a,0x76,0xd0,0xea,0x6,0xe1,0x61, + 0x17,0x88,0xde,0xcf,0x62,0xd4,0xae,0xe8,0x28,0xeb,0xfd,0xe0,0xb9,0x63,0x11,0x7, + 0xcc,0x82,0x8d,0xaf,0x25,0xbe,0x2e,0xcb,0xd6,0x8f,0x4,0x17,0x39,0x82,0x2,0xba, + 0x77,0x3b,0x56,0xe5,0xb3,0xed,0x3c,0x83,0x7,0x61,0x77,0x2b,0x39,0x2f,0xf2,0x40, + 0x17,0x8d,0x3,0x47,0xe4,0x60,0xb1,0xee,0x2e,0x29,0x7d,0x21,0xe2,0xa8,0x8,0x0, + 0x17,0x67,0x86,0xf0,0xc3,0x9b,0x67,0x30,0x54,0xce,0x7f,0xa3,0x14,0x29,0x4a,0x6e, + 0x7a,0xb6,0x71,0x88,0xf,0xee,0xae,0x21,0x4c,0xd7,0xa3,0x3e,0x3f,0x0,0xc1,0xf7, + 0x3,0x27,0x70,0x2,0x84,0x68,0xfe,0x58,0x1b,0xc8,0x63,0xa2,0x56,0x42,0x21,0x9b, + 0xe9,0xfb,0x8c,0x98,0x3,0xff,0xe1,0xea,0x3e,0xee,0x2f,0xef,0xa1,0x17,0x4,0x88, + 0xe4,0x77,0x4b,0x40,0x24,0x42,0x5b,0x23,0x73,0x29,0xad,0x2e,0xd9,0x73,0x3c,0xf5, + 0x56,0x84,0x21,0x2b,0xd9,0x31,0x47,0x55,0xe8,0x8,0xad,0x9c,0x30,0xa2,0x50,0xc8, + 0xe0,0xda,0xec,0x30,0xde,0xb9,0x3a,0x4d,0x37,0x16,0x46,0x69,0x6a,0x68,0x0,0xd5, + 0xb2,0x7f,0x4f,0x26,0xf1,0x3d,0xa2,0xcf,0x7c,0xbb,0xd3,0xc5,0x97,0x4f,0xb6,0xf9, + 0xe7,0x5f,0x3d,0xc7,0x6f,0xee,0xac,0xf2,0x6e,0xbd,0x61,0x24,0xfd,0xec,0x2c,0x3e, + 0xd,0xc9,0xca,0x77,0x7f,0x73,0xe2,0x4a,0x16,0x9b,0x1f,0xf2,0xee,0xa,0xb6,0x5d, + 0x96,0xf9,0xc7,0x2e,0xbf,0x3e,0x44,0x77,0x85,0xb0,0x5b,0xe6,0x15,0x10,0x61,0x76, + 0x74,0x10,0xb,0x93,0x55,0x2f,0x2a,0x35,0x2e,0x13,0xd,0x7,0x93,0xf5,0xfd,0x63, + 0xfc,0xf2,0xab,0x25,0x3c,0x59,0x3f,0x74,0x56,0x3e,0xfa,0xff,0x1e,0xae,0x1f,0x60, + 0xe7,0x57,0xf7,0xf1,0xc5,0x93,0x6d,0x7c,0xf7,0xea,0x24,0xfe,0xe4,0xf5,0x5,0x54, + 0xb4,0x33,0xde,0x8b,0xc8,0x75,0x12,0xad,0x7b,0xfb,0xca,0x24,0xa6,0x86,0x7,0xb0, + 0x30,0x3e,0x88,0x5f,0xde,0x5e,0xc1,0xd7,0xcf,0xb6,0xbd,0x67,0xc2,0xcf,0x6f,0xa4, + 0xa8,0x6e,0x45,0xf0,0xad,0x44,0x5f,0x67,0xad,0xc9,0x2,0xb7,0x7f,0x31,0x34,0x82, + 0x80,0x6c,0xd8,0x34,0xab,0xc0,0x21,0x5d,0xc2,0x23,0x8c,0xad,0x64,0x40,0x3e,0xdf, + 0xcc,0x50,0xa,0x8,0x2,0x4d,0x64,0x93,0xa2,0x2d,0x19,0x4b,0xea,0xc3,0xfe,0x16, + 0xc1,0x54,0x12,0x6e,0x11,0xeb,0xb3,0x18,0xc,0x41,0x89,0x42,0xc,0x62,0xef,0x98, + 0x41,0x2c,0xea,0xd9,0xd1,0xf1,0x11,0x77,0x24,0xf1,0xbf,0x98,0x37,0xa1,0xbb,0x94, + 0x40,0xbb,0xb7,0xf4,0x7e,0x1e,0x8e,0x20,0xff,0x14,0xb5,0x84,0x95,0x88,0x49,0x4c, + 0x6,0x15,0x97,0x44,0x79,0xc8,0x11,0x6b,0x73,0x37,0x38,0x28,0xc3,0x41,0xae,0xca, + 0x39,0xb5,0x85,0xf0,0x3a,0xc1,0xe8,0xcd,0xed,0xdf,0x28,0x21,0x5b,0xb,0xc9,0x6f, + 0xac,0xed,0x5e,0x5,0x93,0x9d,0x34,0xf2,0x46,0x70,0x43,0x1d,0x81,0x40,0xf9,0x74, + 0x9a,0xae,0xcf,0x8f,0xd2,0xbb,0x37,0x66,0xe9,0xbb,0x57,0x66,0x68,0x7a,0xe4,0xc5, + 0x8c,0xf1,0xed,0xc3,0x26,0xee,0x2e,0x6d,0xe3,0xe3,0x7,0xeb,0xf8,0xf8,0xe1,0x6, + 0x1e,0xae,0xec,0xb,0x13,0x1,0x1,0x6a,0xf4,0x31,0xd1,0xa7,0xe4,0xd9,0xac,0xcf, + 0x7b,0x49,0xb1,0x36,0xa,0xd5,0x52,0x1e,0x67,0x27,0xab,0x98,0x1e,0x1e,0x30,0x72, + 0x96,0x44,0x28,0xac,0xd5,0xe9,0xe1,0xf3,0xc7,0x9b,0xb8,0xf3,0x7c,0xf,0x1,0xf7, + 0xb1,0xf7,0x8d,0x1e,0xa8,0xfa,0x61,0x98,0x19,0x2d,0xe3,0xf,0x6f,0xce,0xe1,0xdd, + 0x1b,0xb3,0x9e,0x71,0x48,0x92,0xcd,0x28,0x11,0xe1,0xa8,0xd9,0xc6,0x9d,0xc5,0x1d, + 0xfc,0xfc,0x8b,0x45,0x7c,0x78,0x77,0x15,0x3b,0xf5,0x53,0xd4,0x4f,0x5a,0xc8,0x64, + 0x52,0xb6,0xc3,0x8f,0x1d,0x30,0xc,0x34,0x3b,0x5d,0x99,0xe9,0x4b,0x1e,0x45,0xd6, + 0x36,0xf3,0x64,0xdf,0x71,0x46,0x24,0x81,0x7d,0x28,0x4d,0xde,0x85,0x9e,0xfa,0x2c, + 0x69,0xdd,0x33,0xf6,0x26,0x26,0x21,0x11,0x21,0x44,0x27,0x62,0x8a,0xe3,0x81,0xb1, + 0x70,0x5,0xef,0xdf,0xf9,0xd1,0x80,0xc2,0xff,0xdc,0x3d,0x31,0x82,0x70,0x1a,0x59, + 0x2,0x43,0x90,0x5,0x90,0x98,0xc0,0x0,0xa0,0x94,0x4f,0xe3,0xda,0x99,0x61,0xbc, + 0x73,0x75,0x1a,0x17,0xa7,0x87,0x50,0xca,0x67,0x5e,0x68,0x30,0x13,0x9d,0x98,0x36, + 0xf6,0x4e,0x70,0x6b,0x71,0x1b,0xf7,0x96,0x77,0x71,0x72,0xda,0x8b,0x4c,0x31,0xee, + 0x59,0x65,0x24,0x70,0x2f,0xe2,0xb,0x20,0x0,0xc0,0x60,0x21,0x8b,0xb9,0xf1,0xa, + 0x2a,0xa5,0xdc,0x37,0x3a,0xd9,0x6d,0x1e,0x34,0xb0,0xba,0x7b,0x82,0x46,0xbb,0x6b, + 0xf9,0x2,0x2c,0xe6,0x50,0x86,0xb1,0x7e,0x63,0xcf,0x4b,0x85,0x85,0x1f,0xad,0xa1, + 0xe9,0x81,0x48,0x70,0xc0,0x58,0xf4,0xc3,0xca,0x81,0xb3,0xca,0xbd,0xdc,0xf9,0x4c, + 0x1a,0xe3,0x95,0x22,0xa6,0x46,0xcb,0x74,0x76,0x7c,0x10,0x97,0x66,0x86,0xf1,0xca, + 0xdc,0x8,0xcd,0x8d,0xd,0x22,0x15,0xc9,0x7,0xf,0xb4,0xdd,0xb7,0xf4,0x26,0x8f, + 0x22,0x4f,0x2b,0xbb,0x27,0xb8,0xbb,0xb4,0xcd,0xbf,0xbb,0xbb,0xc6,0x9f,0x3e,0xda, + 0xc4,0xd6,0x41,0x83,0x59,0x48,0xc7,0xd9,0xcc,0x89,0x3a,0xa3,0x4b,0xa0,0xef,0x1e, + 0x5c,0x2c,0x9b,0xf,0xe7,0x80,0x10,0xd9,0x35,0x7b,0xb1,0x30,0xd6,0x69,0x26,0xec, + 0x45,0xd9,0x28,0xfe,0x9c,0x4,0x8c,0x8,0x98,0x19,0x2d,0x63,0x61,0xbc,0x82,0x74, + 0x8a,0x12,0xbd,0x30,0x4c,0xf3,0xba,0x79,0xd0,0xc0,0xe3,0xf5,0x43,0xac,0xef,0x9d, + 0x44,0xfb,0xdd,0xf0,0x8e,0xc,0x80,0x9d,0xe3,0x53,0x7c,0xfe,0x64,0x13,0xcd,0x76, + 0x7,0xad,0x4e,0x80,0x57,0xcf,0x8e,0x62,0x7e,0xac,0x82,0x41,0xb1,0x5b,0x4f,0x32, + 0xd4,0x31,0xd7,0x30,0x97,0x49,0xe3,0xe2,0x74,0xd,0x44,0x40,0x26,0x9d,0x42,0x3e, + 0x9b,0xa2,0x7b,0xcb,0x7b,0xdc,0x38,0xed,0x44,0xf8,0x5a,0x62,0xcd,0xe4,0xbc,0xfb, + 0xe1,0xac,0x5a,0x92,0x90,0x4e,0x45,0xda,0x54,0xc6,0xec,0x62,0x74,0x13,0x14,0x18, + 0xc3,0x9,0x1d,0xb1,0xab,0x99,0x33,0xa1,0x8f,0xbb,0xe7,0xb0,0x86,0x88,0xd0,0x25, + 0xbc,0x85,0x1c,0x1f,0xdf,0xa0,0x84,0xc,0x99,0xde,0x24,0x80,0x9f,0xa8,0x8f,0x80, + 0x58,0x21,0xc5,0xb2,0x4e,0xc4,0x4a,0x2d,0xb6,0xf3,0x8e,0xef,0xdc,0xbc,0xf3,0xc1, + 0x47,0x31,0x10,0xcd,0x10,0xf7,0xd8,0x42,0xe6,0xba,0xa5,0x65,0xc,0xa6,0xcf,0xae, + 0x76,0x5f,0x47,0xb9,0x73,0x3e,0x2,0xcd,0xb3,0x23,0x3a,0xc0,0x35,0xcb,0x11,0x79, + 0xbc,0x90,0x5,0x9b,0x43,0x4c,0x39,0x5e,0x3c,0xd9,0xec,0x5f,0xc7,0x6a,0x87,0x12, + 0x77,0xa5,0x2c,0xde,0x7a,0x7a,0x27,0xa5,0x98,0x44,0xfe,0xb9,0x99,0xd6,0xc3,0x96, + 0xce,0x9c,0xea,0xb6,0xb,0x30,0x31,0x3a,0xb6,0x77,0x31,0xf8,0x3d,0x29,0x9c,0x9d, + 0x1a,0xa2,0xff,0xfe,0x87,0x57,0xe9,0x5b,0x17,0xa7,0x68,0xb0,0x98,0x8d,0xed,0xc8, + 0xcd,0xfb,0xbd,0x5e,0x80,0xe3,0x66,0x1b,0x1f,0x3f,0x58,0xc3,0x5f,0xbf,0x77,0x1f, + 0x4f,0xd6,0xf6,0xd1,0x68,0x77,0xdd,0x5,0x66,0xf6,0x60,0x19,0x2f,0x9d,0x3b,0xa9, + 0x2e,0x27,0x30,0xfe,0xfd,0xf3,0x3c,0xaa,0x27,0xa,0xbf,0x4e,0x21,0x9b,0xc6,0xcc, + 0xc8,0x20,0xc6,0x6b,0xc5,0x17,0xc6,0x1a,0x12,0x11,0x8e,0x4f,0xdb,0xb8,0xbf,0xb2, + 0x8f,0xb5,0xbd,0xe3,0x17,0xc7,0x39,0x45,0x3a,0xc9,0x89,0xda,0x0,0xde,0xb8,0x30, + 0x89,0x3f,0xfb,0xd6,0x39,0x2c,0x4c,0x56,0x13,0xbb,0xf1,0x28,0xab,0xfd,0xce,0xe2, + 0xe,0xfe,0xc3,0x2f,0xee,0xe0,0xde,0xd2,0x1e,0xea,0x8d,0x16,0x88,0x14,0xaa,0x3, + 0x79,0xd4,0x6,0x5e,0x34,0x55,0x32,0x3a,0xbd,0x20,0xa2,0xa3,0x72,0xe4,0x28,0xab, + 0xb0,0xb4,0x1e,0xd0,0x1,0x87,0xe1,0x2c,0x12,0x5b,0x97,0x4e,0x46,0xa2,0x13,0x88, + 0xc0,0xeb,0x24,0x98,0x51,0x5a,0x9a,0x45,0x92,0xd5,0xc1,0x22,0x68,0xd6,0x8f,0x30, + 0x14,0x7a,0x60,0x8f,0xa1,0x23,0xac,0x6a,0x29,0xa1,0x5f,0x8e,0xb2,0x58,0x38,0x1a, + 0x19,0xa3,0x77,0xf4,0x5a,0xba,0xc9,0xec,0x20,0x70,0x26,0x20,0x45,0xc0,0xf5,0xb9, + 0x51,0xfc,0xf,0x3f,0xba,0x8a,0x6b,0x67,0x46,0x2c,0xbb,0xfd,0x9b,0xcc,0x7a,0x2c, + 0xd4,0x7e,0xd0,0xc0,0x7b,0x5f,0xaf,0xe0,0xf3,0x27,0x5b,0x38,0x68,0xb4,0xb5,0xe9, + 0x13,0xc1,0xeb,0x1f,0x8c,0x8e,0x99,0xbe,0x69,0x21,0xe0,0xb6,0x3f,0x13,0x43,0x3, + 0xb8,0x7a,0x66,0x18,0xc5,0x84,0xcc,0x2,0xf9,0xb6,0xb9,0x7f,0x82,0xfb,0x2b,0xfb, + 0xa1,0xc2,0x83,0x84,0x26,0x97,0x92,0x49,0xea,0x14,0x6d,0x30,0x3d,0x2e,0xad,0x37, + 0xa5,0xb3,0xb4,0xf4,0x75,0x72,0x41,0x77,0x48,0x65,0x52,0x84,0xf3,0x93,0x55,0xfa, + 0xf6,0xa5,0x49,0xfc,0xe1,0x2b,0xb3,0xb4,0x30,0x51,0xc5,0x60,0xc4,0xb2,0xb5,0x5f, + 0x6c,0x68,0x94,0xf0,0xc5,0xcc,0xd8,0x3e,0x6c,0xe2,0x1f,0x3f,0x7b,0xca,0xbf,0xfa, + 0x6a,0x85,0x1f,0xae,0xed,0x73,0xb7,0x17,0x88,0x61,0x8a,0xd8,0x13,0x3d,0x18,0xe5, + 0x4,0x4b,0x97,0x21,0x30,0x47,0x93,0xe7,0xc9,0x3,0x6e,0x5c,0x68,0x9a,0xb4,0x22, + 0x86,0xcb,0x66,0x86,0x48,0x72,0x66,0x4f,0xbb,0xc4,0x48,0x29,0x85,0x99,0xd1,0x4a, + 0xd8,0xac,0xa8,0xfe,0xc8,0x4d,0xc0,0x1,0xee,0x2f,0xef,0xe2,0xee,0xd2,0x5e,0x28, + 0x55,0xf0,0xc4,0xc8,0x10,0x79,0x1f,0x84,0x93,0x56,0xf,0x9f,0x3d,0xde,0xc6,0xdd, + 0x95,0x7d,0x7c,0xff,0xfa,0xc,0xfe,0xf2,0xdb,0xe7,0x70,0x75,0x76,0xc8,0xcb,0x4a, + 0x8f,0x72,0x67,0xa2,0x67,0xc4,0x85,0xa9,0x1a,0x86,0x6,0xa,0x38,0x33,0x36,0x88, + 0xff,0xf3,0xbd,0x7,0xf4,0xc9,0x83,0x75,0xb6,0x83,0xa3,0xd6,0xf5,0x18,0x9e,0xb, + 0x43,0xe,0x87,0x24,0xc8,0xc3,0x81,0xf3,0x1e,0x20,0x3,0x92,0xdb,0x27,0x8c,0xb4, + 0x23,0x8d,0x51,0xc9,0x84,0xc5,0x84,0xa3,0xc4,0x74,0x6d,0xdc,0x4e,0x96,0xab,0xc8, + 0xbe,0x5b,0xba,0xa1,0xc8,0x4b,0xad,0x9c,0xf2,0x92,0x6e,0x63,0xbe,0x2f,0x2a,0xbe, + 0x2e,0x23,0x44,0x86,0xda,0x24,0x77,0x55,0x69,0xbb,0x1a,0x8b,0x40,0x8f,0xa4,0x95, + 0x7a,0x19,0x58,0x52,0xed,0xc3,0x96,0xf3,0xe4,0xf,0x12,0x14,0x16,0x74,0xdb,0xa9, + 0x53,0x4,0xbf,0xa7,0x8,0x51,0x5f,0xf9,0x58,0x32,0x1b,0x4,0xdc,0xe0,0x24,0x9e, + 0x87,0x32,0xcb,0xa1,0x83,0x1c,0xe4,0x1,0x9f,0x54,0xa0,0x77,0xb6,0x24,0x75,0x52, + 0x21,0xcb,0xd8,0xd2,0xd7,0x6c,0x2e,0xb9,0x2,0xe9,0xd0,0x15,0x83,0xc3,0x3b,0x8d, + 0x45,0x58,0xd3,0x95,0xf6,0x93,0x53,0x26,0x4a,0x55,0x8c,0x55,0xb2,0xfd,0xa5,0x74, + 0x8a,0xf0,0xee,0xcd,0x33,0xea,0x27,0xaf,0xcd,0xd1,0xab,0x67,0x27,0x68,0xb0,0x98, + 0xf5,0xf6,0xc3,0xbe,0x49,0x4c,0x7,0x4f,0x37,0xeb,0xf8,0xc7,0xcf,0x9e,0xe1,0x93, + 0x87,0x1b,0x78,0xba,0x7e,0x80,0x46,0xbb,0x17,0x4f,0xac,0xf1,0xe,0x6c,0x8a,0xf, + 0xda,0x56,0x6a,0x6d,0x48,0x57,0x52,0x2e,0x24,0x1a,0x25,0x92,0xcd,0x8f,0xf,0x85, + 0x4c,0xd4,0x4a,0xb8,0x30,0x5d,0x43,0x31,0x9b,0x4e,0x24,0xbf,0x98,0x7,0xea,0xa8, + 0xd1,0xc6,0xb3,0x8d,0x43,0xec,0x1f,0x9d,0x46,0xa6,0xce,0x84,0xac,0x5d,0x71,0xf3, + 0x95,0x72,0x19,0xbc,0xfb,0xca,0x2c,0xfe,0xfc,0xad,0x73,0x98,0x1a,0x2e,0x25,0x22, + 0x15,0xf2,0x7b,0x1d,0x1e,0xb7,0xf0,0x5f,0xbe,0x78,0x86,0xf7,0xef,0xac,0xe2,0xfe, + 0xf2,0x1e,0xea,0xcd,0x36,0x8c,0xc7,0x0,0x29,0x65,0xf,0x98,0x7e,0x91,0x8c,0x64, + 0x21,0xd6,0x8,0x4a,0xc5,0x7e,0x92,0x85,0xf6,0x72,0xb7,0x4d,0x99,0xee,0x1c,0xc3, + 0x23,0x54,0x85,0xa9,0x29,0x6,0x77,0xe3,0xc8,0xfe,0x1a,0x62,0xa8,0xb3,0xbb,0x1e, + 0x86,0x49,0xce,0xa4,0x8,0x73,0xdd,0xde,0xa5,0x2a,0x4a,0x47,0xa5,0x58,0x5a,0xb5, + 0xb0,0x2a,0x71,0xd3,0xa6,0xd7,0xd0,0x89,0xa0,0x18,0x44,0xa1,0x7e,0xc1,0x91,0xd0, + 0xe,0xc4,0xa1,0x94,0x6a,0x30,0x8f,0x1f,0xdd,0x3c,0x83,0x77,0xae,0x4e,0xe3,0xda, + 0xdc,0x8,0xaa,0xa5,0x9c,0x37,0x4d,0x46,0x8b,0x50,0x14,0x1e,0xde,0xad,0x37,0xf1, + 0xc9,0xa3,0xd,0xfc,0xec,0xd3,0x45,0x3c,0x5c,0xd9,0x83,0xcf,0xf1,0x8e,0xae,0x82, + 0xa2,0xeb,0xeb,0x38,0x7e,0x14,0x5a,0x60,0xb2,0x26,0x5e,0x15,0x70,0x69,0x66,0x8, + 0x3,0x85,0x8c,0x77,0x1f,0x44,0x7f,0xae,0xf5,0xfd,0x63,0x7c,0xf5,0x6c,0xb,0x87, + 0x8d,0x96,0xd3,0x23,0x47,0xd6,0x51,0xf6,0x5e,0xc,0x8d,0x21,0x21,0x47,0x11,0x52, + 0xc2,0xaf,0xda,0x41,0x35,0x9a,0x39,0x6b,0xe5,0xd9,0xcc,0x96,0x14,0x43,0x38,0x37, + 0x55,0xa1,0x4b,0x33,0x35,0x5c,0x9c,0xac,0x61,0x76,0xb4,0x4c,0x33,0xa3,0x65,0x4c, + 0xd,0xd,0x78,0xcd,0x50,0x3f,0xc2,0x58,0xbf,0xa6,0xe4,0xf3,0x27,0x9b,0xfc,0xe1, + 0xbd,0x75,0xbe,0xb7,0xba,0x87,0x95,0xed,0xe3,0x30,0xc7,0xdb,0x12,0xa4,0x4c,0x66, + 0x53,0xc0,0x96,0xb8,0x15,0x28,0xe3,0x48,0x6a,0xac,0x50,0xd8,0x37,0x22,0x12,0xc2, + 0x6b,0xc4,0x7c,0x1,0xc8,0xd9,0xbc,0xba,0xf2,0xc6,0x3a,0x56,0x32,0xc9,0x5e,0x1, + 0x44,0x9c,0xcb,0x66,0x68,0x6a,0xa8,0x84,0x19,0x81,0x2e,0x26,0x11,0x79,0x53,0x4a, + 0xe1,0xf1,0xc6,0x21,0x6e,0x3f,0xdf,0x41,0xa7,0xd3,0x13,0xa4,0x50,0xb6,0x5c,0xf1, + 0x28,0x32,0xdb,0x68,0x75,0xf1,0xfb,0xfb,0x1b,0x38,0x38,0x6e,0xd1,0xeb,0xe7,0xc6, + 0xf0,0xc6,0xf9,0x31,0xbc,0x7e,0x6e,0x3c,0x71,0x4a,0x4f,0x8a,0x5e,0x1d,0x1e,0xcc, + 0xe3,0xc6,0xfc,0x28,0x3a,0xbd,0x0,0x63,0xd5,0x2,0xfd,0xea,0xab,0x65,0x6e,0xb4, + 0xba,0x9e,0xe6,0xda,0xbd,0xf4,0x4a,0xd0,0xa5,0xad,0x76,0xc4,0x75,0xf9,0x46,0x63, + 0xcb,0x76,0x57,0xa2,0x57,0xb4,0x4c,0x8,0x98,0x8,0xca,0x8e,0x98,0x8,0x33,0x1f, + 0x42,0x16,0x43,0xc0,0x4c,0x1e,0xd,0x51,0xff,0x8d,0x81,0xe9,0x3,0x8a,0x51,0xe9, + 0xfc,0xfb,0xdf,0xeb,0xdd,0x45,0x2e,0x9,0xbb,0x35,0xbb,0x2c,0xd4,0xe4,0xd3,0xd6, + 0x48,0xac,0xf0,0xac,0x64,0x8d,0x11,0x9f,0xc0,0xe5,0xeb,0x6a,0x55,0x20,0xca,0x1f, + 0xf2,0xe4,0xb1,0xa1,0xa4,0xec,0x4f,0x43,0xee,0x24,0x86,0x9c,0xa8,0xc5,0xac,0x81, + 0xdf,0x5d,0x8f,0x23,0xa5,0x6c,0x82,0xf9,0xaa,0x84,0x10,0xce,0x5e,0x8,0xe5,0x82, + 0x35,0x84,0x25,0x5e,0x38,0x65,0x8b,0x63,0x51,0x59,0x7b,0x34,0x92,0x3c,0x77,0x39, + 0xa9,0xeb,0x7f,0x23,0xd2,0xd4,0x48,0xec,0xd2,0x25,0x4,0xef,0xc8,0x73,0x8e,0x19, + 0xaf,0x8f,0x5d,0x72,0xb1,0xa8,0xe5,0x42,0x96,0x2e,0xcc,0xd4,0xe8,0xa7,0x6f,0x2c, + 0xd0,0xf,0x6f,0x9c,0xb1,0xce,0x6f,0x49,0x85,0xab,0x71,0xda,0xc1,0xa3,0xb5,0x7d, + 0x7c,0x78,0x6f,0xd,0x7f,0xf7,0xc9,0x33,0x6c,0x1f,0x36,0xe1,0x59,0xda,0x79,0x19, + 0x88,0x7a,0x79,0xa6,0x84,0x56,0x34,0x7a,0x9d,0x8c,0x26,0xd1,0x9b,0xe2,0x15,0x4c, + 0xb8,0x8f,0x70,0xd4,0xd1,0x15,0x47,0xb0,0x77,0x89,0x30,0x5e,0x2b,0x61,0x7e,0xbc, + 0x82,0x5c,0xb6,0xff,0x84,0xc4,0xcc,0xd8,0x3c,0x38,0xc1,0x93,0xcd,0x3,0x34,0xbb, + 0x3d,0x2f,0xf1,0x5a,0xf2,0xec,0xa2,0x2c,0xcb,0xc1,0x52,0x16,0xd7,0xe7,0x46,0xf0, + 0xee,0x2b,0xb3,0xb8,0x3e,0x37,0xf2,0x42,0x9b,0xcb,0x20,0x8,0xb0,0x7b,0x74,0x8a, + 0x5b,0x8b,0xdb,0xf8,0xbb,0x8f,0x9f,0xe1,0xd6,0xe2,0xb6,0x67,0xb,0x6c,0xa9,0x5d, + 0xfc,0x4d,0x7e,0xe4,0x86,0xa6,0xec,0xec,0x73,0xb4,0x35,0x13,0xec,0xc0,0x62,0xd8, + 0x15,0x6c,0x12,0x13,0xbd,0x69,0x3b,0xbc,0xc5,0x52,0x7a,0xd,0x20,0x26,0xd,0xc1, + 0x43,0xd1,0x29,0x9c,0x51,0xed,0x88,0x75,0x37,0x24,0xf2,0x59,0x4a,0x1e,0x4b,0xdd, + 0xa3,0x5e,0x27,0xb2,0x42,0x3c,0x39,0x94,0x73,0x7b,0x92,0x76,0xca,0x62,0x19,0x1a, + 0xa5,0x74,0x9b,0x7,0xbf,0x90,0x4d,0x61,0xa2,0x56,0xc2,0x2b,0xf3,0x23,0xf8,0xf3, + 0xb7,0xce,0xe1,0xda,0xdc,0x88,0xd7,0xc,0xf5,0x2b,0xe4,0xf2,0x30,0xad,0x9f,0xb4, + 0xf0,0xf9,0xd3,0x2d,0xbc,0x7f,0x67,0x15,0xb7,0x16,0x77,0x90,0x64,0x8d,0x47,0xae, + 0x72,0x33,0x13,0x49,0x53,0x4e,0x48,0x3b,0x66,0xfb,0x3c,0xc0,0xc9,0x26,0xc7,0xaa, + 0x25,0x9c,0x9d,0xa8,0xa0,0x98,0x4b,0xf7,0x8d,0xd2,0xc,0x95,0x15,0xd,0xdc,0x5e, + 0xda,0xc5,0x51,0xb3,0x1b,0x93,0xe3,0x48,0x7b,0x59,0x7b,0xf5,0x14,0x49,0x9b,0x6a, + 0xf6,0xd6,0x43,0xd2,0xbd,0x12,0x6e,0xf1,0x98,0xc9,0x2a,0x2a,0x64,0xd2,0x28,0xe4, + 0x32,0x98,0x1e,0x2e,0xe1,0xb5,0x73,0xa3,0xf8,0xd6,0xf9,0x49,0xba,0x76,0x66,0xc8, + 0x1a,0xf0,0xf4,0x6b,0x38,0x92,0x9a,0x4c,0xd6,0xaa,0xe5,0x66,0xbb,0x83,0xf5,0xfd, + 0x13,0xdc,0x59,0xdc,0xe5,0x9f,0x7f,0xf5,0x9c,0x3f,0xb8,0xbb,0xa6,0x35,0x10,0xb6, + 0x5e,0xb0,0xce,0x7,0xb1,0xc6,0x26,0xa1,0x91,0x48,0x18,0xbb,0x69,0xa7,0x72,0x10, + 0x14,0x2,0x17,0xe6,0x21,0x3c,0xdc,0x49,0xbc,0x26,0x1c,0x65,0xa,0x1b,0xc7,0x42, + 0x7b,0x6e,0x93,0x33,0x4d,0x8c,0x30,0x3b,0x89,0x8,0x23,0xd5,0x2,0x46,0x6,0xb, + 0x31,0x62,0x5f,0xb4,0x89,0xa9,0x9f,0xb4,0xb0,0xb8,0x55,0xc7,0xf3,0xed,0xe3,0xf0, + 0x65,0x15,0x26,0x2a,0x49,0x4e,0xf1,0x7a,0x53,0x85,0xfd,0x46,0xb,0xbf,0x7f,0xb8, + 0xc1,0x9b,0x7,0xd,0x3a,0x6c,0xb4,0x91,0x52,0xa,0xf3,0x63,0x83,0x28,0xe5,0xd2, + 0xd6,0x68,0x4b,0xee,0xe8,0xa3,0xe4,0xb9,0xda,0x40,0xe,0xdf,0xbb,0x32,0x85,0x72, + 0x21,0x8b,0x83,0xe3,0x16,0xee,0x2c,0xed,0xa1,0xde,0x68,0x4b,0x18,0xc6,0x99,0x3a, + 0x28,0x68,0x44,0xdd,0xf0,0x61,0x8c,0xd5,0xa9,0x4e,0x42,0x64,0x43,0xf6,0x67,0x93, + 0xa5,0x68,0x2c,0x3c,0x2c,0x65,0x2d,0xac,0xe4,0xca,0xb8,0xc0,0x6b,0x5c,0x57,0xd7, + 0x23,0xcf,0x1,0xce,0x20,0x80,0xac,0xbf,0x3b,0xc7,0xf6,0xd9,0xec,0xf7,0xe6,0xa2, + 0x6e,0x9,0xf9,0x25,0x25,0x8d,0xed,0xec,0x79,0x4d,0x38,0x54,0x9b,0x84,0xe2,0x45, + 0x9,0xbc,0x9e,0x23,0xcf,0x7,0xc5,0xa6,0x2f,0xa2,0x88,0x4c,0x8a,0xe3,0x24,0xdf, + 0x74,0xd4,0x68,0x89,0x15,0xbc,0xe0,0x9,0xfb,0xd8,0x9,0xeb,0x67,0xbb,0xd1,0x91, + 0x7,0x98,0x80,0xed,0x59,0xc0,0x4,0x51,0x4e,0x80,0x99,0xcc,0x49,0x60,0x47,0xb6, + 0xbc,0x9b,0xf9,0xda,0xaa,0xb5,0x94,0xe6,0xa9,0x1b,0x80,0x1c,0x12,0x62,0x77,0x45, + 0x5a,0xe9,0xec,0x73,0x17,0x9f,0x4a,0x36,0xe7,0xdc,0xd0,0x3d,0x84,0x99,0xe7,0xcd, + 0xf3,0x63,0xf4,0xbf,0xfc,0xe4,0x3a,0x9d,0x9b,0xac,0x51,0x3a,0x9d,0xea,0xb,0x5b, + 0x1e,0x37,0xdb,0xb8,0xb3,0xb4,0x8b,0xbf,0xf9,0xe8,0x31,0x7e,0x7b,0x77,0xd,0x47, + 0x8d,0xb6,0x25,0x8f,0x40,0xb4,0x6b,0x96,0x58,0x4d,0x62,0xa7,0x41,0xf0,0xad,0x35, + 0x4d,0xd3,0xe3,0x64,0x4f,0x8e,0xd9,0x41,0x88,0xeb,0xfa,0xd,0x1a,0x62,0x47,0xd2, + 0xf0,0xc5,0x1c,0x1e,0x2c,0x60,0x76,0x64,0x0,0x99,0xc8,0x1e,0x30,0xfa,0xb6,0x5d, + 0x3f,0xc5,0xd2,0xd6,0x11,0x5a,0x9d,0x9e,0xcd,0xb5,0x91,0xf4,0x5a,0xdf,0xaf,0x3d, + 0x5c,0xc9,0x5d,0x9e,0x19,0xc6,0xff,0xf4,0xe3,0x6b,0xb8,0x3c,0x33,0x9c,0x58,0x30, + 0x64,0xe1,0x68,0xb4,0x7a,0xf8,0xd9,0xa7,0xcf,0xf0,0xb7,0x1f,0x3f,0xc3,0xca,0x4e, + 0x3d,0xa1,0xf8,0x19,0x61,0x28,0x7b,0x93,0x65,0x62,0x3d,0x57,0xae,0x61,0x61,0xf8, + 0x6b,0x69,0x8,0xbf,0x29,0xf6,0x43,0x83,0xdd,0xe0,0xb,0x61,0xba,0xcc,0x1c,0x93, + 0x7b,0x98,0xde,0x40,0x66,0x6,0xc1,0xda,0x7e,0x8a,0xf8,0xae,0x98,0xd8,0x3c,0xd2, + 0xb3,0x7b,0xf,0xa8,0x6f,0xc8,0x24,0xc4,0xed,0x24,0xfd,0xac,0x29,0x42,0x65,0xa6, + 0x3e,0x1c,0x89,0x7c,0x36,0x8d,0xd7,0xcf,0x8d,0xe1,0x87,0x37,0xcf,0xe0,0x3b,0x97, + 0x26,0x30,0x32,0x58,0x78,0x69,0x1f,0x6e,0x67,0xb1,0xda,0xc6,0xad,0xe7,0xbb,0xf8, + 0x8f,0x1f,0x3e,0xc1,0x67,0x8f,0x37,0x19,0x91,0xe7,0x94,0x24,0xc9,0xc3,0x99,0x67, + 0x70,0xd4,0x42,0xce,0x47,0xd2,0x24,0xe9,0x87,0x31,0x52,0x29,0x60,0x6e,0x74,0x30, + 0xc6,0x8b,0xf0,0x8b,0x27,0x63,0x65,0xf7,0x8,0x8f,0x56,0xf,0xf5,0x4a,0xa5,0x1f, + 0x1f,0x84,0x7c,0x77,0x3d,0xd2,0xa6,0x9b,0xc2,0xfe,0x4f,0xc6,0x6d,0xca,0x9,0x97, + 0x40,0x98,0x1f,0xab,0xe0,0xf5,0x73,0x63,0x78,0xf3,0xfc,0x18,0x9d,0x9d,0xa8,0xa2, + 0x5c,0xc8,0xa2,0x94,0x4b,0x23,0x9f,0x4d,0x7b,0x4d,0xe4,0x8b,0xae,0x63,0xf4,0xe3, + 0xcd,0x76,0x7,0xbf,0xbe,0xbd,0xc2,0x1f,0xdc,0x5b,0xe3,0xaf,0x9e,0xed,0x60,0xe7, + 0xb0,0xc1,0x6c,0xd3,0x93,0x8d,0x37,0x81,0x2d,0xae,0x76,0xcc,0x13,0x5e,0x70,0x66, + 0x8b,0x61,0x16,0x96,0xc6,0xa1,0xdc,0xd2,0x0,0x3c,0xa2,0xa6,0x15,0x72,0x58,0x6b, + 0x29,0x93,0x28,0x67,0x97,0xaa,0xe1,0x8f,0x2f,0x27,0x35,0xb7,0xb9,0x1f,0x2a,0xe7, + 0xe9,0xe2,0x64,0xcd,0xdb,0x6f,0x27,0xbd,0x2e,0xcd,0x76,0x17,0x8b,0xdb,0x75,0x6c, + 0xed,0x37,0xd,0x2a,0x62,0x29,0xf8,0xd1,0x15,0xa9,0xbb,0x36,0xbe,0x9f,0xc8,0xf2, + 0xce,0x31,0xff,0xe7,0xcf,0x17,0x71,0xe7,0xf9,0x2e,0x7e,0x74,0x73,0x96,0x7e,0xfa, + 0xfa,0x9c,0xd7,0x48,0x44,0x51,0x1,0xf9,0x56,0xc8,0x65,0x70,0xed,0xcc,0x30,0xfe, + 0xd7,0x3f,0xb9,0x41,0xff,0xf0,0xe9,0x22,0xff,0xa7,0x8f,0x9e,0xa0,0xd9,0xe9,0xb9, + 0x25,0xb4,0xfd,0xe6,0x21,0xc2,0x21,0x21,0x6c,0xe,0x34,0x5e,0xa6,0x39,0xdb,0xa2, + 0xf1,0x93,0x72,0x6f,0x72,0x91,0x30,0x76,0xca,0xd7,0x4f,0x61,0x4a,0xe6,0x8c,0x7a, + 0xe9,0x2a,0x60,0x62,0x65,0x88,0x76,0x22,0xef,0x31,0xbc,0xdd,0x89,0x59,0x88,0x66, + 0x4c,0xe6,0x23,0xc1,0x33,0x79,0xf7,0x14,0x21,0x2e,0x50,0x54,0x9,0x35,0x7,0xc7, + 0x39,0x4b,0x4c,0x82,0xdc,0xe7,0x88,0xc8,0xde,0x75,0x24,0x3f,0x97,0xd5,0x23,0xc9, + 0x11,0x83,0xa3,0x1e,0xd6,0xc,0xa4,0xa1,0x28,0x12,0xf7,0x26,0xe8,0x77,0xe4,0x3f, + 0x54,0x9e,0xce,0x42,0x79,0x78,0xba,0xc7,0xc,0x96,0x9f,0x6f,0x8b,0xb3,0x27,0x51, + 0xb3,0x7,0x39,0x59,0x2c,0x5e,0x1e,0xa8,0xfa,0xe3,0xa4,0xdc,0x44,0xee,0x4f,0xe5, + 0x32,0x42,0xd5,0x8d,0xe4,0xb0,0x30,0xbb,0xd1,0x31,0x39,0x27,0x19,0x6,0x21,0x93, + 0x22,0xbc,0x7e,0x6e,0x5c,0xfd,0xf8,0xe6,0x1c,0x5d,0x9f,0x1b,0xa1,0x6c,0x26,0xdd, + 0x97,0x21,0x6c,0xa6,0xcf,0x5f,0xdf,0x5a,0xc6,0x27,0xf,0x37,0x71,0x64,0xf6,0x90, + 0xba,0x9b,0x32,0xdb,0xe,0xd6,0x1e,0xc5,0x96,0xfb,0x4f,0xec,0xfb,0x54,0x4b,0x2b, + 0x50,0x99,0x6c,0x17,0xe1,0x7a,0x32,0x92,0xfc,0x4b,0x84,0xc2,0x5f,0xff,0xfa,0x83, + 0xc5,0x1c,0x46,0x2a,0x45,0x64,0xd2,0xc9,0x6,0x37,0xe6,0x63,0x7b,0x47,0xa7,0x58, + 0xdd,0x3b,0x41,0x5b,0x48,0xd5,0xe4,0x1a,0xc0,0x13,0x2a,0x29,0xc2,0xcd,0xf9,0x61, + 0xfc,0xe0,0x46,0x38,0x99,0xcb,0x4c,0xf7,0xa4,0xa2,0xbe,0xb2,0x7b,0x8c,0x8f,0xee, + 0xaf,0xe1,0x57,0xb7,0x57,0xf0,0x78,0xfd,0x20,0xe1,0x28,0x70,0x3b,0x5a,0x49,0xa0, + 0xeb,0xbb,0xf7,0x85,0x2f,0x31,0xa,0x7b,0x6a,0x66,0x6f,0x73,0x25,0x14,0x76,0x7e, + 0xaa,0x34,0x3b,0x82,0x36,0x8b,0x3d,0x31,0xc7,0x95,0x69,0xf6,0xb1,0x54,0x4c,0x5e, + 0x2b,0x64,0x98,0x1c,0x64,0x4b,0x9c,0xc7,0xb7,0x88,0xb5,0x4d,0x9e,0xac,0x4d,0x90, + 0x77,0x98,0xbc,0xe9,0x93,0x45,0xc7,0x2e,0x7f,0x11,0xf9,0xa,0x67,0xd2,0xa,0x67, + 0x46,0x6,0x71,0x7d,0x6e,0x8,0xdf,0xba,0x30,0x8e,0xd7,0xcf,0x8d,0x63,0x72,0xc8, + 0x5f,0x75,0xc4,0xa7,0x48,0x8e,0xc9,0xa9,0xb6,0xf,0x9b,0xf8,0xfc,0xc9,0x26,0xde, + 0xbb,0xb3,0x8a,0x3b,0x8b,0x3b,0x1c,0xf6,0x71,0xe4,0x11,0x6c,0x84,0xab,0x72,0xa4, + 0xcb,0x37,0x9,0x38,0x7a,0x15,0x69,0x36,0x8b,0x2,0x27,0x49,0xa5,0x80,0xb1,0xc1, + 0x22,0x46,0x2b,0x5,0x3b,0x95,0x25,0x21,0x4,0xad,0x4e,0x17,0x6b,0x7b,0x27,0x58, + 0xdb,0x6d,0x84,0x32,0x49,0x22,0x4b,0x44,0x72,0x7d,0xa9,0xf2,0xf8,0x8a,0x1c,0x2b, + 0xd5,0xd6,0xec,0x14,0xc2,0x82,0x7,0xd5,0x81,0x1c,0x46,0xcb,0x5,0x1a,0xaf,0x16, + 0x78,0xbc,0x56,0xa2,0xf9,0xf1,0x41,0x5c,0x98,0xac,0xe0,0xf2,0x74,0xb8,0xdb,0x8d, + 0xed,0x8c,0x5f,0xb0,0x9e,0x88,0x23,0x5a,0xd,0x3c,0xdf,0xaa,0xf3,0xc3,0xd5,0x3, + 0x7c,0xf2,0x68,0x93,0xef,0x2e,0xef,0xf2,0xee,0xf1,0x29,0x10,0x68,0x83,0x12,0x98, + 0x28,0x31,0xeb,0xcc,0xc3,0xcc,0x9a,0x90,0x69,0x5c,0xc7,0x5d,0x4f,0xca,0xee,0xf0, + 0x64,0x20,0x20,0x76,0x16,0xb0,0xd6,0xe9,0xc8,0x8d,0x80,0x4e,0x58,0x4b,0x1a,0xc1, + 0x63,0x8f,0xbc,0xa9,0x44,0x77,0x43,0x9e,0x25,0xd,0x86,0x7,0xb,0xb8,0x38,0x5d, + 0x45,0x39,0xe2,0x20,0x18,0x5d,0x23,0xec,0x1c,0x36,0x71,0xfb,0xf9,0x2e,0x76,0x8e, + 0x9b,0x2,0xa7,0x61,0xcf,0x91,0x4c,0xa7,0x91,0x2,0x51,0x77,0x32,0xfd,0x7e,0x8f, + 0x81,0xdd,0xa3,0x36,0xf6,0x8e,0x77,0xc1,0xcc,0xdc,0xee,0x6,0xf4,0xda,0xd9,0x11, + 0x9c,0x9f,0xa8,0xa1,0x5c,0xcc,0x24,0x9e,0x47,0xf2,0x4c,0x2d,0x17,0xb2,0xb8,0x7e, + 0x66,0x18,0xa7,0xed,0x2e,0x75,0xba,0x3d,0xfe,0xf8,0xd1,0x16,0xad,0xec,0x1c,0xb3, + 0x97,0xe8,0x12,0xda,0x18,0x5a,0x52,0x6b,0x38,0xc0,0xea,0x28,0x36,0x97,0xe3,0x23, + 0x7c,0xf7,0x34,0xe1,0x26,0xc5,0xa4,0xa3,0x5a,0x48,0x60,0xe2,0xa4,0xbd,0x21,0x6c, + 0x6d,0xd1,0xe0,0xa,0xb3,0x87,0x8f,0x28,0x32,0xd2,0x18,0x2,0xc9,0x72,0x1b,0xf1, + 0x55,0x31,0xba,0x4,0x81,0xcd,0x19,0x62,0xb0,0x52,0xfe,0x99,0xa3,0x64,0x2d,0xa5, + 0x38,0xb7,0x46,0xd8,0xb6,0x42,0x4,0xae,0x58,0x79,0xb8,0x4a,0x6e,0x3a,0x29,0xc2, + 0x67,0xf6,0x82,0x20,0x15,0x90,0x86,0x6d,0x7b,0x64,0x27,0x2c,0x1a,0x76,0x6b,0x68, + 0x1d,0xd9,0x2e,0x90,0x8b,0x91,0xb4,0x16,0x98,0x66,0x77,0xaa,0xc9,0x36,0x91,0x9c, + 0x19,0x37,0x24,0x29,0x31,0x7b,0x91,0xdb,0x33,0xda,0x58,0x4b,0xd2,0x36,0x95,0x21, + 0x35,0x9d,0x4c,0x26,0xac,0x22,0x7f,0xda,0x86,0xa,0xf1,0x7a,0xf6,0x48,0x70,0x6e, + 0xdf,0x4e,0x22,0x7f,0x94,0x40,0x34,0x35,0x3c,0x40,0xff,0xf6,0x7b,0x17,0xe9,0xdb, + 0x17,0x27,0x28,0x1a,0x5b,0x29,0xdf,0x4e,0x4e,0x3b,0xf8,0xfd,0x83,0x75,0xfc,0xd3, + 0x97,0xcf,0xf1,0xfe,0x9d,0x55,0xbb,0x94,0x95,0x7,0xba,0xf9,0xcd,0x28,0xe6,0x12, + 0x44,0x11,0x30,0x35,0xce,0x6f,0xa7,0x4,0x6c,0xcb,0x4b,0x9c,0xe6,0xf8,0xee,0xdd, + 0x7c,0xbc,0x94,0xcf,0xa0,0x5a,0xca,0x23,0xdd,0xa7,0x40,0x9a,0x7,0xea,0xb0,0xd1, + 0xc6,0xe6,0x7e,0x13,0xdd,0xe,0x27,0x12,0xee,0x8,0xae,0x4b,0x1d,0xab,0x14,0xf0, + 0x57,0xdf,0x39,0x8f,0x77,0xae,0x4e,0x21,0x2b,0x22,0x22,0x63,0xba,0xf1,0x5e,0x80, + 0x23,0x7d,0x6d,0xfe,0xb7,0x9f,0xdf,0xc3,0xfa,0xfe,0x89,0xb3,0xaf,0xb4,0xcd,0x9d, + 0x6f,0x5f,0xfb,0x12,0xe3,0xa5,0xb5,0xfa,0x35,0xfe,0x4c,0x1e,0xaf,0xc3,0xf5,0xaa, + 0x6c,0x73,0x26,0x95,0x98,0x8f,0x94,0xf3,0x6e,0x14,0x38,0xa1,0x6b,0xae,0x9c,0x6, + 0x58,0xba,0x3b,0x90,0x62,0x92,0x97,0x96,0xd8,0x4,0x7,0x90,0xf7,0x4,0x91,0x67, + 0xee,0x43,0xee,0x3e,0x76,0xfa,0x78,0xe5,0x9,0x4,0x22,0x23,0x83,0x98,0x47,0xe3, + 0x42,0xb0,0x4c,0x9a,0x30,0x37,0x56,0xc1,0xbf,0xfe,0xce,0x39,0x7c,0xf7,0xf2,0x4, + 0xa6,0x86,0x4a,0x48,0xa7,0x52,0x7d,0xbd,0xf8,0x13,0x1f,0x70,0x22,0x6c,0x1f,0x36, + 0xf0,0xe1,0xfd,0x75,0xfc,0xc3,0x67,0xcf,0xf8,0xe3,0x47,0x5b,0x62,0xa5,0x42,0x1e, + 0x1c,0x68,0x25,0x43,0x24,0x90,0x37,0x8a,0xac,0xb,0x6c,0xeb,0x44,0x16,0x8d,0x22, + 0x0,0x3,0x85,0xc,0x2e,0xce,0xd4,0x30,0x5e,0x29,0xbd,0xf0,0xe7,0x3a,0x6a,0x76, + 0xf0,0xe5,0xd3,0x6d,0xac,0xee,0x9d,0xf8,0x8e,0x74,0x88,0x6,0xd7,0x44,0x9e,0x5, + 0x16,0x87,0x9c,0xf7,0x1c,0x84,0xc0,0xf5,0x44,0xad,0x48,0x57,0x66,0x86,0xf0,0xfa, + 0xf9,0x51,0xbc,0x32,0x37,0x4c,0x17,0x26,0xab,0xd6,0xb0,0x28,0xc9,0xa6,0x34,0xaa, + 0x25,0x7f,0xd1,0xdb,0xd6,0x41,0x3,0x1f,0xdd,0x5f,0xe7,0x5f,0xde,0x5e,0xe1,0xdf, + 0x3f,0xdc,0xe4,0x76,0xb7,0xa7,0xb9,0x41,0xc4,0xb6,0x98,0xb2,0x9e,0xce,0xd9,0xb2, + 0xf0,0x38,0xcc,0xf4,0xa,0xcc,0x7a,0x40,0xb,0x9f,0xad,0xff,0x10,0x1b,0xe8,0x27, + 0xd0,0xb1,0xa0,0xac,0x44,0x5f,0x15,0x39,0x95,0xb5,0x34,0xcb,0x92,0x33,0x6d,0xef, + 0xc5,0x11,0x84,0x82,0x7c,0x93,0x92,0xe1,0x72,0x1,0xe7,0x27,0x6b,0x24,0x3d,0xfe, + 0xa3,0xd7,0x83,0x99,0xb1,0xb6,0xdf,0xc0,0x57,0x8b,0x3b,0x38,0x38,0xe9,0x98,0xf0, + 0x11,0x7b,0xef,0x92,0xaf,0xe1,0xb0,0x8c,0x15,0x42,0xd4,0x8b,0xdc,0x29,0xf1,0x6e, + 0x2f,0xef,0xd3,0xe3,0x8d,0x23,0xfe,0xa3,0xd7,0x66,0xf1,0xa3,0x1b,0x3d,0x7a,0xfd, + 0xec,0x8,0x8a,0xf9,0x6c,0x8c,0x0,0x9b,0xf4,0x1a,0xbc,0x7e,0x76,0xc,0xd3,0xc3, + 0x3,0x94,0x4d,0xa7,0xf8,0xe7,0x5f,0xad,0x60,0xef,0xe4,0x34,0xb4,0x65,0x37,0x84, + 0xa,0x61,0xbf,0x2a,0xa6,0x59,0xb2,0xeb,0xa,0xf3,0x48,0x6,0xc2,0xd8,0x92,0xad, + 0x9f,0xb3,0xa6,0xc1,0x83,0x10,0xe8,0x7d,0x92,0xdb,0x0,0xea,0x52,0xa5,0x1b,0x6, + 0x17,0xe5,0xcd,0x8c,0x20,0x2e,0x19,0x26,0x10,0x82,0x4,0x7,0x15,0x12,0xc4,0x35, + 0xd1,0x23,0xc7,0x26,0x66,0x81,0x70,0x78,0xe3,0x87,0x40,0x66,0x4d,0x31,0xf7,0xa0, + 0x7b,0x69,0xf9,0xad,0xa4,0x76,0x1f,0x7d,0xa5,0x70,0x6,0x19,0x4f,0x4b,0xa3,0x9, + 0xa9,0x40,0xf5,0x74,0x7c,0x88,0x49,0x7a,0x63,0x32,0x1b,0x5f,0xf5,0xe3,0x24,0x24, + 0xc4,0x14,0xd5,0xea,0x46,0x71,0x1d,0x67,0xcd,0xa8,0x9c,0xe8,0xc8,0xad,0xc1,0xf5, + 0x97,0x53,0x2e,0x21,0x8d,0x48,0x85,0x3b,0x13,0xc1,0x7e,0x37,0xe3,0x30,0x91,0x74, + 0xfc,0x70,0xc7,0xf2,0xd5,0xd9,0x61,0xfa,0xd1,0xcd,0x59,0x75,0x6d,0x6e,0x84,0xaa, + 0xc2,0x2a,0x35,0x7a,0x10,0x2c,0x6e,0x1e,0xe2,0xf7,0xf,0x37,0xf0,0xcb,0x5b,0xcb, + 0xb8,0xb7,0xb2,0xe7,0x35,0x2f,0xec,0xc5,0xa,0xf8,0xee,0xf7,0x42,0x38,0xe8,0x35, + 0x32,0xa,0xc9,0xe,0x40,0x89,0x1d,0x97,0x79,0x10,0x85,0xa7,0x8c,0x7,0x1f,0x2b, + 0x20,0x9b,0x49,0xa3,0x98,0x4b,0x79,0xbb,0xab,0xa4,0xc3,0xbe,0x7e,0xd2,0xc2,0xf6, + 0x51,0x33,0xcc,0x1a,0xb7,0x12,0xf,0x1,0x47,0xeb,0x1b,0xe9,0xfc,0x64,0xd,0x3f, + 0xbc,0x3e,0x83,0x57,0xcf,0x8e,0x5a,0x7f,0x76,0x9,0x91,0xcb,0x83,0x71,0xeb,0xb0, + 0x81,0xbf,0xfd,0xe4,0x29,0xde,0xbb,0xb3,0x8a,0x4d,0xe3,0x2,0x45,0x11,0x2b,0x4b, + 0x2f,0x95,0xf2,0xa5,0x2a,0xba,0x34,0x2d,0x72,0x97,0x47,0x8b,0x84,0x49,0x3f,0x54, + 0x61,0xec,0x69,0xe0,0x5a,0x1b,0xa5,0x75,0x6f,0xb0,0x99,0x2e,0xd2,0xd5,0xc0,0xad, + 0x3f,0x84,0xa8,0x55,0x8e,0xf8,0x7e,0x27,0x46,0x4e,0xa0,0xe2,0x21,0xe2,0xce,0x6c, + 0xd8,0xde,0x2f,0xb2,0xa1,0x25,0x5f,0x86,0x65,0xfb,0x70,0x17,0xe1,0xe2,0x91,0xe0, + 0x4c,0x3,0x3c,0x50,0x48,0xe3,0x95,0xb9,0x11,0x5c,0x3f,0x33,0x8c,0x2b,0xb3,0x43, + 0x38,0x37,0x59,0xc1,0x44,0xb5,0x88,0x74,0x4a,0x25,0x12,0x33,0xfb,0x91,0xe1,0x82, + 0x80,0xf1,0xd5,0xe2,0x36,0x3e,0x7e,0xb0,0xc1,0x1f,0x3e,0xd8,0xc0,0xe3,0x8d,0x43, + 0xf9,0x44,0xda,0x9e,0x5a,0xf0,0x1,0x61,0x68,0x8,0xd1,0xae,0xdf,0x16,0x3,0x41, + 0x49,0x92,0x60,0x48,0x31,0x9b,0xc1,0xc5,0xa9,0x21,0x8c,0x55,0xa,0x89,0x64,0x28, + 0xf3,0x73,0x9f,0x9c,0x76,0xf0,0xe5,0xb3,0x1d,0xac,0xec,0x1e,0x87,0xc8,0x15,0xf9, + 0x51,0xcc,0x48,0x92,0xc3,0xb1,0xd8,0x49,0xea,0xcf,0x1f,0xaf,0x16,0x31,0x3d,0x5c, + 0xc2,0xf4,0xd0,0x0,0xcd,0x8e,0xe,0x60,0xb2,0x56,0xc4,0x44,0xb5,0x84,0xd1,0xc1, + 0x2,0x86,0x7,0xf3,0xc8,0x67,0xd3,0x7d,0xc3,0x43,0xe2,0x16,0xb4,0x41,0xac,0xc0, + 0xf4,0x7a,0x1,0x16,0xb7,0xeb,0xf8,0xea,0xd9,0xe,0xdf,0x7e,0xbe,0x8b,0x27,0xeb, + 0x87,0xbc,0xb4,0x7d,0xc4,0xda,0x7c,0xc9,0x16,0x6d,0x3b,0x1b,0xda,0x9b,0x4b,0xec, + 0xc8,0x55,0x18,0xf0,0xa1,0x33,0x3f,0x75,0xb1,0x37,0x77,0x32,0x33,0x3b,0x5f,0xe9, + 0xc8,0x6d,0xc5,0xf6,0x79,0x26,0x37,0xa1,0xbb,0xb0,0x15,0xa1,0x7b,0x32,0x70,0x3e, + 0x45,0x2d,0x68,0x42,0xa9,0x15,0x86,0x7,0xf3,0xb8,0x38,0x5d,0x43,0xa5,0x98,0x4d, + 0xb4,0x65,0xb5,0x4,0xbf,0xc3,0x26,0xee,0x3c,0xdf,0xe3,0xfa,0x49,0x5b,0x38,0x2c, + 0x7b,0x44,0x3d,0xf6,0x4d,0x8d,0xc8,0xf7,0x8b,0x8f,0xb3,0x43,0xf9,0xb4,0xd3,0xc5, + 0x7,0xf7,0xd7,0x69,0xef,0xb8,0xc5,0x8b,0x5b,0x75,0x7c,0xfb,0xe2,0x4,0x5d,0x9c, + 0xaa,0xf6,0x85,0xde,0xcd,0xc7,0x53,0x29,0x85,0x89,0x6a,0x9,0x7f,0xf1,0xd6,0x59, + 0x1a,0xab,0x96,0xf0,0xf7,0x9f,0x2e,0xf2,0xb3,0xad,0x7a,0x18,0x8d,0xc2,0xec,0xd4, + 0x89,0xe4,0x94,0x54,0x82,0xfb,0xc3,0x16,0x9c,0xd6,0xfc,0x2b,0xe,0x8c,0xde,0x81, + 0x4c,0xd1,0xf,0x27,0x42,0x15,0x10,0x3,0x4a,0x11,0x5,0x41,0xa0,0x97,0xb8,0xf6, + 0x65,0x32,0xd3,0x3a,0x73,0x0,0x2,0x21,0x15,0x7e,0x5c,0x2b,0xe2,0x64,0x36,0x83, + 0x19,0x78,0x39,0x26,0xf2,0x8b,0x1e,0x5b,0x5e,0x6c,0x94,0x17,0x23,0xe5,0x73,0xe6, + 0x48,0xf0,0x7c,0xfc,0x26,0x57,0x92,0xee,0x3c,0xb1,0x13,0x9,0x8d,0x7c,0xa2,0xbe, + 0x34,0x3c,0x77,0xd2,0xc2,0xf6,0x2d,0xf2,0x98,0xf9,0xbc,0x7c,0xbb,0xc5,0x54,0x14, + 0x59,0x83,0xf9,0x1a,0x13,0xcf,0xdc,0x8c,0x9d,0x4f,0x1b,0xcb,0x4e,0x42,0x9f,0xb5, + 0xca,0x46,0x12,0xd8,0x94,0x72,0xa1,0x51,0x57,0x2e,0xa9,0x58,0x85,0x7c,0x64,0x29, + 0x65,0xb3,0xe6,0xaf,0x26,0xb8,0x56,0x59,0x1d,0x32,0xe9,0x8e,0x57,0x6f,0xf7,0x15, + 0x55,0x4b,0x19,0x7a,0xe7,0xca,0x14,0xfd,0xe8,0xe6,0x19,0x1a,0xaf,0x16,0x12,0x77, + 0xe6,0x0,0x70,0xd4,0x68,0xe3,0x93,0xc7,0x9b,0xf8,0xd9,0x67,0xcf,0x71,0xe7,0xf9, + 0xe,0x7a,0x7a,0x2,0x93,0x31,0x78,0x72,0x9,0xc1,0xec,0xdb,0x10,0xca,0x28,0x3c, + 0x4a,0xb8,0xe6,0x9e,0xac,0x21,0xe1,0x85,0x71,0xa6,0x67,0x9,0x45,0x4f,0x9f,0x31, + 0xd9,0x74,0xa,0x39,0xb1,0x2a,0xe8,0x3b,0x4d,0x33,0xa3,0xd7,0x83,0x75,0xc2,0x8d, + 0x86,0xbc,0x90,0x62,0x54,0xa,0x39,0x7c,0xef,0xea,0x14,0x7e,0xfc,0xda,0x19,0x4c, + 0xf,0xf,0xf4,0x8d,0x5b,0xec,0x76,0x43,0xf7,0xb7,0x4f,0x1e,0x6f,0xe1,0x67,0x9f, + 0x2d,0xe1,0xf9,0x76,0xdd,0xfd,0x4c,0xc2,0x5d,0xd0,0xb3,0x64,0x64,0x4a,0x30,0x32, + 0xe9,0xb3,0x43,0x97,0x2d,0x10,0xc9,0x6,0x89,0xbc,0xa4,0xcd,0xf0,0x26,0x61,0xfb, + 0x9c,0x23,0x61,0xd7,0x4b,0x42,0x7a,0x93,0xd0,0x7e,0x11,0x39,0xaf,0x5,0x91,0xae, + 0x19,0x6e,0x46,0x43,0x15,0x99,0x79,0xc,0x8d,0x37,0x82,0x88,0x73,0x53,0x2a,0x59, + 0x99,0x6e,0xb9,0x8b,0x2a,0xd2,0x31,0x1b,0xb6,0x3c,0x21,0x97,0x56,0x28,0xe4,0xd2, + 0x28,0xe5,0x32,0xb8,0x30,0x55,0xc5,0x1f,0x5c,0x9d,0xc2,0x9b,0xe7,0xc7,0xb4,0x97, + 0x0,0xbc,0x46,0x2a,0x4a,0x2c,0x8a,0x6a,0xa4,0x9b,0xad,0xe,0x8e,0x5b,0x5d,0x2c, + 0x6d,0xd5,0xf1,0x8b,0x5b,0x2b,0xfc,0xe1,0x83,0xd,0x2c,0x6e,0xd5,0xf5,0x66,0x4b, + 0xee,0x9f,0xed,0x99,0xcd,0x14,0x63,0xe5,0x93,0xb3,0x10,0x87,0x8b,0x7d,0xd4,0x50, + 0x3b,0xeb,0xf8,0x63,0xfb,0x74,0xf,0x14,0xb3,0xb8,0x30,0x55,0xc5,0x68,0xa5,0x10, + 0x2b,0x8e,0xf2,0xd0,0xde,0x3b,0x3e,0xc5,0xa3,0xf5,0x43,0x6c,0xd5,0x4f,0xdd,0x23, + 0xcc,0x11,0x88,0x51,0x9c,0x1f,0x29,0x2,0xb2,0xd9,0x14,0xb2,0x29,0x85,0x6c,0x26, + 0x85,0x5c,0x3a,0x85,0xf1,0x5a,0x1,0xb,0x63,0x83,0x38,0x3b,0x51,0xc1,0xc5,0xa9, + 0x2a,0xce,0x4d,0xc4,0x75,0xef,0xd2,0xa9,0x2c,0xba,0xd2,0x49,0x72,0x49,0x23,0x22, + 0x74,0xbb,0x3d,0xb4,0xba,0x3d,0x34,0xda,0x1,0x96,0xb6,0xe,0x71,0x77,0x79,0x9f, + 0x7f,0x71,0x6b,0x99,0xef,0x2e,0xed,0x71,0x2f,0x8,0xf4,0x48,0xed,0x18,0xc0,0xe4, + 0x4c,0xed,0x4c,0x45,0x67,0x2d,0x24,0x33,0x7e,0xe1,0x7a,0x30,0xb3,0x6c,0x2b,0x53, + 0x59,0xd8,0x62,0xd,0x3a,0x34,0xc8,0x7,0xf0,0x5c,0x28,0x8d,0x43,0x76,0x8,0x91, + 0xbc,0x6d,0x3b,0xa3,0x44,0x0,0x2d,0x66,0x61,0x9b,0x30,0x32,0x58,0xc4,0xa4,0x96, + 0xb0,0xca,0xb3,0x40,0x5e,0xa3,0x46,0xab,0x87,0xf5,0xdd,0x63,0x6c,0x1c,0x36,0x85, + 0xf4,0x2d,0xe2,0x5a,0x4e,0xca,0xdb,0xc5,0x3a,0x14,0x40,0xb9,0xd5,0x8b,0xd8,0x24, + 0x1b,0x1e,0xc9,0xce,0x51,0x9b,0x7f,0x7b,0x6f,0x3,0x5b,0x87,0x4d,0x6a,0x76,0xba, + 0x9c,0x4e,0x11,0x8d,0x57,0x8a,0x28,0x64,0x53,0xf6,0x3e,0x96,0xfc,0x19,0xf3,0x73, + 0x29,0x45,0xb8,0x34,0x5d,0x43,0xa5,0x98,0xa3,0x7a,0xb3,0x8d,0x4c,0x3a,0xc5,0xcf, + 0xb6,0xea,0x68,0x77,0x7a,0xce,0x2a,0x41,0x87,0xec,0x89,0xc,0xb,0x1d,0xaf,0x0, + 0x10,0x1b,0x47,0x18,0x52,0xa4,0x2,0x33,0x47,0x87,0x4d,0x7e,0x88,0xd9,0x12,0x2, + 0xa5,0x42,0x65,0x3d,0x93,0x49,0x5e,0x62,0x62,0xa2,0xc0,0x44,0xd1,0x6,0x21,0x4f, + 0xcb,0xc2,0xed,0x66,0x2,0x53,0xd6,0xe3,0x95,0x14,0x13,0xb4,0x4b,0x11,0x71,0x5c, + 0x16,0x1f,0x17,0x5e,0xfa,0x5c,0x11,0x73,0x7e,0x58,0x22,0xbc,0x6c,0x9,0x54,0x2, + 0xb1,0x4d,0x32,0xd8,0x25,0xf9,0x9d,0xe2,0xc6,0x32,0xce,0xf0,0x8a,0xad,0x50,0x3e, + 0x6d,0xed,0x18,0x13,0x88,0x11,0x12,0xfd,0x4f,0xb2,0x20,0x4d,0xfc,0x43,0x42,0xb0, + 0x14,0x0,0x50,0x4a,0x7e,0x29,0xf3,0x83,0x28,0x2f,0xc,0x84,0x64,0x4a,0xaa,0x72, + 0x9a,0x74,0x22,0x33,0xc6,0xb9,0xbd,0xb9,0xbd,0x33,0xb5,0x8c,0xc1,0xcc,0xea,0xe, + 0x4d,0x8,0xdf,0x19,0xaf,0x16,0xf0,0x83,0x57,0x66,0xe9,0x9d,0x6b,0xd3,0x34,0x27, + 0x12,0xd3,0xe4,0x41,0x9,0x0,0x7b,0x47,0xa7,0xf8,0xe2,0xe9,0x16,0xde,0xbf,0xb3, + 0x86,0xdb,0x4b,0x7b,0xe,0xc1,0x89,0x4d,0x9e,0xc,0xea,0xeb,0x49,0xfc,0x32,0xd5, + 0x8b,0xa3,0xa1,0x69,0x88,0xd6,0x2f,0x39,0xda,0x47,0x3,0x6e,0xd2,0x8a,0x5e,0xca, + 0xcf,0xbb,0x5c,0xc8,0xa2,0x56,0xce,0x61,0xeb,0xf0,0x54,0xf8,0x11,0x3b,0x7d,0xcc, + 0x64,0xb5,0x84,0x3f,0x7b,0x73,0x1e,0x7f,0x70,0x7d,0x1a,0x67,0xc7,0x2b,0x5e,0xce, + 0x76,0x14,0xb9,0xd8,0x6f,0xb4,0xf1,0xf,0x9f,0x3d,0xc7,0xdf,0x7d,0xba,0x88,0xcd, + 0xfd,0x86,0x7f,0xf0,0x70,0xdc,0x34,0xc1,0x39,0x80,0xd1,0x37,0x4f,0xe7,0x3a,0xca, + 0x4c,0x64,0xa,0x90,0x48,0xc7,0xb6,0xcc,0x3a,0x6d,0xfd,0x69,0x49,0xd0,0x6,0x93, + 0x71,0x1e,0xe8,0xc2,0x26,0x41,0x53,0x63,0x94,0x21,0xc4,0xbb,0xcd,0x18,0x39,0x8d, + 0xab,0x5,0xf1,0x42,0x5f,0x4,0x57,0xe0,0xed,0xb7,0x37,0xb7,0x9f,0xc5,0xe6,0xe1, + 0x5,0xa8,0x7a,0x2f,0xba,0xd2,0xc6,0xe7,0x4c,0x32,0x41,0x83,0x35,0xef,0x21,0x8b, + 0xab,0x33,0x35,0xbc,0x7a,0x76,0x14,0xd7,0xcf,0xc,0x63,0x66,0x64,0x0,0xe5,0x7c, + 0x6,0xc5,0xdc,0x37,0xc3,0xeb,0xd1,0x62,0xde,0xeb,0x5,0x78,0xbc,0x71,0x88,0xf7, + 0xee,0xac,0xf1,0x7,0xf7,0xd6,0xb0,0x79,0xd0,0xe0,0xe3,0xd3,0x8e,0xf6,0x5d,0x4f, + 0xda,0xd7,0x24,0x48,0xed,0xec,0x11,0x0,0x2f,0x2f,0xdc,0x19,0xf8,0x90,0x88,0xe0, + 0xe,0x7f,0xa4,0x52,0x2e,0x83,0xf3,0x93,0xd5,0x44,0xb2,0x9e,0x9,0xda,0x69,0xb4, + 0x3a,0x58,0xdd,0x6b,0x60,0xe3,0xa0,0xe1,0x9b,0x58,0xca,0xbc,0x67,0xf6,0x80,0x1d, + 0xd4,0xca,0x79,0x2c,0x4c,0xc,0xe2,0xfc,0x44,0x5,0x67,0xc7,0x6,0x71,0x6e,0xa2, + 0x82,0x6a,0x29,0x87,0x62,0x2e,0x8d,0x4c,0x5a,0x21,0x9b,0x4e,0x21,0x9f,0x49,0xf5, + 0x85,0x6f,0xfb,0x35,0xb4,0x51,0x2f,0x9,0x66,0x46,0xbd,0xd9,0xc1,0x9d,0xe7,0xbb, + 0xfc,0xfe,0xdd,0x55,0x3c,0x58,0x3d,0xe0,0xcd,0x83,0x26,0xd7,0x1b,0x6d,0xf4,0x58, + 0xeb,0xe4,0x2c,0x43,0x4b,0xd9,0x9,0xdb,0xa4,0xa3,0xd9,0xdd,0xb7,0x2d,0xdc,0xe1, + 0xa8,0xc7,0x60,0xe,0xf4,0x2e,0x43,0x53,0xe4,0x64,0xf4,0x88,0xdd,0xb9,0x7b,0xd6, + 0xbe,0xee,0xd9,0x92,0x7d,0xb0,0xcf,0xf8,0x24,0xb9,0x8e,0x62,0x2f,0xe8,0x83,0x10, + 0x1a,0xb6,0x4c,0xd6,0x8a,0x9e,0x1f,0x45,0xd2,0xb5,0x69,0xb4,0xba,0xb8,0xb3,0xb4, + 0x8b,0xa5,0xdd,0x23,0xb6,0x2e,0x88,0xc,0x9b,0x40,0x2f,0xa9,0x20,0x2e,0x85,0xde, + 0x1f,0x48,0x54,0x44,0xf9,0x20,0x58,0xf1,0xf6,0x3b,0x3f,0xdd,0x38,0xe2,0xc3,0xc6, + 0x33,0xdc,0x59,0x3a,0xc0,0x7f,0xf3,0xd6,0x2,0x7d,0xeb,0xfc,0x28,0x8a,0xf9,0x6c, + 0xcc,0x78,0x26,0xda,0x78,0x8c,0xe,0xe6,0xf1,0xdf,0x7d,0xff,0x22,0x4d,0xf,0x95, + 0xf0,0xff,0x7e,0xbc,0xc8,0x8f,0xd7,0xf,0xa8,0xdd,0xd,0x98,0x24,0xcc,0xe0,0x8, + 0xa6,0xc4,0x76,0x7f,0xcd,0x0,0xa5,0x8,0x1c,0x98,0xbd,0x1b,0x1,0x50,0x9c,0xa2, + 0x80,0x82,0xc0,0xc4,0x59,0x6a,0xb7,0x19,0xfd,0x77,0x8,0x2,0x2,0x11,0xa5,0xf4, + 0xa3,0xc9,0xca,0x23,0x7c,0x22,0x20,0x30,0x5,0x20,0x22,0x8d,0xd,0xea,0xfc,0x75, + 0x8d,0xbb,0xb0,0x8a,0x21,0xe2,0xa2,0x74,0x73,0x2,0x22,0x49,0x31,0x53,0x65,0xdf, + 0xda,0x5d,0x6,0x77,0x99,0x73,0x5f,0x5e,0x9f,0x8,0x1f,0x81,0x10,0x63,0xe1,0xdb, + 0x41,0x53,0xab,0xa4,0xd2,0x24,0x27,0xf4,0xc8,0xf,0xa9,0x38,0x61,0x2f,0x90,0x50, + 0xa0,0xa2,0x3d,0x89,0xf,0x3c,0x8,0x69,0xe,0x9,0xd1,0x29,0xc9,0x5d,0xbc,0xb2, + 0xb8,0x92,0x11,0x95,0xfa,0xbc,0x60,0x63,0xee,0xa1,0x5c,0x2,0x9b,0x25,0xc7,0x39, + 0x5b,0x29,0xcb,0x81,0x67,0x45,0xc,0x50,0x29,0x9f,0xa6,0x9b,0xb,0x63,0xea,0x47, + 0x37,0x67,0xe9,0xfc,0x44,0x85,0xa2,0x10,0x9c,0x3c,0x28,0x9f,0x6e,0x1c,0xe0,0xe7, + 0xb7,0x56,0x70,0x77,0x65,0x4f,0xd8,0xdc,0xc2,0x4f,0xc9,0x82,0x14,0x23,0xc6,0xd6, + 0x81,0x9e,0x7d,0x26,0x43,0x38,0x72,0x81,0x90,0xcb,0xa4,0x30,0x3d,0x5c,0xc4,0xdc, + 0xd8,0x20,0x4a,0xd9,0x34,0x2,0x6d,0xcd,0xba,0xb2,0x7b,0x8c,0x7,0xab,0x7,0x9, + 0xbb,0x76,0xd7,0x7d,0xc9,0xef,0xa2,0x52,0xea,0x1b,0xad,0x3f,0x1,0xe0,0xc2,0x74, + 0xd,0xef,0x5c,0x99,0xc2,0xef,0x1f,0x6f,0x61,0x6d,0xf7,0xd8,0xde,0x6c,0xa5,0x7c, + 0x1a,0xf3,0xe3,0x83,0x78,0xeb,0xe2,0x78,0x58,0xcc,0x85,0x73,0x56,0x14,0xd6,0x65, + 0x66,0x3c,0xdb,0xac,0xe3,0x37,0x77,0xd7,0xf0,0xfe,0xdd,0x35,0xac,0xee,0x9d,0xc4, + 0xbf,0xa1,0x22,0x2f,0xf1,0xcc,0x73,0x6f,0x79,0x99,0xb7,0xf0,0x35,0xd7,0x23,0x6e, + 0x84,0x89,0x63,0xb5,0xfb,0x52,0x9a,0xcf,0x20,0x12,0xa5,0xda,0x46,0x65,0xb3,0x4b, + 0x33,0xb5,0xc4,0x4d,0x6d,0x43,0x41,0x2e,0x79,0xd,0x66,0x93,0xc3,0x62,0xd5,0x23, + 0x4a,0x7c,0xa8,0x81,0xb6,0x52,0xba,0x44,0x9b,0x73,0x99,0x8c,0xc7,0x7e,0x5e,0x20, + 0x32,0x2a,0x85,0x4a,0x31,0x8b,0xa1,0x81,0x5c,0x48,0xe2,0xaa,0x14,0x30,0x51,0x2d, + 0x62,0x61,0x3c,0x2c,0x5a,0xf3,0x63,0x65,0x64,0xd2,0x71,0xff,0xf3,0xe8,0xc1,0x67, + 0xa,0xb9,0x79,0x9d,0x3b,0xdd,0x1e,0x9e,0xef,0x1c,0xe3,0xd1,0xea,0x3e,0x7f,0xf5, + 0x7c,0xf,0x9f,0x3d,0xde,0xe2,0xa7,0x9b,0xf5,0x78,0xd9,0x26,0x5,0xb6,0xb0,0xa1, + 0x30,0x97,0xe2,0x88,0x84,0x82,0x5d,0x58,0x8d,0x29,0x2f,0x92,0xa3,0x23,0x88,0xb9, + 0xac,0x14,0x61,0xac,0x5a,0xa2,0xa1,0x81,0x9c,0x57,0x58,0xe5,0x24,0xdc,0xb,0x7a, + 0x58,0xdc,0x3e,0xc2,0xe3,0xf5,0x3,0x34,0x5a,0x3d,0xb7,0xb3,0x17,0xd7,0xaf,0x98, + 0x4d,0xa1,0x56,0xca,0xa3,0xa6,0xaf,0xcd,0x70,0x39,0x8f,0xb1,0xc1,0x2,0xa6,0x86, + 0x4a,0x98,0x19,0x2e,0x61,0x6a,0x68,0x0,0x13,0x3a,0x29,0x2c,0x89,0x5c,0x15,0xf5, + 0x59,0x57,0x4a,0xd9,0x9f,0x21,0x69,0x45,0x64,0x56,0x0,0xdb,0xf5,0x26,0x56,0x76, + 0x8e,0xf9,0xe9,0x46,0x1d,0xf7,0xd6,0xf6,0xf9,0xd6,0xb3,0x1d,0xde,0x3c,0x6c,0x4a, + 0x1f,0x61,0x1d,0xce,0x43,0x6,0x54,0x84,0xe,0x5,0xf2,0xa,0xb9,0xa9,0x24,0x7a, + 0x95,0x6b,0xe8,0xd0,0x4c,0x61,0x84,0x10,0xb3,0x17,0xc1,0xc9,0xae,0xbc,0xfb,0xa3, + 0x80,0xd6,0x47,0xbb,0xa6,0x52,0xac,0x2a,0x5d,0xb2,0xab,0x78,0xc0,0x5d,0xaa,0xb4, + 0x4b,0xcb,0xcb,0x67,0x53,0x38,0x3b,0x59,0xa1,0xb1,0x4a,0xe1,0x85,0x32,0xc6,0x46, + 0xab,0x8b,0x5b,0x4b,0x7b,0x58,0xdc,0x3e,0x71,0xeb,0x62,0x33,0xa5,0x5b,0xa6,0xb7, + 0x62,0x47,0xcc,0xf3,0x2c,0xfb,0xac,0x68,0xd1,0xcb,0x20,0x21,0x8f,0x85,0x3,0x6, + 0xa8,0xcb,0x8c,0xad,0xc3,0x53,0x1c,0x9d,0x6e,0x71,0x3e,0x93,0xc2,0xde,0x71,0xb, + 0xaf,0xcc,0xf,0xd3,0xcc,0x70,0x9,0x39,0x7d,0xbf,0x47,0xa5,0xc1,0x44,0x84,0x54, + 0x4a,0x61,0xb8,0x9c,0xc7,0x5b,0x97,0x26,0xa8,0x13,0x30,0xde,0xff,0x3a,0xc3,0x5f, + 0x2f,0xef,0xd1,0xc9,0x69,0x2f,0x6c,0x95,0xec,0x18,0x4b,0x22,0x39,0x4f,0x93,0x14, + 0x41,0x6,0xed,0x20,0x50,0xa0,0x48,0xbb,0xd0,0xe8,0x74,0xcd,0x0,0xc,0xa,0x2, + 0x3b,0x22,0x42,0x27,0xe4,0x58,0xf,0x8a,0xc0,0x28,0x64,0x4d,0x7e,0x1a,0x59,0xeb, + 0x67,0x3d,0x3c,0x28,0x27,0xc4,0x62,0x31,0x4b,0x3b,0x43,0x55,0xe1,0xb5,0x26,0x7, + 0x45,0x80,0xa8,0xcf,0x90,0xe7,0xad,0x24,0x65,0xdb,0xeb,0x46,0x72,0x8a,0xc6,0x10, + 0x26,0x94,0x70,0xbf,0xee,0x3a,0x24,0x2a,0x2d,0xc9,0x33,0x3e,0xa9,0xc7,0x6f,0xdf, + 0xfa,0xd4,0x7c,0x1f,0x1b,0x48,0xd8,0x30,0x47,0x25,0x3f,0x96,0x29,0xae,0x9c,0x56, + 0xc8,0x14,0x70,0x9b,0xb5,0xe6,0xf8,0x70,0x5e,0x8e,0x1a,0x83,0xac,0x3c,0xd3,0xe8, + 0xdb,0xb5,0x9c,0x21,0x34,0x1b,0x70,0xe9,0x59,0x94,0xcf,0xa6,0xe9,0xe6,0xc2,0x28, + 0xbd,0x73,0x75,0x8a,0x5e,0x3b,0x3b,0xe6,0x85,0x30,0x48,0x78,0xae,0x17,0x4,0xd8, + 0x3b,0x6a,0xe1,0xab,0xe7,0xbb,0xf8,0xf5,0xed,0x55,0xb4,0xbb,0x81,0x85,0x99,0x5c, + 0x9c,0x24,0x7c,0xc9,0x17,0x39,0x12,0x18,0x4b,0x25,0x71,0x94,0x50,0xa8,0xaf,0x44, + 0x26,0xad,0x70,0x76,0x62,0x10,0x3f,0x78,0x65,0x6,0xff,0xea,0xf5,0x33,0x98,0x1c, + 0x1a,0x40,0xaf,0x17,0x60,0xbb,0xde,0xc4,0xdf,0x7d,0xba,0x88,0xc7,0xeb,0x75,0x74, + 0x83,0xa8,0x80,0x84,0x23,0x5,0x92,0xc5,0x83,0x4d,0x2f,0x4c,0x58,0x63,0x66,0xdc, + 0x98,0x1b,0x42,0x21,0x9b,0x42,0xb7,0x17,0x9e,0x34,0x7b,0x47,0x4d,0x64,0xd2,0xa, + 0x97,0xa6,0xaa,0xf8,0xb7,0x6f,0x9f,0xc7,0x1b,0xe7,0xc7,0x30,0x34,0x90,0x17,0xc3, + 0xb6,0x8f,0x5c,0xf4,0x82,0x0,0xfb,0xc7,0x2d,0x7c,0xf8,0x70,0x3,0xff,0xc7,0xaf, + 0xef,0x63,0xf7,0xa8,0xe5,0xd9,0x3d,0x44,0x77,0xff,0xd2,0x94,0x44,0xea,0xd1,0x5f, + 0x62,0x83,0xee,0xb1,0xc6,0x49,0x3a,0x30,0x5a,0x87,0x2d,0xb2,0x54,0x17,0x52,0x5e, + 0xfd,0x25,0xe1,0x9d,0x6f,0xa1,0x48,0x8e,0xe8,0xc2,0xed,0xde,0x52,0x2e,0x93,0xc9, + 0x3f,0x68,0x25,0x80,0xcf,0x3a,0xbd,0xcb,0xf3,0x36,0x26,0xdf,0x54,0x59,0x66,0xc0, + 0x19,0xff,0x81,0x5c,0x3a,0x85,0x89,0x5a,0x11,0x17,0xa7,0xaa,0xb8,0x32,0x5b,0xc3, + 0xb5,0xd9,0x1a,0xe6,0xc6,0x6,0x31,0xa4,0xbd,0xec,0xfb,0xed,0x14,0x93,0xe0,0x6b, + 0x39,0xc9,0xb4,0xda,0x1d,0x2c,0xef,0x9e,0xe0,0x6f,0x3f,0x5e,0xe4,0xf,0x1f,0x6c, + 0xf0,0x62,0xb8,0x6f,0xb4,0x30,0xa4,0x1c,0xb6,0x6d,0x43,0xe2,0xfd,0xf8,0xcc,0x88, + 0x22,0xb7,0x14,0x23,0x69,0xb2,0x80,0xc9,0x6c,0x45,0x57,0x4,0xcc,0xc,0xf,0xd0, + 0xec,0xc8,0x80,0x87,0xe2,0x44,0x21,0xed,0x6e,0x8f,0x71,0x7f,0xf5,0x0,0xf,0xd6, + 0xe,0x5,0x69,0x31,0x7c,0x6d,0x53,0x14,0x92,0xea,0xe6,0xc7,0x7,0x71,0x65,0xba, + 0x8a,0x4b,0xd3,0x55,0x5c,0x98,0xa8,0x60,0x6e,0xac,0x8c,0x42,0xc4,0x20,0xa9,0x9f, + 0x14,0xb3,0x9f,0x52,0x42,0xda,0xf,0x47,0x77,0xc7,0x27,0xa7,0x5d,0x3c,0xdd,0x3a, + 0xc2,0x47,0xf,0xd6,0xf9,0x83,0xfb,0x9b,0xfc,0x74,0xa3,0xce,0xcd,0x76,0xd7,0x3c, + 0xb5,0x66,0x44,0xd,0x6f,0x69,0x4d,0x93,0x34,0x39,0x0,0x9a,0x4d,0xa5,0x73,0xb6, + 0x8d,0xc2,0x4b,0x85,0x25,0x5a,0x4c,0xe7,0x61,0xb5,0x51,0xc,0x32,0xf,0xb0,0xa3, + 0x2d,0x90,0xe3,0xb,0x1b,0x26,0x39,0xb9,0xdf,0xcf,0xdd,0x4c,0xb6,0x66,0x29,0x67, + 0xef,0x21,0x8d,0xc1,0x59,0xaf,0x43,0x58,0x8c,0x69,0x85,0x5c,0x1a,0xe7,0x27,0x6, + 0x31,0x5e,0x29,0x50,0xd4,0xa3,0x40,0x5e,0xc3,0xe3,0x56,0x17,0x77,0x9f,0xef,0xf3, + 0xca,0xce,0x89,0x21,0xf2,0xc5,0xf2,0x7,0xc4,0xb2,0x96,0xa3,0x1c,0x12,0x2f,0x3c, + 0x84,0x23,0xbc,0x2e,0x77,0x3c,0xd9,0xc3,0xb1,0xd9,0xe,0xe8,0x17,0xb7,0x57,0xf9, + 0xfe,0xea,0x3e,0xfe,0xe2,0xcd,0x5,0xbc,0x73,0x65,0x82,0x2e,0x4d,0xf7,0x77,0x9b, + 0x34,0x1f,0x9b,0x1e,0x2a,0xe1,0x5f,0x7f,0x7b,0x81,0x34,0x54,0xcf,0x5f,0x3e,0xdb, + 0xc1,0x69,0x47,0x37,0xf0,0x36,0xc5,0x41,0x1a,0x48,0x2a,0x45,0x1,0x7,0x20,0x5, + 0xa6,0x80,0xcc,0x1a,0x8d,0xc0,0x8a,0x3,0xa,0xc2,0x71,0xdb,0xd4,0xe,0x56,0x8, + 0x38,0xb0,0x26,0x34,0x8a,0x81,0x40,0x53,0x3,0xd,0x2a,0x1e,0xa4,0x40,0x29,0x6, + 0x7,0x30,0x69,0x2f,0x1a,0x37,0xd4,0x2e,0xb3,0x91,0xc6,0x9e,0x92,0x6,0x3a,0x24, + 0xd4,0x61,0x39,0xc,0x82,0x22,0xff,0x8f,0x8,0x6a,0xa6,0x10,0x4d,0x8d,0x93,0xf5, + 0x25,0x9a,0xb9,0x1e,0xd,0x66,0xe1,0xd0,0x29,0xce,0x11,0x31,0x8,0xe8,0x13,0x4a, + 0xd5,0xcf,0x6f,0x3c,0x5a,0xde,0x9,0xb1,0xbd,0x63,0x84,0x68,0x44,0x72,0x51,0xae, + 0xdf,0x65,0x81,0xa0,0xb3,0x9d,0xcf,0xc9,0x4e,0xf4,0x86,0x55,0xa4,0x48,0xda,0xc0, + 0x6a,0x16,0x9d,0x8d,0xa4,0x35,0x85,0x3d,0xfc,0xea,0xe3,0xd5,0x2,0xfe,0xf8,0xf5, + 0x33,0xea,0xed,0x4b,0x93,0x14,0x3d,0x4c,0xe5,0x61,0x71,0x72,0xda,0xc5,0x2f,0xef, + 0xac,0xe0,0xa3,0x7,0x9b,0x68,0x77,0xd9,0xbb,0x4b,0x1d,0xfc,0x25,0x63,0x61,0xa3, + 0xf,0x64,0xc2,0xb1,0xa8,0xdf,0xcd,0x66,0xd2,0xb8,0x34,0x55,0xc5,0xcd,0x85,0x61, + 0xdc,0x9c,0x1f,0xc1,0xc5,0xa9,0x1a,0x26,0x87,0x6,0xf4,0xe1,0x44,0x18,0xaf,0x16, + 0x8d,0x8e,0x93,0x65,0x90,0xbd,0xdf,0x46,0x79,0x18,0x25,0x5,0xdf,0xa0,0xab,0x35, + 0xbf,0x63,0x29,0x9f,0xc5,0xb9,0x89,0x2a,0xfe,0xcd,0x77,0xcf,0xe1,0xfb,0xd7,0xa7, + 0xd0,0x6c,0xf7,0x90,0x52,0x84,0x6a,0x29,0x87,0xf3,0x93,0x15,0xc,0x8b,0xa0,0x8f, + 0xa4,0xc9,0x7c,0x75,0xf7,0x4,0x7f,0xff,0xe9,0x12,0x7e,0x7b,0x7f,0xd,0xbb,0x27, + 0xed,0x30,0xc4,0xf6,0xb7,0x50,0x27,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x20, + 0xf2,0xbc,0xc7,0x46,0x71,0x4b,0x68,0x48,0x6e,0xfd,0xfa,0x4d,0xe8,0x24,0xcd,0x14, + 0xfc,0xdf,0xc6,0xa7,0x9e,0x98,0x24,0xcc,0xd0,0x6d,0x49,0xe,0xd0,0x22,0x5a,0x92, + 0xbd,0x70,0x6,0x19,0x38,0x43,0x71,0x46,0x22,0xc9,0xfd,0x16,0x3c,0xf7,0x5e,0xb9, + 0xcb,0x57,0x96,0x34,0x41,0x62,0xc7,0x39,0x51,0x2d,0xd2,0x44,0xad,0x84,0xc9,0x6a, + 0xb8,0xc7,0x1c,0xad,0x16,0x30,0x5a,0x2e,0x60,0x68,0x20,0x87,0x4a,0x29,0x8b,0xe1, + 0x81,0x7c,0x62,0xb6,0xb4,0xbc,0xee,0x51,0x39,0x9a,0x84,0x8a,0x83,0x80,0x71,0x77, + 0x65,0xf,0xb7,0x16,0x77,0xf8,0xf3,0x67,0x3b,0x78,0xbc,0x76,0xc8,0x5b,0x87,0xd, + 0x83,0x3,0x8b,0x20,0x19,0x17,0x10,0xe2,0x6c,0x3c,0x5,0x52,0x66,0x12,0x26,0x7c, + 0x35,0x10,0x62,0x3e,0x52,0x82,0xac,0x6b,0xf6,0x19,0x8a,0x14,0x26,0x6b,0x45,0x4c, + 0xd,0x95,0xb4,0x9a,0x97,0x13,0xc9,0x70,0xed,0x6e,0x80,0x2f,0x9f,0xed,0xe0,0xce, + 0xf3,0x3d,0x14,0x73,0x59,0xd4,0x4a,0x39,0x4c,0xd6,0xc2,0xe9,0x7b,0xbc,0x52,0xc4, + 0x64,0xad,0x80,0xa1,0x81,0x3c,0x2a,0xa5,0x2c,0x86,0x6,0xf2,0x18,0x2c,0x64,0xbc, + 0x58,0xdd,0xe8,0xb3,0x19,0x8d,0x2c,0x7d,0x91,0xc6,0x59,0x16,0x88,0x76,0xa7,0x87, + 0xc5,0xed,0x3a,0x1e,0xac,0x1e,0xf0,0xa3,0xf5,0x43,0x3c,0xdf,0x3e,0xe2,0x95,0x9d, + 0x13,0x6c,0x1e,0x36,0xf8,0xb4,0x1d,0xc0,0x52,0xdb,0x4c,0xe,0xb6,0xc9,0x2e,0xd3, + 0x1,0x3f,0x7a,0xcd,0xca,0x96,0x13,0x17,0x52,0x33,0x35,0x83,0x9d,0xd9,0xc9,0xd2, + 0xc0,0x7a,0xe1,0xa4,0xb,0xbb,0x32,0xbe,0xa2,0x6,0x8d,0x66,0x79,0x75,0x49,0x46, + 0x6f,0x4a,0x2a,0xb1,0x54,0xfa,0x32,0xc9,0x84,0x54,0x1b,0xfb,0xe7,0xb6,0xb0,0x6e, + 0x13,0x98,0x4b,0xa7,0x71,0x61,0xaa,0x86,0x89,0x5a,0x29,0xf1,0x2c,0x30,0xd7,0x6f, + 0xeb,0xb0,0x81,0xa5,0xbd,0x13,0x34,0x3a,0x3d,0x67,0x20,0x43,0xec,0x8a,0xb7,0x72, + 0x85,0xdc,0xba,0x3b,0xf9,0x36,0x1,0x3e,0xfb,0x9a,0xe3,0x7e,0x63,0x62,0xcd,0x69, + 0xbf,0xf2,0xfa,0x41,0x93,0x7e,0xf6,0xe5,0x12,0xaf,0xec,0x9d,0xe0,0xcd,0xf3,0x23, + 0x78,0xeb,0xc2,0x38,0xd,0x97,0xf3,0xb1,0xfb,0x5f,0x36,0x66,0xd9,0x4c,0xa,0xdf, + 0xbb,0x32,0x45,0xe5,0x7c,0xe,0x3,0xf9,0x34,0xbe,0x78,0xb6,0xc7,0xbb,0x47,0x4d, + 0xf8,0xc6,0xbe,0x76,0x6d,0x11,0x2a,0x99,0x98,0x34,0xe4,0xe,0x67,0x2d,0x18,0x6, + 0xd9,0x90,0x26,0xcc,0x2b,0xe,0x60,0xc8,0x16,0xc4,0xca,0x19,0xf2,0x85,0xdb,0x36, + 0xd,0xfe,0x91,0xb0,0x92,0x37,0x1b,0xb6,0x80,0x98,0x28,0x70,0xd7,0x40,0xfe,0x0, + 0x8a,0xa2,0x97,0x2a,0xb9,0xa2,0xb,0xcd,0x3b,0xc5,0x60,0x78,0x6f,0xb1,0xe1,0x6a, + 0xb,0x4b,0x1d,0x23,0x47,0x34,0x54,0x2a,0xe1,0x10,0x73,0x5f,0x2d,0x6d,0x49,0x6e, + 0x94,0x44,0x8f,0x97,0xf2,0x26,0x7,0xce,0xf9,0x12,0x21,0x82,0x67,0x5f,0x2a,0x64, + 0x70,0x96,0x94,0xc4,0x32,0x52,0xd4,0xb4,0x37,0x29,0x92,0x6c,0x61,0x48,0xd2,0x80, + 0x67,0xe7,0xa,0xb7,0x8f,0x95,0x52,0x14,0xc1,0x1e,0xf3,0xe2,0x2e,0x9,0x18,0x2c, + 0x66,0xe9,0xfc,0x64,0x8d,0xde,0x38,0x37,0x46,0xa3,0x95,0x42,0xdf,0x5d,0x9b,0x49, + 0x24,0xfb,0xec,0xf1,0x36,0xee,0xad,0xec,0xdb,0x93,0xdd,0xda,0x12,0x68,0x66,0xb8, + 0x95,0x6c,0x98,0xa2,0xce,0x91,0xfc,0x10,0xeb,0x72,0x40,0xc8,0x64,0x8,0xf9,0x4c, + 0xa,0x95,0x52,0x1e,0x33,0xb5,0x22,0xbe,0x7d,0x69,0x2,0x6f,0x5d,0x18,0xc3,0xa5, + 0xe9,0x9a,0x77,0x0,0x1d,0x37,0xdb,0xd8,0xaa,0x9f,0x62,0x75,0xf7,0x24,0xe2,0xfd, + 0xe8,0xed,0xd8,0x20,0x8d,0xfb,0x15,0x88,0x5b,0x9d,0x80,0x7a,0x41,0x60,0x63,0x2b, + 0xfb,0xd9,0x3c,0x32,0x33,0x6,0xf2,0x69,0xdc,0x98,0x1f,0x79,0x61,0x88,0x46,0x74, + 0xf2,0x69,0x77,0xba,0x58,0xd9,0x6b,0xe0,0xe3,0x47,0x9b,0xf8,0xc7,0xaf,0x96,0xb0, + 0xb2,0x7b,0xcc,0x88,0xca,0xae,0x88,0x23,0xc1,0xb9,0x92,0x94,0x6b,0xd6,0xcd,0xca, + 0x53,0x49,0x24,0x65,0x4a,0x7b,0x5a,0x4a,0x8f,0x74,0x3,0x88,0x2e,0x87,0x3d,0xe5, + 0x0,0x31,0x11,0x87,0x5a,0x5d,0x37,0x6c,0x38,0xc1,0xba,0x89,0xd9,0x72,0xd1,0x8a, + 0x42,0xfb,0x1f,0xf9,0xf6,0x1e,0xf7,0xc7,0x9b,0xe6,0x1,0xa5,0x14,0xa5,0x15,0x21, + 0xad,0x42,0x58,0x30,0x93,0x4a,0x85,0x2c,0xd2,0xb4,0x42,0x3e,0xad,0x30,0x32,0x98, + 0xa7,0x99,0x91,0x32,0xe6,0x47,0x7,0x30,0xaf,0x77,0xbf,0xe3,0x95,0x82,0x4d,0xf0, + 0x8a,0x92,0xda,0xa2,0x70,0x70,0x94,0xbc,0x24,0xff,0x7c,0xda,0xee,0xa2,0xd9,0xee, + 0xe1,0xd9,0x56,0x1d,0xbf,0x7f,0xb4,0xc5,0xef,0x7f,0xbd,0xc6,0x8f,0x36,0xea,0x76, + 0xef,0xa9,0x8d,0x78,0x3c,0xb3,0x54,0x97,0x65,0x22,0x9e,0x53,0xfb,0x35,0x35,0x96, + 0x21,0xed,0xe,0x3c,0x12,0xad,0xd0,0x4a,0xd9,0x70,0xce,0xf0,0x55,0x4c,0xa5,0x8, + 0x93,0x43,0x25,0x4c,0xd6,0x1c,0xb,0x3f,0xa9,0x80,0x74,0x3,0xe,0xf7,0xba,0x43, + 0x25,0x2c,0x8c,0xd,0x62,0x66,0xa4,0x84,0x33,0x23,0x3,0x58,0x18,0x2b,0x63,0x6e, + 0xb4,0xec,0x19,0x9f,0x44,0x77,0xdb,0x49,0xc,0xfe,0xe8,0x34,0x2e,0xf3,0xbc,0xa3, + 0x7b,0xd8,0xd3,0x76,0x17,0xa7,0x9d,0x1e,0x1a,0xad,0x2e,0x96,0x77,0x8e,0xf8,0xeb, + 0xa5,0x7d,0x7c,0xf4,0x68,0x93,0xef,0xaf,0x1e,0x72,0xa3,0xd5,0x91,0x40,0x68,0x38, + 0x7e,0xb9,0xfb,0xcd,0xfc,0x8f,0xa1,0xc4,0x15,0x35,0x96,0x84,0xac,0x9d,0xc1,0x9d, + 0x7f,0x7c,0xa0,0xbf,0x8e,0x65,0xbb,0x87,0x65,0x81,0x59,0x6b,0x27,0xd9,0x68,0x3, + 0x1d,0xdf,0xcd,0xb,0xb,0xf5,0x21,0x26,0xc1,0x6b,0x67,0x87,0x0,0xd9,0x30,0x4a, + 0x23,0xc0,0x17,0xb6,0xd9,0xf6,0x3e,0x2f,0x17,0xb3,0x98,0x1d,0x19,0xb0,0x45,0x32, + 0xfa,0x8c,0x5,0x41,0x18,0x9d,0xbb,0xbc,0x7d,0xc2,0xfb,0x27,0x2d,0x7b,0x86,0x86, + 0x3d,0x7,0x59,0x83,0x40,0xe7,0xa4,0xa2,0xc3,0xe5,0x2d,0xf3,0xda,0x86,0x6d,0xf8, + 0xc2,0x4b,0x8f,0x90,0x4d,0x2e,0xd2,0x8e,0x94,0x26,0x86,0x86,0x97,0x2a,0x60,0xf0, + 0xe2,0xd6,0x31,0xb6,0xeb,0x2d,0x6c,0xd7,0x4f,0x91,0x52,0xa,0xdf,0x3a,0x37,0x46, + 0xe5,0x42,0x1a,0x99,0x74,0x2a,0x76,0x66,0x99,0x67,0x64,0x68,0x20,0x87,0xb7,0x2f, + 0x8d,0x51,0xc0,0x8c,0x94,0x4a,0xe1,0xc3,0x87,0x9b,0xa8,0x37,0x3b,0x8e,0x3b,0x13, + 0x93,0x57,0x11,0x14,0x93,0x62,0xe2,0x30,0xad,0x29,0xa0,0x20,0xdc,0x9a,0xa4,0x94, + 0x7e,0x6d,0x3,0x4a,0x11,0x71,0xa0,0x3d,0x7b,0x18,0x4a,0x6b,0xd4,0xc8,0x48,0x5e, + 0xc1,0x60,0xa4,0x40,0x8,0x44,0x5c,0x33,0x9c,0xed,0x24,0xf9,0x44,0x2,0x4d,0x8f, + 0x11,0xf2,0xda,0x58,0xe2,0x91,0x7,0x55,0xfa,0xc8,0xad,0xf8,0x7c,0x1b,0xbb,0x4c, + 0xf1,0x25,0xb5,0xc7,0xd5,0x11,0x86,0x65,0xac,0xfd,0x2e,0x38,0xc9,0xca,0x19,0xac, + 0x9d,0xe2,0x1c,0x9b,0x8,0x32,0xbc,0xcf,0x4b,0x9d,0x88,0xe5,0x28,0x5b,0x4b,0x1c, + 0x13,0x76,0x11,0xc5,0xfc,0xcd,0x36,0x2a,0x14,0xdd,0x4b,0x46,0x80,0xc4,0xd9,0xe5, + 0x6e,0xd3,0x1c,0x4c,0x32,0x93,0xc5,0x16,0x78,0x67,0x31,0x63,0xba,0x2c,0xf7,0xef, + 0x85,0xbe,0x8d,0x40,0x57,0x66,0x87,0xe8,0x9d,0x2b,0x93,0x4a,0xa6,0x53,0xf5,0x9b, + 0x6a,0xbb,0x1,0x63,0xf3,0xb0,0x89,0xd3,0x4e,0x20,0xe0,0x2f,0xc7,0x4,0x37,0x19, + 0x99,0x12,0xfe,0x20,0x22,0xab,0xe9,0x95,0x1e,0x27,0x85,0x6c,0xa,0xe7,0xc6,0x2b, + 0xb8,0x39,0x3f,0x8c,0x57,0xe6,0x86,0x71,0x71,0xaa,0x8a,0x6a,0x29,0x87,0x6c,0xc6, + 0x87,0x5,0x9b,0xad,0xe,0x1e,0xae,0x1f,0xe2,0xff,0xfe,0xe0,0x9,0x7f,0xfe,0x74, + 0x3b,0x54,0x5f,0x29,0x88,0x17,0x8a,0x62,0x49,0x9a,0xe6,0xbb,0xd5,0x9b,0x1d,0x6c, + 0x1c,0x34,0x31,0x36,0x98,0x47,0x36,0x93,0x4e,0x94,0xad,0x49,0x22,0x55,0x3f,0xbf, + 0xe5,0xa4,0xb7,0x6e,0xb7,0x87,0xf5,0x83,0x26,0xfe,0xe6,0xe3,0x67,0xf8,0xcf,0x5f, + 0x2e,0xf3,0xde,0xd1,0xa9,0x78,0x5d,0xfd,0x89,0xdb,0x35,0x36,0xd1,0x4,0x37,0xcb, + 0x55,0x13,0x5e,0x42,0xf4,0x82,0xd7,0x40,0x39,0x79,0x18,0x93,0x7d,0x50,0xe0,0x22, + 0x18,0xb4,0xf4,0x57,0x7b,0x64,0xbb,0x34,0x40,0x99,0xe8,0xc2,0xc2,0x91,0x89,0xec, + 0xf4,0x6a,0x24,0x80,0xde,0x31,0xc0,0xbe,0x98,0x3c,0xe1,0xb1,0x28,0x17,0xb2,0x54, + 0x1d,0x8,0xa7,0xcc,0xe1,0x72,0x1e,0x43,0xe5,0x3c,0x46,0xca,0x79,0x1a,0xe,0xff, + 0x8b,0x91,0xc1,0x1c,0x6,0xf2,0x19,0x64,0xd3,0x29,0x64,0x52,0xa,0xd9,0x8c,0x42, + 0x36,0xa5,0xbc,0xf5,0x45,0x3f,0x18,0x38,0x69,0x5a,0x97,0xd7,0xe6,0xb4,0xdd,0xc5, + 0xc3,0xf5,0x43,0xfc,0xe2,0xd6,0xa,0x7f,0xf5,0x6c,0x8f,0xd7,0xe,0x4f,0x70,0x74, + 0xd2,0x61,0x72,0x9d,0x12,0xbb,0x38,0x2f,0xab,0xca,0xf5,0x64,0x2e,0x46,0xd5,0xc3, + 0xc6,0x31,0xd7,0x76,0x61,0xce,0x2a,0x9d,0xac,0xe5,0x19,0x5b,0xc7,0x62,0x4b,0x0, + 0x74,0x0,0x2b,0xa5,0x34,0x92,0x34,0x5e,0x2d,0xf6,0x7d,0xd,0x7b,0xbd,0x0,0xb9, + 0x8c,0xc2,0xbf,0xff,0xfe,0x5,0x74,0x7b,0x8c,0x72,0x21,0x83,0xac,0x26,0xb4,0x65, + 0xd3,0xca,0x12,0x39,0x5f,0x44,0x60,0xfb,0x66,0xbb,0x2,0x8a,0x15,0x73,0xcb,0x7f, + 0xd9,0x3c,0xc2,0x97,0xcf,0x76,0xf8,0xb3,0xa7,0x3b,0xbc,0xbc,0x7b,0x8c,0xfd,0x93, + 0x16,0x37,0x4f,0xbb,0x38,0xed,0xf6,0xe0,0xd8,0x3,0xae,0x4a,0x89,0xf3,0x98,0xdd, + 0x83,0x1c,0x32,0xd8,0x11,0x84,0xd7,0x54,0x6b,0xc7,0x8d,0x9e,0x9c,0x8d,0x64,0x8d, + 0xad,0x1b,0x9,0x19,0xf2,0x9b,0x7d,0x9f,0xc9,0xd2,0xc1,0x19,0x1e,0x77,0xd2,0x99, + 0x5a,0x5a,0xca,0xb6,0xf9,0xa3,0x35,0xda,0x24,0xa7,0x8a,0x22,0x69,0x50,0x44,0x4e, + 0x61,0xad,0xbf,0x78,0x5a,0x29,0x8c,0x55,0xa,0xa8,0x8a,0x30,0xa9,0xe8,0x35,0xa, + 0x38,0xc0,0xd3,0xad,0x63,0xdc,0x5f,0x3f,0x40,0xaf,0x67,0xef,0xe,0x87,0x4c,0x18, + 0x87,0x62,0x16,0xd1,0xc3,0x76,0xda,0x56,0xd6,0xf,0xc2,0x86,0xa7,0x68,0xa7,0x74, + 0x8e,0x45,0x88,0x39,0xcf,0x6b,0x32,0x4,0x1,0xfd,0xc8,0x42,0x31,0x9d,0xb4,0x7a, + 0x7c,0x7b,0x69,0x8f,0x76,0x4f,0x5a,0x7c,0x7f,0xf5,0x10,0xff,0xe6,0x3b,0xb,0x34, + 0x3b,0x32,0x90,0xf8,0x5a,0x9a,0xdf,0x23,0x9f,0x4d,0xe3,0x7b,0x57,0x26,0xa8,0x5a, + 0xca,0xa2,0x32,0x90,0xa5,0x5f,0xdd,0x59,0xb,0xb6,0xeb,0xa7,0xd6,0x87,0x34,0x44, + 0x9,0x94,0x43,0xc6,0x4d,0xcb,0xca,0x3a,0x6c,0x95,0x10,0x12,0xd8,0xb5,0xc4,0x84, + 0x3,0x76,0xde,0x25,0xa6,0xa3,0x61,0xd2,0xd4,0x7,0x63,0xcd,0x67,0xfc,0xf7,0xa3, + 0xe4,0x36,0x72,0x9e,0xd2,0x81,0xb3,0xa2,0xb1,0x68,0xa1,0x34,0x68,0xf2,0xa8,0x3f, + 0x51,0xc2,0x9b,0x5f,0x4b,0x63,0x26,0x5f,0xec,0xf2,0x2c,0x98,0x1c,0x43,0x9e,0x3d, + 0x28,0x84,0x22,0xa9,0x83,0xe2,0xdb,0x1a,0x96,0x7b,0x2c,0x8e,0x8d,0x9c,0xe9,0x81, + 0xce,0x29,0x37,0x27,0x88,0xf8,0x66,0x32,0xf,0x5a,0x85,0x2f,0x74,0x8c,0xba,0xcd, + 0x76,0x17,0xc4,0x31,0x18,0xc2,0xfd,0x42,0x96,0x7c,0xac,0x19,0xc5,0x2c,0x27,0x19, + 0x57,0xcc,0xed,0x4d,0x2e,0x21,0x2c,0x3,0xdf,0xbb,0x40,0xa2,0xf0,0x2f,0xe7,0x46, + 0xcb,0xb8,0x3c,0x53,0x45,0x3e,0x9b,0xfa,0xc6,0x43,0x22,0xa5,0x8,0xa3,0xd5,0x2, + 0x32,0xeb,0x87,0xe8,0xf4,0xd8,0xc9,0x9,0x8c,0x19,0x87,0xd4,0x11,0xc2,0x1,0x11, + 0x29,0xa5,0x50,0xce,0x67,0x31,0x58,0xcc,0xa0,0x52,0xca,0x61,0xa4,0x9c,0xc3,0x54, + 0xb5,0x88,0x33,0xa3,0x65,0x9c,0x9f,0x1c,0xc4,0xc2,0xd8,0x20,0x2a,0xc2,0xbd,0x8a, + 0x99,0xd1,0xed,0xf6,0xb0,0xb6,0xdf,0xc0,0xdd,0x95,0x7d,0x7c,0xfc,0x68,0x93,0x3f, + 0x79,0xb4,0x89,0xc3,0x66,0xc7,0x1b,0x97,0x88,0x39,0x96,0x7e,0x25,0x21,0x9a,0xe7, + 0xdb,0x47,0x7c,0x6f,0x65,0x9f,0xaa,0x97,0x26,0x90,0xcd,0xc4,0x9d,0xc4,0xfa,0xc1, + 0x94,0x49,0x87,0xa3,0xfc,0x77,0x8d,0x56,0x1b,0x8f,0xd6,0xeb,0xf8,0xe0,0xde,0x6, + 0x7f,0x70,0x7f,0x3,0x3b,0xf5,0x53,0xc1,0x56,0x17,0xe1,0xdf,0x9e,0xb4,0x82,0x12, + 0xf2,0xbe,0xdd,0x8d,0xcc,0xc,0xee,0xf4,0x2,0xca,0xbf,0xc8,0xe8,0xc3,0x7c,0xdc, + 0xe4,0x9,0x4b,0x9c,0xcf,0x9a,0x6d,0xa9,0xd0,0x41,0x13,0x8a,0x95,0x54,0x50,0xb8, + 0x6,0x88,0x72,0x69,0x85,0xca,0x40,0xe,0x33,0x43,0x25,0xd4,0x6,0xb2,0xc8,0xa4, + 0x52,0x48,0xa5,0x74,0x5f,0xeb,0x28,0x74,0xc4,0x71,0x4f,0x6,0xaf,0xa8,0xe7,0xb2, + 0x69,0x94,0x73,0x19,0x94,0xb,0x69,0x94,0xb,0x59,0xaa,0x14,0xb3,0xa8,0x14,0xb3, + 0x28,0x17,0x32,0xa8,0x96,0x72,0x31,0xa8,0xb8,0x1f,0x1c,0x9c,0xd4,0x68,0xc9,0x49, + 0x34,0x7a,0x90,0xed,0x1f,0xb7,0xb0,0xba,0x7f,0x82,0x27,0xeb,0x47,0xfc,0xf5,0xca, + 0x1e,0x3e,0x7d,0xbc,0xcd,0x2b,0xbb,0xc7,0x2c,0x66,0x25,0xb9,0xac,0x64,0x31,0xa0, + 0xb0,0xd4,0xcc,0xda,0xde,0xcf,0xc8,0x2d,0xd9,0xb9,0xf6,0x39,0xd4,0x2e,0x54,0xfb, + 0x1a,0x43,0x45,0x99,0x56,0x4a,0xa6,0x8a,0xe9,0x9d,0x2a,0xa5,0x14,0xd5,0x4a,0x39, + 0x54,0x4b,0x59,0xa4,0xfa,0x98,0x19,0x81,0x80,0x6c,0x2a,0x85,0xb3,0xe3,0x83,0x89, + 0x5,0x37,0x9,0xa,0x7e,0xd1,0x3d,0x9a,0x14,0x96,0x22,0xef,0xd9,0xa3,0x66,0x7, + 0x5b,0xf5,0x26,0xb6,0xf,0x1a,0xbc,0xba,0xdf,0xc4,0x93,0xcd,0x3a,0x1e,0xae,0x1d, + 0xf2,0xa3,0xb5,0x43,0x6e,0x76,0xba,0x5a,0x4,0x6e,0x38,0x94,0x22,0x6,0xd1,0x86, + 0x90,0x84,0x44,0x36,0xf1,0x78,0xb1,0x55,0xeb,0x29,0x1d,0xcc,0xa5,0x93,0xd3,0xf4, + 0xb5,0x67,0xfd,0x85,0x98,0x8,0xcc,0x3a,0x59,0x53,0xb7,0x5,0x3a,0xbf,0x8b,0xd, + 0x4c,0xc4,0x2c,0xb4,0x46,0x86,0xe6,0x60,0x1f,0x13,0x6d,0xa8,0x61,0xd0,0x27,0x53, + 0xc2,0x35,0x4f,0x9b,0x9,0x8a,0x38,0xaa,0x6f,0xf5,0xe4,0x6c,0xe1,0x3a,0x71,0x6a, + 0x78,0x80,0xc,0xfb,0x3f,0x89,0x7b,0x40,0x20,0x3c,0xdb,0xaa,0xf3,0x83,0xb5,0x3a, + 0xba,0xc6,0x2f,0xdc,0xda,0x83,0xb1,0xb3,0xaa,0xf5,0x95,0xa2,0x6c,0x92,0x43,0xc9, + 0x63,0x6a,0x9b,0x4b,0x21,0xcf,0x40,0x16,0xe4,0x3e,0xa3,0xd5,0x13,0x6c,0x1a,0x23, + 0x8a,0x54,0x44,0x8d,0x4e,0xc0,0x8f,0x36,0x8e,0xd0,0xe9,0x31,0xb2,0x19,0x85,0x6f, + 0x9d,0x1b,0xa5,0x4b,0x53,0x61,0x2,0x5e,0x12,0xba,0x68,0x8a,0xfa,0xe5,0xe9,0x5a, + 0x48,0x3b,0x8,0x40,0x1f,0x3d,0xde,0xc2,0xca,0xee,0x89,0x8d,0x5c,0x23,0x72,0x5, + 0xd6,0xcc,0x76,0x36,0x29,0x15,0xa4,0x58,0x71,0xa0,0x99,0x10,0x9e,0x5,0x78,0xb8, + 0x6f,0xf,0xdd,0xe3,0x42,0x98,0x22,0x20,0x4b,0x82,0x64,0xcb,0x12,0x75,0x45,0x5e, + 0xbb,0xd7,0x69,0x8d,0xa5,0x7d,0x85,0xad,0x19,0x9d,0x12,0x55,0xd5,0x73,0xc3,0x72, + 0x53,0x34,0x4b,0xb3,0x2d,0xdf,0xa2,0x2,0xd1,0xd,0xa5,0x64,0xa3,0x5,0xe8,0xe3, + 0xe1,0xa0,0x8f,0xe2,0x0,0x22,0xd7,0x35,0xcc,0x12,0x40,0xda,0x32,0x27,0xe1,0x8b, + 0xde,0xa5,0xdd,0x80,0x1f,0xd5,0xa4,0xc7,0x49,0x25,0x2d,0x61,0x23,0xdb,0x4f,0x91, + 0xdc,0xce,0xc2,0x98,0x43,0x1a,0xbe,0x38,0x82,0x1b,0xbc,0x94,0xd4,0xb8,0xd5,0x93, + 0x73,0xac,0x12,0x9d,0x2d,0x4c,0xcc,0x24,0x79,0xdd,0x4e,0xf8,0x81,0xe1,0xc1,0x2, + 0xcd,0x8e,0x94,0x29,0xf3,0x2,0x8,0xcf,0xdc,0x40,0x85,0x6c,0x1a,0x6f,0x9c,0x1d, + 0x43,0xbd,0xd1,0xc1,0x97,0xcf,0x76,0x23,0xe6,0x31,0x31,0xfb,0x9e,0xd0,0x5e,0x8f, + 0x28,0x64,0x2e,0x8f,0x95,0xb1,0x30,0x5e,0xc6,0xd5,0x99,0x1a,0x2e,0xcf,0xd4,0x30, + 0x5a,0xce,0xdb,0xc3,0xde,0x64,0x2c,0xcb,0x1b,0x76,0x75,0xaf,0x81,0xdf,0xdc,0x5b, + 0xe3,0x9f,0x7f,0xb5,0x8a,0x3b,0xcb,0xfb,0x6c,0x7b,0xf6,0x48,0xd4,0x5e,0xd4,0xf6, + 0x5a,0x82,0x71,0x4f,0x36,0x8e,0xf0,0xfb,0x7,0x9b,0x7c,0x65,0xa6,0x46,0xa5,0x5c, + 0xfa,0xa5,0xdd,0xb0,0x5e,0x34,0x1d,0x9e,0xb6,0x3b,0x78,0xb4,0x5e,0xc7,0xcf,0x6f, + 0xad,0xf2,0x7f,0xfa,0x64,0x11,0x8d,0xff,0x8f,0xb6,0x37,0x6b,0xd2,0x34,0xbb,0xae, + 0xf3,0xf6,0x3e,0x99,0x55,0xd5,0xd5,0x33,0xd0,0x40,0x3,0x60,0x83,0xc4,0x40,0x91, + 0x30,0x68,0x99,0x83,0x69,0x9b,0x8e,0x10,0x15,0xe,0x85,0x15,0xa1,0x4b,0x5d,0xf8, + 0x4e,0x3f,0xc5,0xbf,0x47,0x17,0xe,0xdb,0x57,0xba,0x50,0x78,0x64,0xd0,0x41,0x8a, + 0x92,0x48,0x2,0xe0,0xd0,0x4,0xd0,0x18,0xba,0xd1,0xd5,0x43,0x55,0x57,0x65,0x4d, + 0x99,0x95,0x73,0x7e,0x67,0xf9,0xe2,0x9c,0xbd,0xf7,0xda,0xfb,0xbc,0x5f,0x83,0xa2, + 0xc3,0x8c,0x90,0x50,0xdd,0x5d,0x5d,0x9d,0xf9,0xe5,0xfb,0x9e,0xb3,0x87,0xb5,0x9e, + 0x75,0x79,0x3,0x49,0x59,0xde,0x2d,0x89,0x3,0x57,0x9c,0x2d,0xc3,0xec,0xe2,0xc5, + 0xef,0x1d,0x72,0x79,0xdd,0xe5,0xd5,0x97,0xf6,0x9,0xc1,0xec,0xb9,0x1f,0x9a,0x16, + 0x77,0x6,0x34,0x49,0xe3,0x29,0x42,0x7,0xcf,0x9e,0x12,0xbe,0xf,0xb4,0x2,0xe8, + 0xed,0x37,0x5f,0x96,0xdf,0xfb,0xd6,0x5b,0xfa,0xcf,0xfe,0xf1,0x3b,0xf2,0x9d,0x77, + 0xde,0xd4,0x97,0x6f,0x1f,0xc8,0xdd,0xdb,0x87,0x9b,0x59,0xec,0xbf,0xcc,0xf2,0xb7, + 0xaf,0x83,0xde,0x27,0xec,0xf9,0xfb,0x76,0x9b,0xfb,0xe8,0x7b,0xcf,0xce,0xae,0xe4, + 0xdd,0x7b,0x4f,0xf1,0x7f,0xff,0xed,0x27,0xf2,0x57,0xbf,0x78,0x8c,0x7,0x4f,0xcf, + 0x60,0x6,0xe7,0x30,0xea,0xf9,0x57,0xe0,0x63,0x6,0xf5,0x63,0x8c,0x7b,0x26,0xd0, + 0x76,0xcc,0xc6,0xbc,0x39,0x8,0x3d,0x7a,0x81,0x49,0x4,0x73,0x93,0xc8,0xf8,0x1b, + 0xad,0xa9,0xc2,0x5d,0x0,0x4d,0x5e,0xbe,0x73,0x28,0xaf,0xde,0x39,0x64,0xb9,0x70, + 0xfa,0xbf,0x83,0xd6,0xe4,0xa0,0xed,0x57,0x5a,0xff,0xa7,0xd2,0xdb,0xb6,0x52,0xd1, + 0x4c,0x53,0xf0,0xe4,0xf4,0x4a,0xde,0x7f,0xf0,0x1c,0xdf,0x7f,0xff,0x48,0xbe,0xf7, + 0xfe,0x11,0xde,0xfb,0xf4,0x39,0x2e,0x26,0x13,0xdc,0x33,0xd8,0x48,0x8c,0x36,0x90, + 0x9c,0xa0,0xcf,0x13,0x86,0x61,0x85,0x78,0xe2,0xba,0xa9,0xd7,0x1b,0x20,0x1d,0x33, + 0x9f,0xdd,0x85,0x6f,0xb0,0x7f,0x3e,0xc7,0xed,0xaa,0x7d,0x5e,0xe4,0x24,0x8c,0x6b, + 0x2a,0xf4,0xfb,0x22,0x8e,0x94,0x78,0xc4,0x73,0x92,0x3f,0x6c,0x3,0x14,0x42,0x3f, + 0x36,0xbd,0x12,0x49,0x56,0x8d,0x97,0x78,0x9,0x79,0x4,0x6d,0xaa,0x5f,0x7b,0xeb, + 0x55,0xfd,0xd5,0xb7,0xb2,0x48,0xb1,0xae,0x78,0x76,0x80,0xfc,0xe2,0xe8,0x85,0xbc, + 0xff,0xe8,0x4,0xd7,0x1d,0xc4,0x9b,0xcf,0x97,0xb9,0x68,0x1b,0xb4,0xbb,0x46,0x6f, + 0x1c,0xe5,0xec,0xc,0x77,0x31,0xdd,0xf8,0x94,0x39,0xc,0xd2,0xa3,0xfa,0x83,0xe9, + 0xc2,0xa,0x49,0x42,0x4c,0x55,0xd5,0xf,0x1f,0x9f,0xe2,0x5f,0xff,0xe9,0xcf,0xe5, + 0xde,0xe3,0x53,0xf9,0x1f,0xfe,0xe0,0x9b,0xfa,0x9b,0x93,0x2f,0xb0,0xef,0x8c,0x7e, + 0xf5,0xee,0x2d,0xf9,0xdd,0x6f,0xbe,0xa5,0x2f,0xbf,0x74,0x4b,0xbf,0xf0,0xda,0x4b, + 0xfd,0x7f,0xf9,0xf,0x1f,0xc8,0xd3,0xb3,0xcb,0x91,0x60,0x27,0xa2,0x21,0xea,0xa0, + 0x20,0x36,0xf8,0x18,0xdd,0x43,0x5b,0xfa,0x44,0x3b,0xcf,0x9f,0xaa,0x9a,0x17,0x71, + 0x9c,0x24,0x73,0x89,0x3e,0xbb,0x75,0x1f,0x67,0xcd,0x42,0x70,0xbc,0x4d,0x23,0xf9, + 0x49,0x4b,0x37,0x6d,0x9c,0x85,0x48,0x4e,0x6b,0x2b,0xe4,0xd3,0x6e,0xbd,0x94,0x2c, + 0xb7,0xc7,0xc2,0x46,0x67,0x67,0x8e,0xb3,0x95,0x5,0xe1,0xec,0x57,0x42,0x43,0x7c, + 0xd,0x4d,0x66,0x7c,0xaa,0xf2,0xbe,0xb1,0xf4,0x84,0x1a,0xfb,0x1e,0x8f,0x74,0x3, + 0xe5,0xe8,0x2a,0x69,0x2c,0xc8,0xcf,0x2a,0x69,0xcf,0x2e,0x91,0x9f,0xb4,0xac,0xc0, + 0x63,0x7a,0xce,0x30,0xe,0x27,0x19,0xf1,0x3,0xeb,0xff,0x72,0xf3,0x8b,0x3e,0xd6, + 0xac,0x73,0x37,0xa5,0x2a,0xaf,0xdd,0xbd,0x25,0x7c,0xd9,0xed,0x1b,0x77,0x8a,0x88, + 0xbc,0x74,0xeb,0x40,0xfe,0xf0,0xbb,0x5f,0x95,0xb7,0xdf,0xb8,0x2b,0xdf,0xf9,0x95, + 0x37,0xe5,0x83,0x87,0x27,0xf2,0xf8,0xe4,0x52,0xae,0x6f,0xba,0xdc,0x3a,0x6c,0xf2, + 0xfa,0xdd,0x5b,0xa3,0xb,0x7f,0xf9,0x8e,0xbc,0xfe,0xf2,0x6d,0x79,0xfd,0xee,0x6d, + 0x79,0xe3,0xe5,0x5b,0x62,0x9d,0xdb,0x1b,0xaf,0xdc,0x91,0x37,0x5f,0xb9,0x23,0x5f, + 0x7c,0xe5,0x76,0xba,0x3c,0xd8,0x12,0x77,0xef,0xd1,0x89,0xfc,0xf9,0xcf,0x1e,0xe1, + 0xaf,0x3f,0x7c,0x2c,0x3f,0x7f,0x70,0x2c,0x1f,0x3d,0x3a,0x99,0xdc,0x12,0x84,0x8a, + 0x3b,0x28,0x15,0x29,0xdd,0x6a,0xb2,0x54,0x8c,0xff,0x2c,0xf7,0x9f,0x9f,0xc9,0xdf, + 0x7c,0xfc,0x54,0xff,0xfa,0x17,0x8f,0x71,0xf7,0xd6,0x81,0xbe,0xf5,0xfa,0xdd,0x4, + 0xd9,0xf8,0xbc,0x3,0x73,0x4b,0xcc,0xf4,0xf8,0xe4,0x42,0xfe,0xea,0x83,0x23,0xfc, + 0xd1,0xbb,0x9f,0xca,0x5f,0xfd,0xe2,0x31,0xce,0xaf,0x6e,0xca,0x9f,0xa1,0xb2,0xf5, + 0x57,0x5a,0x5c,0xf4,0x1e,0x4f,0x4d,0x3f,0xd4,0xab,0x5d,0x97,0x27,0x2f,0x2e,0xe4, + 0xcd,0x57,0x6e,0xc9,0x1,0x59,0xb0,0xea,0xe,0xdb,0x9f,0x41,0x52,0x8e,0x7a,0x2c, + 0xa1,0x78,0xf1,0x19,0x13,0x7a,0xde,0x8f,0xcf,0xbf,0xf8,0xed,0x6f,0xbe,0xa5,0xff, + 0xf2,0xbf,0xf9,0xa6,0x7e,0xf3,0xcb,0xaf,0xcb,0xeb,0x2f,0xdf,0xfa,0xa5,0xa3,0xee, + 0xbf,0xcf,0x45,0xb2,0xaf,0xd3,0xde,0xda,0xe9,0x6e,0x75,0x99,0x5b,0x4a,0x76,0xfb, + 0x73,0x2f,0xae,0x6f,0xe4,0x67,0xf,0x8e,0xe5,0xdd,0x8f,0x9e,0xe2,0x67,0x9f,0x1e, + 0xcb,0x7,0x8f,0x4e,0xf0,0xe0,0xe9,0x29,0x8e,0x5e,0x5c,0x6,0x1d,0xcc,0x1d,0x81, + 0xbe,0xaf,0xb3,0xee,0xf,0x61,0x7c,0xa0,0x90,0x15,0x14,0xb7,0x0,0xc2,0x74,0xac, + 0x98,0x81,0x9e,0x95,0x3b,0xa1,0x73,0xda,0xd8,0x54,0x69,0x71,0xe1,0x9d,0xba,0x8a, + 0xe0,0xee,0xed,0x5b,0x5a,0xad,0x76,0xfb,0xac,0x62,0x75,0xe7,0xfd,0xcb,0xc4,0x9b, + 0xfb,0x3e,0x3f,0xfb,0xfb,0x47,0xc7,0x17,0x72,0xef,0xe8,0x85,0x7c,0xfc,0xe4,0x14, + 0x1f,0x3f,0x39,0x95,0xfb,0x4f,0xcf,0x71,0x74,0x7c,0x2e,0x47,0x27,0x57,0xf2,0xe8, + 0xf8,0x1c,0x17,0x33,0x9b,0x3c,0xca,0xf0,0xd0,0x19,0x84,0x2a,0x68,0x46,0x7a,0x44, + 0xd8,0x21,0xdf,0x4f,0x10,0xbb,0xe8,0x47,0x5c,0xe5,0x4c,0x4c,0x93,0xde,0x23,0x90, + 0x7b,0xcc,0x63,0x61,0x77,0x78,0xb3,0x4f,0x13,0xf6,0xe1,0x77,0xdb,0xb7,0x53,0x37, + 0x85,0xba,0xec,0x69,0x1e,0x2c,0xe9,0x17,0x28,0x9a,0xe5,0xb0,0x8d,0xf0,0x11,0x37, + 0x55,0x35,0x21,0xc4,0x42,0x44,0x8e,0x34,0x55,0x79,0xfb,0xcd,0xbb,0xf2,0x2b,0x6f, + 0xbd,0xfc,0x39,0xd9,0xe7,0x22,0x9f,0x3e,0x3d,0x97,0x87,0xc7,0x97,0x62,0x97,0xb9, + 0x79,0xe9,0x66,0x2c,0x2d,0xc2,0x96,0x26,0xd0,0x36,0xa3,0xe2,0xfa,0x98,0x61,0x75, + 0xf1,0xe3,0x34,0x8d,0x31,0x98,0x44,0xcb,0x8a,0x2d,0x1e,0xd,0xfb,0xba,0x46,0xa1, + 0x48,0xa8,0xc5,0x31,0xce,0xb8,0xea,0x82,0xbf,0xf8,0xe0,0xb1,0x9c,0x5e,0x77,0xfc, + 0xd3,0xef,0x7c,0x45,0x7f,0xff,0x5b,0x6f,0xe9,0xaf,0xd3,0x64,0xa7,0xbe,0x6b,0xad, + 0xa9,0x7c,0xeb,0xcb,0xaf,0x88,0xea,0x57,0x5b,0x6b,0xda,0xff,0xf8,0x47,0xf,0xe4, + 0xc7,0x9f,0x3e,0x13,0x2b,0x46,0xfd,0x53,0x77,0x17,0x80,0xef,0x92,0x74,0xd6,0x66, + 0xf3,0x3,0x1f,0xac,0xf7,0xb9,0x1e,0x1f,0xf3,0x98,0x29,0xda,0xc2,0xf8,0x77,0x20, + 0x3a,0x16,0x2d,0xd2,0xc7,0xb3,0x0,0x90,0xcd,0xab,0xcf,0xfd,0xa,0x8b,0x2,0x23, + 0xca,0x3d,0xbf,0x53,0xf6,0xb0,0xc1,0x3a,0x69,0x3a,0xd3,0xad,0xd9,0x29,0x9,0x82, + 0xa0,0xe9,0x75,0x4f,0x17,0x36,0x39,0xdd,0xa1,0x4b,0xc8,0xda,0xe8,0xe4,0xd5,0xb1, + 0xeb,0x87,0xc1,0xe2,0xe,0x8d,0x3,0x68,0xe8,0xe,0x51,0x1a,0xa3,0x72,0x68,0x8b, + 0x26,0xab,0x70,0xb2,0xab,0xe5,0xa4,0xc4,0x69,0x66,0x9d,0xc1,0x97,0x1a,0x28,0x19, + 0xd5,0xcc,0x93,0x6,0x2f,0x5d,0x4d,0xe9,0xde,0xe2,0x32,0xcf,0x16,0xf5,0x59,0x86, + 0x6b,0x64,0x6a,0x47,0xb6,0x4b,0xfb,0x25,0x7b,0xdb,0xf8,0xbf,0xdb,0xb7,0xe,0xe4, + 0xd7,0xbe,0xf4,0x9a,0x7c,0xe5,0xf5,0x97,0xe4,0xeb,0x6f,0xbd,0x22,0x3f,0xb9,0xff, + 0x5c,0x3e,0x3a,0x3a,0x95,0xcb,0xeb,0x9d,0xdc,0x39,0x6c,0xf2,0x85,0xd7,0xee,0xc8, + 0x5b,0xaf,0xda,0xee,0xf4,0x25,0xf9,0xe2,0xab,0x63,0x7f,0xba,0x75,0x48,0xdb,0x7f, + 0xaf,0x77,0xc8,0xc5,0xf5,0x8d,0x9c,0x5d,0xee,0xe4,0xc1,0xf3,0x33,0x79,0xf7,0xde, + 0x53,0xfc,0x6f,0x3f,0xf8,0x48,0x7e,0xfc,0xc9,0x33,0x74,0x64,0xa3,0x94,0xf2,0x58, + 0x3,0x31,0x46,0x36,0x9e,0xad,0x8,0x15,0xbc,0xf3,0x7,0xf8,0xf1,0xe3,0x33,0xfc, + 0xe9,0x7b,0x9f,0xe9,0xed,0xc3,0x3,0xfc,0xc1,0x6f,0x7c,0x59,0x5f,0x7f,0xf9,0xce, + 0x5e,0x86,0xf3,0xbe,0x5f,0x3,0x22,0xcf,0xce,0xae,0xe4,0x2f,0x7f,0xfe,0x8,0xff, + 0xcf,0xdf,0xdd,0x97,0x3f,0xf9,0xd1,0x7d,0x8c,0x9d,0x63,0xcb,0x1c,0x24,0xcd,0x25, + 0xf8,0x32,0x4a,0x28,0x9,0xb1,0x2c,0xb4,0x3e,0xbf,0xea,0xfa,0xd1,0xd1,0xa9,0x7c, + 0xf1,0xd5,0x3b,0xe,0x24,0x59,0x4,0x62,0x4d,0xa5,0xda,0x2c,0xaa,0xd0,0xc3,0xfc, + 0xe4,0x1,0x27,0xe1,0xdf,0x31,0x4c,0xea,0xdf,0xf8,0xd2,0x6b,0xf2,0xdb,0xdf,0x78, + 0xeb,0x3f,0xa9,0x3b,0xfe,0xfb,0x4c,0x2f,0xf6,0xfd,0x35,0xaf,0x38,0xb6,0xfc,0xe3, + 0x5c,0xd0,0x19,0xa5,0xec,0xe2,0xba,0xcb,0xd5,0x6e,0x27,0xcf,0xcf,0xaf,0xe5,0x93, + 0xa3,0x17,0xf8,0xde,0xfb,0x8f,0xe5,0x2f,0xde,0x3f,0xc2,0x7b,0x9f,0x3e,0x3,0xc5, + 0x4f,0x88,0x93,0x66,0xd,0x34,0x11,0x1f,0xad,0x77,0x95,0xb0,0x51,0x85,0xfd,0x9b, + 0x8a,0xfa,0x33,0xcb,0x40,0x17,0xd2,0xca,0x80,0x8d,0xb2,0x4d,0x85,0x26,0x77,0xd4, + 0x84,0xcc,0xb8,0xca,0x83,0x61,0xbb,0xdc,0xfa,0xfc,0xf6,0x5,0xee,0xd4,0x82,0xf6, + 0xf3,0x8a,0xa4,0x28,0x90,0x20,0x57,0xbb,0x2e,0x57,0xd7,0x5d,0xae,0x77,0x3b,0x39, + 0xbb,0xde,0xc9,0xd1,0xf1,0xb9,0x7c,0xfc,0xf8,0x14,0xef,0xdd,0x3f,0x96,0x9f,0xdc, + 0x3f,0xc6,0xcf,0x3f,0x3b,0x96,0x93,0xf3,0x6b,0x1b,0xfe,0xfa,0xd4,0xd3,0x2c,0x67, + 0xce,0x60,0xd,0x21,0xff,0x3c,0xe2,0x3d,0x53,0xd0,0xfc,0x68,0x73,0x17,0x3e,0x27, + 0x1d,0x10,0xa0,0x35,0x78,0x3a,0x89,0x5d,0xf0,0x90,0x3e,0x9f,0xcd,0xe,0xa3,0x99, + 0x40,0x21,0xcd,0xc6,0xec,0x53,0x66,0x25,0xf0,0xef,0xe,0xe5,0xed,0x1,0x15,0xac, + 0x88,0x98,0xb3,0xb9,0x6a,0x9e,0x7a,0x37,0x69,0xe3,0xe0,0x4e,0xcd,0x4b,0xf2,0xe, + 0xc7,0x38,0xf4,0x40,0xe5,0xed,0x37,0xee,0xca,0x57,0xde,0x78,0x59,0xf,0x29,0x71, + 0x91,0xcf,0xb9,0x27,0x2f,0x2e,0xe4,0xe7,0xf,0x4f,0xf0,0xf8,0xf4,0x12,0xf0,0x54, + 0xb5,0x71,0xf,0x74,0x50,0xbd,0xe1,0xbd,0xa9,0x37,0x89,0xe8,0x1e,0x6b,0xe0,0x3d, + 0xab,0x3f,0x8a,0x1e,0x9c,0x13,0x38,0x27,0x1b,0xea,0x24,0x74,0x19,0x68,0xaa,0x67, + 0xc3,0x78,0x1a,0xcd,0xeb,0xb3,0x8b,0x6b,0xfc,0xfb,0x9f,0x3f,0x92,0xf3,0xeb,0x9d, + 0x5c,0xdc,0xdc,0x88,0xaa,0xea,0x3b,0x5f,0xb8,0x2b,0xb7,0x4b,0xd1,0x68,0x4d,0xca, + 0x9d,0x5b,0x87,0xf2,0x9b,0x5f,0x7d,0x5d,0x5e,0xbe,0x73,0xd8,0xa0,0xda,0x8f,0x4e, + 0x2f,0xf1,0xe8,0xe4,0xc2,0xf4,0xb1,0x11,0xdf,0xd3,0x7,0xe,0xd6,0x50,0x87,0x1a, + 0x7c,0xdb,0x79,0x91,0x8f,0xff,0x37,0x9e,0x82,0x36,0x7f,0xd,0x92,0x42,0xe,0x3a, + 0x8b,0x1e,0xcc,0x17,0xca,0x14,0xca,0x10,0x91,0x3,0x9a,0x98,0x26,0xc8,0x8b,0xa6, + 0x71,0x46,0x86,0x38,0x38,0xf9,0x8a,0x62,0x93,0x19,0xdf,0x98,0x71,0x34,0x9d,0x33, + 0x2c,0x54,0x58,0xdf,0xea,0x89,0xa7,0x89,0xed,0x4f,0xed,0x7c,0x9f,0xab,0xe2,0x43, + 0x8a,0x33,0x95,0xf4,0x73,0x61,0xb7,0x9b,0x85,0xad,0x6c,0xa0,0xd1,0xb8,0x7b,0xda, + 0xe7,0xc9,0xb,0x9b,0x3,0x49,0x35,0x13,0x4a,0x5b,0x89,0x2f,0xcc,0xe3,0xf5,0x49, + 0x92,0xf3,0x7d,0x94,0xc6,0x88,0xd6,0xf,0x73,0x49,0xf,0xbd,0x8a,0xc8,0x35,0x8d, + 0xbb,0x3f,0x4f,0x8c,0xc3,0x7f,0xff,0xf6,0xad,0x43,0xf9,0xd6,0xdb,0xaf,0xc9,0xaf, + 0x7c,0xe1,0x15,0xb9,0xba,0xd9,0x79,0x77,0x7c,0xd0,0x54,0xe,0x55,0xe5,0xe0,0x40, + 0xe5,0x40,0xd5,0xa1,0x20,0x5b,0x81,0x10,0xf6,0x7f,0xcf,0xcf,0xae,0xe4,0xdd,0x7b, + 0x8f,0xf1,0x1f,0x7f,0xf6,0x48,0x7e,0xf8,0xf1,0x53,0x7c,0xf2,0xe4,0x54,0x4e,0x2f, + 0x6f,0x6,0xfe,0x5f,0xd9,0x60,0x44,0xa,0x71,0x14,0x6b,0xdf,0x2c,0x26,0xc3,0xe3, + 0xde,0x3c,0xb7,0xe4,0x7a,0xd7,0xe5,0x4f,0xfe,0xee,0x3e,0xce,0x2f,0x77,0xf2,0xd2, + 0xad,0x3,0xf9,0xbd,0x6f,0xbd,0x95,0xc2,0x19,0xea,0xc5,0xb9,0xb5,0xd3,0xfc,0xe8, + 0xf1,0xb,0xf9,0xb7,0xdf,0xbf,0x87,0x3f,0xff,0xd9,0x11,0x7e,0xfe,0xd9,0xb1,0x5c, + 0xdc,0x8c,0x16,0x45,0xeb,0x3c,0x48,0xf3,0xae,0x19,0x31,0xbd,0x5,0x53,0x82,0x3b, + 0x56,0xe7,0xd9,0xd3,0xf3,0x2b,0xfc,0xed,0xc7,0x4f,0xe5,0x9d,0xb7,0x5e,0x51,0x8b, + 0x59,0x5c,0xc6,0xb0,0x89,0x42,0x98,0x62,0x48,0x25,0x98,0x50,0x8e,0x1c,0x86,0xbf, + 0x30,0x1a,0x0,0x5,0x90,0x43,0x62,0xb,0x48,0xf2,0xf,0xb9,0xd0,0xff,0x21,0xff, + 0xb7,0x45,0x50,0xf3,0xbd,0xef,0xc5,0x8d,0xbc,0x77,0xff,0x19,0x7e,0xf0,0xc1,0x63, + 0xf9,0xf1,0xfd,0x63,0x7c,0xf8,0xe8,0x44,0x8e,0xcf,0xae,0x70,0x79,0xdd,0xbd,0xe3, + 0xe,0xa1,0x1b,0x83,0xf,0x40,0xc9,0x5d,0xe2,0x8b,0x5e,0xf2,0xd0,0x81,0x42,0x1e, + 0xb0,0x51,0x6f,0x91,0x14,0x8e,0x8c,0xea,0x64,0x4e,0x71,0xbb,0x68,0xe6,0x48,0xcd, + 0x1d,0x68,0xd3,0xd6,0xfe,0xbe,0x1e,0x44,0xf9,0xdc,0xcf,0xfe,0xf3,0x7c,0xf7,0xc7, + 0x17,0x37,0x72,0xef,0xf1,0xb,0xf9,0xf9,0x83,0x63,0xfc,0xec,0xe1,0x89,0xfc,0xe2, + 0xd1,0x9,0x1e,0x1d,0x5f,0xc8,0xf1,0xf9,0x35,0xae,0x77,0x5d,0xae,0x26,0xb6,0x75, + 0x32,0xa3,0x46,0xd3,0x84,0xa0,0x49,0x85,0x40,0xb0,0x36,0x6a,0xf3,0xdc,0xc4,0x64, + 0xb4,0xce,0xfb,0x9c,0x82,0x70,0x1,0x85,0xa1,0x5a,0xed,0xcd,0xc1,0x54,0x83,0x61, + 0x4e,0x2d,0x0,0xa0,0x8f,0xc2,0xa1,0x1b,0xd,0x1f,0x72,0x40,0xf7,0x78,0xdc,0x23, + 0xc,0xa4,0x8a,0x4b,0xae,0xf9,0xc9,0x35,0xba,0xf2,0x9,0xaa,0x6,0x43,0x5a,0x54, + 0x63,0xd,0xad,0x2d,0x3b,0x3f,0xd4,0x2b,0x25,0x79,0xf3,0x95,0xdb,0xfa,0xc5,0x57, + 0x6f,0xf,0x1f,0x49,0xf1,0x74,0x3,0x90,0xcf,0x8e,0x2f,0xe4,0x6f,0x3f,0x7e,0x2a, + 0xcf,0x2f,0x6e,0x52,0xb4,0x35,0x75,0x12,0xb3,0x3f,0x1d,0xff,0x9f,0x5f,0x53,0x7, + 0xe2,0x5a,0x1,0x31,0xc9,0x3a,0x6b,0x55,0xe6,0x67,0x68,0x33,0xa0,0x3e,0x42,0x5f, + 0x35,0x44,0xfc,0x9c,0xea,0x67,0xbb,0x63,0xde,0x30,0x47,0x50,0x5,0x44,0xf5,0x6f, + 0x3e,0x7e,0x8a,0x47,0x2f,0x2e,0xe5,0x83,0xa3,0x33,0xf9,0xef,0x7f,0xeb,0x2b,0xf2, + 0x4f,0x7e,0xe3,0x2b,0xba,0x4f,0x50,0xda,0x5a,0x93,0x77,0xde,0x7c,0x59,0xfe,0xd9, + 0x6f,0x7d,0x55,0x6f,0xdf,0x6a,0xed,0xdf,0x7c,0xff,0x23,0xfc,0xe2,0xf1,0x8b,0x1e, + 0xc2,0x43,0xb0,0xf7,0xd7,0xa2,0xf0,0xe6,0x5e,0xa9,0xcf,0xcb,0xbc,0xa9,0xc,0xb9, + 0xe3,0x40,0xc1,0xcd,0x8e,0x5d,0x6d,0x2c,0x8a,0x3e,0x7f,0xe8,0xdd,0xdb,0x6a,0xf4, + 0x9c,0x38,0x27,0x59,0x45,0x94,0xc6,0x3d,0x9c,0x11,0x3,0x59,0x38,0x17,0xe9,0xef, + 0x73,0xf6,0x5,0xa0,0xcb,0x40,0x5b,0xb2,0x4f,0x2f,0x35,0xcf,0x5b,0x74,0x76,0x3b, + 0x29,0xe,0x39,0x88,0x21,0x2a,0x89,0xaa,0xfd,0xd5,0x94,0xc1,0xae,0xd5,0xae,0x94, + 0xdc,0xe,0x79,0xa4,0x8a,0x1c,0x8b,0x3e,0xdc,0x9d,0x8d,0x70,0x9c,0xa6,0x43,0x98, + 0x33,0x83,0x49,0xc9,0x81,0xe1,0x3b,0x6d,0x9c,0xa3,0xd4,0xc1,0x43,0x15,0x84,0x71, + 0xe7,0x24,0x22,0x88,0xa8,0x5e,0x5e,0xef,0xe4,0xfc,0xea,0x46,0x5e,0xbe,0x73,0x2b, + 0x9,0x92,0x6a,0x47,0x51,0xbb,0x88,0xa1,0xca,0x3d,0x10,0x91,0x5b,0x7b,0xad,0x60, + 0x5b,0x9d,0xff,0xd5,0xf5,0x8d,0x1c,0xbd,0xb8,0x92,0xa7,0x2f,0x2e,0xe5,0xc1,0xb3, + 0x33,0xdc,0x3b,0x7a,0x21,0x3f,0xb9,0x7f,0x8c,0x1f,0x7d,0xf2,0x4c,0x3e,0x7e,0x7c, + 0x1a,0x69,0x3d,0x1e,0x9f,0xa,0x70,0x90,0xc7,0x66,0xfe,0x1,0x18,0x93,0x3f,0x7f, + 0xd1,0xda,0x78,0x89,0xa4,0xc9,0x65,0x17,0x79,0xf7,0xe3,0xa7,0xf2,0xca,0x4b,0x87, + 0xf2,0xe0,0xf9,0xb9,0xfc,0xc6,0xd7,0x5e,0x97,0x2f,0xbf,0x7e,0x57,0x5f,0xbf,0x7b, + 0x4b,0x5e,0xbb,0x7b,0x7b,0x11,0xcb,0x5c,0x5d,0xdf,0xc8,0xf3,0xf3,0x6b,0x79,0x7c, + 0x72,0x29,0x9f,0x3d,0xbf,0xc0,0xdf,0x7c,0xf8,0x58,0xfe,0xec,0x27,0xf,0xf1,0xc1, + 0xa3,0x13,0xdc,0xec,0x3a,0x59,0xad,0xd,0x5f,0x91,0xa2,0xa1,0xb2,0x40,0x7c,0xee, + 0x6e,0xd2,0x43,0x3a,0x1b,0x3a,0xd0,0x96,0xf7,0xe9,0xd9,0xa5,0x7e,0xef,0x83,0x23, + 0x7c,0xfb,0xed,0x57,0xe5,0xdb,0x6f,0xbf,0x9a,0xe2,0x6a,0x81,0x29,0xaa,0x6e,0x2a, + 0x32,0xf,0xe9,0xfc,0x27,0x9a,0x28,0x4,0x2e,0xac,0x1c,0xd3,0x4e,0x25,0x44,0xa9, + 0x79,0xd2,0x55,0xae,0x76,0x5d,0x2f,0xaf,0xae,0x17,0xe5,0xff,0xe7,0x75,0x91,0xff, + 0x5f,0x2f,0xef,0x1a,0x6b,0xca,0xcf,0xd3,0xd5,0xcd,0x4e,0x9e,0xbc,0xb8,0x92,0x47, + 0x27,0xe7,0xf2,0xf0,0xf9,0x5,0xee,0x3d,0x7e,0x21,0xef,0x3f,0x7c,0x81,0x9f,0x3e, + 0x78,0x2e,0x1f,0x1d,0x9d,0xe2,0x72,0xd7,0xe3,0x8c,0x18,0x56,0x37,0x90,0x54,0x2, + 0x26,0x3a,0x56,0xff,0xa0,0x3d,0xe8,0x1d,0x7e,0x9b,0x63,0x9c,0xff,0x8,0xe1,0xfb, + 0x16,0x16,0x21,0x68,0xab,0xda,0xf2,0xb1,0x34,0x9f,0xc9,0x2e,0xb4,0xba,0xa,0xcf, + 0xd4,0xbc,0x5c,0x14,0x97,0x37,0x5d,0xb7,0xde,0x81,0x2d,0x11,0xdb,0xbe,0x4b,0xdb, + 0xc3,0x5b,0x2e,0x6f,0xe4,0xec,0xf2,0x46,0x5e,0x5c,0xdd,0xc8,0x8b,0x8b,0x6b,0x39, + 0x3e,0xbf,0xc6,0xd3,0xd3,0x4b,0x79,0xf8,0xfc,0x42,0xee,0x3f,0xbf,0x90,0x4f,0x9f, + 0x9e,0xe2,0xa3,0x27,0x67,0xf2,0xd9,0xf3,0x33,0xec,0x42,0x9f,0xe,0x37,0x9,0x2b, + 0x9d,0x42,0xc1,0x39,0x12,0x1a,0x51,0xf0,0xe7,0x85,0x79,0x99,0xda,0x2c,0xc3,0x46, + 0xec,0x32,0xf3,0xb8,0xe0,0xbb,0x74,0x0,0x5d,0x1d,0xf2,0x99,0x94,0xec,0x10,0x1, + 0xe,0x4,0x2,0xe3,0x8c,0x79,0x95,0x8d,0xe8,0xdc,0x7d,0x1f,0xe9,0x45,0x2f,0x48, + 0xd1,0x6e,0xeb,0x4a,0x78,0x84,0xdd,0x5c,0xb6,0xab,0x8e,0xae,0x78,0x2e,0xff,0xa7, + 0xd0,0xd8,0xff,0x3a,0xb2,0xe,0xe6,0xf1,0xd7,0x74,0x68,0x1a,0x6e,0x1f,0x38,0xe1, + 0xb1,0x4e,0x92,0x1e,0x9d,0x5c,0xe2,0xdd,0x4f,0x9e,0xe3,0xd9,0xc5,0x15,0x9c,0x4a, + 0xa5,0x8a,0xe1,0xa8,0x6e,0x73,0xba,0xa0,0xf3,0xe2,0xe,0xf1,0x9f,0x99,0x48,0x1c, + 0x10,0x37,0x5f,0x6c,0xcf,0xe3,0x20,0xa3,0x70,0x77,0xe2,0x5d,0x11,0x61,0x4c,0xb5, + 0x3e,0x84,0x2f,0x1c,0xc2,0x3a,0xdb,0x98,0x44,0x4,0x37,0xa2,0xfa,0xd1,0xf3,0x73, + 0x5c,0xbe,0xff,0x48,0x6e,0x0,0xbd,0xbc,0x1,0x7e,0xfb,0xeb,0x5f,0xd0,0x2f,0xbf, + 0xfe,0xd2,0xa6,0xf5,0xf3,0xe0,0xa0,0xc9,0x37,0xde,0x7a,0x59,0x55,0xbf,0x22,0x1f, + 0x3d,0x39,0x93,0xe7,0x97,0x37,0xfa,0xf4,0xf4,0x32,0xc6,0xdc,0x88,0x19,0xa1,0x9a, + 0x60,0xc2,0x2f,0x72,0xdb,0xa1,0xb7,0x51,0x93,0xd,0x96,0x9c,0xc7,0xb,0x5a,0xbc, + 0x8e,0x4c,0x36,0x8d,0x1f,0x62,0x4d,0x89,0x51,0x31,0xff,0x3,0x84,0xb9,0xc9,0x6a, + 0xd4,0xb2,0x4a,0xdc,0xfa,0x35,0x9f,0xf7,0xac,0x30,0x17,0xf1,0xf7,0x10,0x8c,0xfa, + 0x85,0xe1,0xef,0xc2,0x59,0x25,0xa0,0xdd,0x79,0x61,0x83,0x1c,0x72,0x5,0x7,0x66, + 0xfe,0x14,0x1d,0x9c,0xd2,0xc5,0xc,0xba,0x64,0x98,0x69,0xc3,0xe8,0x48,0x4f,0xac, + 0x88,0x50,0x3,0xf3,0x32,0xc4,0x8,0xb0,0x5c,0x74,0x72,0x30,0x2b,0x40,0x73,0x20, + 0xcc,0x1d,0x93,0x4e,0xee,0x7b,0xa8,0xdd,0xfd,0xc5,0x10,0x67,0x2b,0xa9,0x8f,0x2d, + 0x70,0x7c,0x7e,0x8d,0x27,0x27,0x97,0x38,0x6c,0x4d,0x6f,0xdf,0x3a,0xf8,0xdc,0xb1, + 0xfb,0x2f,0xdb,0x99,0x6e,0x29,0x6d,0xe3,0x20,0x83,0x5c,0xdd,0xec,0xe4,0xe3,0x27, + 0x67,0xf2,0xee,0x47,0x4f,0xf0,0x57,0xbf,0x78,0x22,0x3f,0xfa,0xf4,0x19,0x3e,0x7e, + 0x7c,0x8a,0xcb,0x9b,0x9d,0xef,0x7c,0x91,0xd7,0xc5,0x73,0x51,0xa6,0xe1,0x7,0x28, + 0xde,0xe8,0xa0,0x9d,0xcc,0x7,0xa,0x71,0xc8,0xfa,0xe5,0x2a,0x22,0xcf,0x2e,0xae, + 0xf5,0x7f,0x7f,0xf7,0x53,0xfc,0xcd,0xc7,0xcf,0xf0,0x9f,0xbd,0xf3,0x86,0xfe,0xfe, + 0x37,0xbf,0x24,0xdf,0xf9,0xda,0x6b,0xf2,0xf5,0xb7,0x5e,0xd3,0x37,0x5e,0xbe,0x25, + 0xb7,0xe,0x9a,0x5c,0xdf,0xec,0xe4,0xc5,0xe5,0x4e,0x8e,0x4e,0x2e,0xe4,0xc3,0x47, + 0x2f,0xf0,0xee,0xc7,0x4f,0xf1,0xef,0x7f,0xfa,0x10,0x1f,0x3d,0x39,0x95,0xeb,0x9b, + 0x59,0x7e,0x36,0x9b,0x6,0xa4,0x2c,0x64,0x8,0xc9,0xa7,0xc8,0xa3,0x93,0x19,0x3, + 0x24,0xa7,0x40,0x1a,0xca,0x43,0xcf,0x6f,0x80,0x1f,0xdd,0x3f,0x96,0x1f,0x7c,0xf8, + 0x54,0xbe,0xf5,0xf6,0x6b,0xf2,0xeb,0x5f,0x79,0x5d,0x99,0xc,0x76,0x76,0x75,0x23, + 0x3b,0xc8,0xc,0x95,0xe6,0xcd,0x43,0x93,0xfc,0xe1,0x20,0xa4,0xb8,0x5a,0x70,0xab, + 0xf3,0xb3,0x3c,0xbe,0xbc,0x96,0xa3,0xd3,0x6b,0xf9,0xf2,0xab,0xba,0xf8,0x5c,0xff, + 0xff,0xfa,0xbf,0x7d,0x17,0xdc,0xc9,0xf9,0xb5,0x3c,0x3c,0x39,0x97,0x77,0x3f,0x7e, + 0x8a,0xef,0xff,0xe2,0x9,0xbe,0xff,0x8b,0x27,0xf2,0xe8,0xf8,0x1c,0xd7,0xdd,0x7b, + 0x65,0x6a,0x26,0x82,0xbc,0x6a,0xce,0x0,0x2e,0x9f,0xe0,0xd8,0xd1,0xd9,0x81,0x77, + 0xb2,0x46,0xa9,0xa2,0xbb,0x5d,0x13,0xb1,0x47,0xd6,0x1c,0x47,0x63,0xaa,0xe4,0x41, + 0x29,0x75,0x35,0x6a,0x8c,0x60,0x3c,0x85,0xcf,0xe5,0xef,0x1e,0x36,0xb9,0x53,0xd1, + 0xa7,0xe7,0x57,0x72,0x72,0x7e,0x2d,0xaf,0xdc,0xd9,0x16,0x19,0xd6,0x75,0xcf,0x56, + 0x87,0x75,0xb3,0xdb,0xc9,0xe3,0x17,0x57,0xf2,0xc9,0xd3,0x53,0xf9,0xec,0xf8,0x12, + 0x9f,0x3c,0x3d,0x93,0xf,0x8f,0x5e,0xc8,0xcf,0x1f,0x9e,0xe0,0xa3,0x27,0xa7,0x38, + 0xbf,0xde,0x89,0xdd,0xb8,0x86,0x41,0xe5,0xf4,0x13,0x25,0xcf,0x4f,0xc4,0xec,0x1a, + 0xe2,0x2,0x40,0x13,0x19,0x20,0x10,0x5f,0xe,0xc3,0xbf,0xf5,0xa9,0x84,0x73,0x7b, + 0xbe,0x0,0x13,0xc,0xe2,0xdd,0xf6,0x14,0x22,0xfb,0x25,0x2e,0xd6,0xad,0xbb,0xcf, + 0x7c,0xfa,0x9d,0x6,0x34,0x1b,0xdd,0x31,0xb0,0x6a,0x96,0x3f,0x3b,0xef,0x62,0x46, + 0xd2,0x42,0x7,0xe4,0x4d,0x4f,0xf3,0x4b,0x30,0x7c,0x99,0x76,0x91,0x9b,0x15,0xab, + 0xb5,0x3c,0x72,0x57,0xa2,0x84,0xa9,0xca,0xad,0x5b,0x87,0x4b,0xe1,0xca,0xe7,0xd2, + 0xa3,0x17,0x97,0xf2,0x93,0x87,0x27,0x72,0x7a,0xdd,0x67,0xb1,0x2c,0xd1,0xc6,0x8a, + 0x5b,0xf5,0xa2,0x70,0x99,0x29,0xe2,0x26,0x12,0x10,0x96,0x48,0xce,0x87,0xb4,0xcf, + 0xe3,0xba,0x27,0x97,0xb4,0x52,0xf2,0xd3,0x78,0xa,0x7a,0x23,0xcc,0x70,0x23,0x82, + 0xa4,0xb2,0xc9,0x5e,0x9c,0xf1,0x21,0xa2,0xfa,0xf0,0xc5,0x15,0xfe,0xaf,0x1f,0x3f, + 0xc0,0xcf,0x1e,0xbd,0xd0,0x7f,0xf5,0x7,0xdf,0x94,0xff,0xee,0x37,0xbf,0xa2,0x2f, + 0xdf,0x6a,0x72,0x48,0x23,0x78,0xfb,0x5e,0xf,0xf,0xe,0xe4,0x5b,0x5f,0x7a,0x55, + 0xff,0xc9,0x6f,0xbe,0x2d,0x17,0xbb,0x9d,0xfe,0xf1,0x7b,0xf,0x71,0x7a,0xb5,0x1b, + 0xd2,0x7c,0x1b,0xd3,0xf5,0x89,0x1a,0xc0,0xdc,0x54,0xeb,0x6c,0xd,0xa6,0x28,0x42, + 0xe,0xe6,0xd8,0xbd,0x99,0x58,0xce,0x2a,0xe2,0x83,0xa1,0x87,0x54,0xf,0x7d,0x4b, + 0xe8,0xde,0x5c,0xb,0xeb,0x6,0xdd,0x3a,0x47,0xbe,0x8a,0x56,0x42,0x8f,0x1b,0xcf, + 0xe3,0xc,0x9b,0x21,0x37,0x9,0xa,0x50,0xef,0x63,0x17,0x67,0x68,0xb2,0xd,0x72, + 0x15,0x6f,0x37,0xf1,0xe1,0x50,0xa,0x46,0xc7,0xe5,0x97,0x95,0x14,0x5a,0x19,0x24, + 0x5,0xc3,0xf2,0x70,0xbe,0x67,0x86,0x5a,0x2c,0xf1,0xe7,0x41,0xd,0x25,0x29,0x15, + 0x47,0x33,0xaa,0x92,0x97,0x5b,0x47,0x23,0xa6,0x34,0x86,0x9a,0xc1,0x69,0x3e,0x3e, + 0x34,0x61,0x5c,0x13,0xb6,0xec,0x4c,0x9b,0xa4,0xba,0x2,0xe0,0x87,0xf7,0x8f,0xf1, + 0xce,0xcf,0x1f,0xe1,0x5f,0xfc,0xf6,0x3b,0x7a,0xfb,0xd6,0xc1,0x72,0xd8,0x30,0x2a, + 0x71,0x9f,0x2a,0x77,0x6b,0xff,0xa7,0xaa,0xf2,0xe4,0xc5,0xa5,0x3c,0x78,0x7e,0x2e, + 0xf,0x9e,0x9d,0xe3,0xd3,0xa7,0xa7,0xf2,0xd1,0x93,0x33,0x79,0xf8,0xfc,0x2,0x8f, + 0x4f,0x2f,0xe5,0xe8,0xf8,0x2,0x4f,0xcf,0x2e,0x47,0x64,0x69,0x6b,0xec,0x7b,0x8d, + 0x2,0xd0,0xc3,0xec,0x91,0x26,0xcc,0xc9,0xba,0xc0,0x5c,0x0,0x53,0x43,0x51,0x18, + 0x71,0x51,0xa4,0xc8,0x83,0x93,0xb,0xb9,0xfc,0x70,0x27,0x9f,0x3e,0x3b,0xc7,0x9f, + 0xfc,0xf4,0xb6,0xbc,0x7a,0xe7,0x96,0xde,0x39,0x3c,0x90,0x91,0x47,0x4,0xb9,0xee, + 0x90,0x8b,0xab,0x9d,0x1c,0x9f,0x5f,0xe1,0xf1,0x8b,0x4b,0x79,0xf0,0xec,0x1c,0xd7, + 0xbb,0x60,0x43,0xdb,0x4b,0xf,0x4a,0x4d,0x53,0xcc,0x57,0xa4,0xd1,0x36,0x52,0x57, + 0x20,0x8b,0x2c,0x71,0x82,0x98,0x18,0xa5,0xe0,0xb5,0xfd,0xc7,0xf,0x8e,0xe4,0xf4, + 0x7a,0x27,0xff,0xf4,0x3b,0x6f,0xcb,0x77,0xbf,0xf6,0xa6,0xbc,0xf1,0xf2,0x2d,0x7d, + 0x78,0x72,0x81,0xef,0xfd,0xe2,0xb1,0x3c,0x39,0xbf,0x1a,0xa,0x5f,0xf,0x94,0x53, + 0x46,0x1c,0x8c,0xdd,0x22,0x18,0xee,0x24,0x1b,0xd8,0x26,0x91,0x4f,0x9f,0x5d,0xc8, + 0x8f,0x3f,0x7d,0x86,0x37,0x7e,0xfd,0xcb,0x7a,0xfb,0x56,0x16,0xae,0xfd,0x43,0xfe, + 0xaf,0x52,0xac,0xb6,0x3a,0x54,0xfb,0xeb,0x67,0xa7,0x97,0xf2,0xd1,0xd3,0x33,0xf9, + 0xf4,0xe9,0x19,0x3e,0x79,0x7a,0x2a,0x9f,0x3e,0xbb,0x90,0xa3,0x93,0xf9,0x4c,0x9c, + 0x5c,0xe0,0xd1,0xf1,0xa5,0x71,0xb3,0xa7,0x37,0x9c,0xf2,0xab,0xd0,0x2,0x26,0x2d, + 0xd6,0x40,0x79,0xc7,0x9,0x97,0xd7,0x1a,0xcc,0xa4,0x39,0x13,0xcb,0xae,0x28,0x78, + 0x4c,0x14,0x89,0x2c,0x7d,0xe9,0xae,0x8,0x61,0xca,0x4c,0xe,0x33,0x1b,0x4f,0xac, + 0xd5,0x1b,0xb9,0x6d,0x9a,0x81,0xd4,0x44,0x45,0xb4,0xb,0xe4,0xde,0xe3,0x33,0xdc, + 0x7b,0x72,0x2a,0xdf,0xfd,0xda,0x1b,0xba,0x6f,0xc5,0x60,0xbf,0xbe,0xd9,0xed,0xe4, + 0xd9,0xd9,0xb5,0x3c,0x3b,0xbf,0x92,0x47,0xc7,0x17,0xb8,0xff,0xec,0x5c,0x1e,0x9e, + 0x5c,0xc8,0xe3,0x17,0x97,0xf2,0xfc,0xfc,0x6,0x2f,0x2e,0xaf,0xe5,0xec,0xea,0x46, + 0x4e,0x2f,0x6f,0xe4,0xe4,0xe2,0x1a,0xcf,0xce,0xae,0xe4,0x6a,0x17,0xa2,0xcf,0x28, + 0xe4,0x28,0x47,0x58,0x84,0x2f,0x4a,0xf8,0xc1,0x37,0xef,0x4f,0xd8,0x1e,0xbb,0x19, + 0x26,0x44,0xe7,0xaf,0x15,0xe8,0x9e,0x45,0x6e,0x83,0x77,0xf4,0xa1,0x65,0xe,0xef, + 0x38,0xa8,0x13,0x9f,0x4,0x38,0xfe,0xfb,0x22,0x32,0x86,0xb6,0xdd,0xce,0xfe,0x79, + 0x8d,0x5b,0x3d,0x39,0x8b,0x89,0x6a,0x37,0x63,0xbb,0xee,0xc8,0xf5,0xd2,0x41,0x3d, + 0x51,0xd,0xdd,0xf0,0x5c,0x3,0x58,0x96,0xe7,0x3c,0x37,0x74,0x8e,0xdc,0x27,0xce, + 0xb8,0x5,0x67,0xbc,0xe9,0xc2,0x46,0xf7,0x34,0xb9,0xdd,0x4e,0x9e,0x9e,0x5d,0xcb, + 0xfd,0xe3,0x73,0x79,0x71,0xb3,0xc3,0x64,0xbd,0xc,0x43,0x38,0x5d,0xd6,0x70,0xf5, + 0xc5,0xfc,0xfe,0xba,0xc1,0x74,0xd4,0x2,0x24,0xed,0xd7,0x3c,0x11,0xe6,0xf7,0x9e, + 0xd2,0x75,0x8d,0x74,0x60,0xb4,0x42,0x4b,0xba,0x8c,0xb8,0xeb,0xf0,0xb3,0x87,0x47, + 0x7b,0xf0,0x25,0x9a,0xd3,0xd6,0x2e,0x76,0x5d,0xdf,0x7f,0x72,0x8a,0xff,0xf9,0xfb, + 0xf7,0xe4,0xc3,0x27,0x67,0xf2,0xcf,0xbf,0xfb,0x15,0xfd,0x47,0x5f,0x7e,0x55,0xe, + 0xf,0xe,0xfc,0xcc,0x8e,0xd5,0x82,0xc8,0x7f,0xf9,0x6b,0x5f,0xd4,0xab,0x1d,0xda, + 0xf,0x1f,0x1c,0xe3,0x83,0xa3,0xd3,0xb1,0x7e,0x6d,0xb6,0x91,0x9a,0x47,0x9,0xda, + 0xe8,0xca,0xe7,0xbe,0x5c,0x1b,0xb4,0x4b,0x98,0xb9,0x6d,0xb9,0xd2,0x7b,0x4e,0xc8, + 0x6,0xcd,0xd2,0xb5,0x89,0x76,0x84,0x61,0x61,0x1d,0xb1,0xf3,0x5,0x1f,0x49,0xf7, + 0x49,0x7d,0x4e,0x7c,0x15,0x4d,0x61,0x1f,0x99,0x1a,0xe7,0x71,0xaa,0x94,0xf0,0xe9, + 0xdc,0x8d,0xb4,0x32,0xdf,0x32,0xdc,0xce,0x82,0x7,0xad,0xe5,0x81,0x7d,0xad,0xfa, + 0xcc,0x22,0x56,0xf,0xbc,0x72,0xa4,0x9a,0x76,0xa2,0x1b,0xd9,0x1e,0x8d,0x5,0xdb, + 0xf1,0x70,0x9b,0x53,0x91,0x78,0xd3,0xb0,0x7d,0x51,0xa3,0xb,0xdf,0xb2,0x94,0x55, + 0xed,0x65,0x47,0x17,0x45,0x33,0xde,0x8f,0x7b,0x48,0xc6,0x37,0xdf,0xdd,0x8f,0xab, + 0xf2,0xb3,0x87,0x27,0x78,0xf9,0xa7,0xf,0xf1,0xce,0x17,0x5f,0xc6,0x77,0xbe,0xf6, + 0xa6,0xde,0x99,0xe0,0x8f,0xc3,0xe9,0xad,0x61,0xe8,0xa,0x1f,0xd2,0xbb,0x5d,0x97, + 0x1d,0x20,0x37,0xbb,0x2e,0x1d,0x90,0x9b,0x2e,0x72,0xb3,0x1b,0x5c,0xf3,0xf3,0xab, + 0x1b,0x79,0x7a,0x76,0x89,0x7,0xcf,0x2e,0xe4,0x17,0x47,0x27,0xf2,0xfe,0xa3,0x53, + 0x7c,0xf0,0xf0,0x58,0x3e,0x38,0x3a,0xa5,0x55,0x87,0x19,0x9e,0x6d,0x94,0x1e,0xf6, + 0x2a,0xf1,0x88,0x26,0xf6,0xf6,0xa5,0x90,0xdc,0xc4,0x5a,0x21,0xa6,0xe9,0xc0,0x13, + 0x82,0x7,0xd2,0x1e,0xb2,0x6c,0x46,0x18,0x79,0x7c,0x7e,0x85,0xc7,0xe7,0x57,0x1b, + 0xb2,0x44,0xf6,0x89,0x9b,0x78,0x47,0x45,0xf,0x18,0xa3,0x98,0x3a,0xc2,0xf9,0x8e, + 0x6b,0x34,0xc8,0xaa,0x65,0x82,0xe0,0x52,0x4f,0x5e,0x8,0xf8,0x9,0xd5,0x8d,0xab, + 0x38,0xdf,0xf8,0xcf,0x4e,0x2e,0xf1,0xe8,0xbd,0x7,0xb8,0xb8,0xd9,0xe9,0x83,0xe7, + 0x17,0xfa,0xd5,0x37,0x5e,0x92,0xf7,0x1f,0xbd,0xc0,0x5f,0xdd,0x7b,0x2a,0xcf,0x2e, + 0xae,0x67,0x39,0x3d,0x13,0x2e,0x24,0xe7,0xc2,0xc3,0xa1,0x3b,0x31,0xd5,0xa1,0xc1, + 0xb0,0x7f,0x4d,0x1f,0x3d,0x3d,0xc5,0xf7,0xee,0x3d,0xd5,0x6f,0x7c,0xe9,0x55,0xf9, + 0xf5,0x3b,0x87,0xcb,0x45,0xbc,0x75,0x51,0x7f,0x9e,0x2b,0x80,0xb,0x1,0x0,0xb2, + 0xdb,0x75,0xb9,0x1,0xe4,0x7a,0x37,0x30,0xa7,0xbb,0x5d,0x97,0xab,0xde,0xe5,0xc9, + 0xe9,0x95,0xdc,0x7f,0x7a,0x86,0x9f,0x3d,0x7c,0x21,0x3f,0x79,0xf8,0x1c,0x3f,0xfd, + 0xec,0x44,0x3e,0x7b,0x7e,0x41,0x16,0x33,0xb3,0x4,0xcd,0x10,0x8c,0x78,0xf9,0x31, + 0x3,0x4c,0xf2,0xce,0x5c,0xdd,0x4e,0x35,0xf7,0xbe,0xd,0x73,0xb3,0x89,0x70,0x9a, + 0xcd,0xa,0xcf,0x14,0xdb,0x4,0x30,0x49,0xef,0x7a,0xcb,0xe7,0xc0,0xc4,0x6b,0x28, + 0x4d,0x57,0xe2,0x80,0x65,0x8d,0xf2,0x94,0x29,0x8b,0x8a,0xdc,0x88,0xca,0x8f,0x3f, + 0x3b,0x96,0xaf,0xbf,0xf5,0x8a,0x7e,0xe3,0xad,0x57,0xe5,0xd5,0x97,0xc6,0x67,0x7b, + 0x7e,0x75,0x2d,0x67,0x57,0x5d,0x4e,0x2e,0xae,0x5d,0x12,0x76,0x71,0xd3,0xe5,0xe4, + 0xfc,0xa,0x8f,0x4e,0x2e,0xe5,0xe1,0xc9,0x85,0x7c,0xfc,0xf4,0x4c,0x3e,0x38,0x1a, + 0xea,0xf4,0xa3,0xb3,0x2b,0x54,0x1a,0xaf,0xed,0x9c,0x39,0xec,0x23,0x76,0xd0,0x76, + 0x1c,0x6a,0x4c,0xf9,0x2,0xd7,0x32,0x76,0xe9,0xa0,0x78,0xbb,0xd9,0x65,0x7a,0x97, + 0x6c,0xaf,0x1d,0xb,0xd8,0xda,0x74,0x98,0x2b,0x30,0xf6,0xef,0xd,0x22,0x7d,0xee, + 0xce,0x63,0x67,0xde,0x25,0x2e,0xd8,0x40,0x2a,0x38,0x31,0x6e,0x74,0xfc,0xd3,0xd7, + 0xed,0x59,0xe8,0xd,0x52,0x63,0x80,0x19,0xd8,0x25,0xfe,0x99,0x9a,0x8b,0x40,0x47, + 0xfa,0xb7,0x42,0xed,0xa2,0x6,0xad,0xa2,0x63,0x8d,0xd8,0x72,0x83,0xd8,0x74,0x49, + 0x46,0xb4,0xff,0x3d,0xbf,0xee,0xf2,0x93,0xcf,0x8e,0xf1,0xc9,0xb3,0xf3,0x71,0x5e, + 0xce,0x8a,0xc,0x42,0xe7,0xad,0x5b,0x4b,0xad,0xa8,0x1,0xc6,0x73,0xa4,0x10,0x45, + 0x17,0x28,0xba,0x59,0xf4,0xa0,0xd3,0xea,0x9d,0xe2,0x59,0x32,0x32,0xd8,0x93,0x30, + 0x45,0x85,0xc0,0x69,0x95,0x21,0xae,0xac,0xd8,0x66,0x2d,0xed,0x10,0x19,0x2a,0x20, + 0xb8,0xda,0x41,0xff,0xf6,0xfe,0x31,0x1e,0xbe,0xb8,0x92,0x3b,0xb7,0x54,0xae,0x76, + 0xd0,0x6f,0x7f,0xe9,0x15,0x79,0xf5,0xce,0xad,0x65,0x22,0xf4,0xc6,0xcb,0xb7,0xe5, + 0x1f,0xbf,0xf3,0xa6,0xfe,0xe6,0xd7,0xde,0xd0,0x27,0x17,0x37,0x78,0x76,0x7e,0x65, + 0x48,0x3d,0x31,0x1c,0xff,0x38,0xc8,0xe2,0x24,0x92,0x9e,0x53,0xb,0x60,0xd8,0xa5, + 0x89,0xae,0x4a,0xcb,0x1a,0xbb,0xc8,0x14,0x61,0x6,0x45,0x76,0x86,0x97,0x89,0x64, + 0x58,0xb5,0x29,0xb7,0xb8,0xde,0x7f,0x48,0xcb,0x70,0x71,0x55,0xbb,0x8,0x37,0x71, + 0xae,0x3f,0x58,0x52,0x39,0x3b,0xdf,0x1,0x59,0x3a,0x3c,0xd0,0xaf,0x68,0x54,0x9a, + 0x48,0x2b,0xbb,0xf3,0x30,0x18,0xa3,0xfc,0x83,0x62,0x95,0xf6,0x97,0x90,0xd5,0x69, + 0xa1,0xcc,0x43,0xaa,0x4a,0xfc,0x21,0x6f,0x34,0xf6,0x6b,0x63,0xab,0x6a,0x53,0xb5, + 0xa9,0xb6,0x4,0x34,0x7b,0xcc,0xa1,0x49,0xbd,0x8b,0x89,0x53,0xf4,0xb5,0xaf,0x40, + 0xe5,0xd9,0xc5,0x35,0x7e,0xf0,0xd1,0x93,0xfe,0xe4,0xec,0x1a,0xbf,0xf7,0x8d,0x2f, + 0xb6,0x3f,0xf8,0xf6,0x5b,0xfa,0xab,0x6f,0xbd,0xaa,0x5f,0x7a,0xf5,0x8e,0xdc,0xb9, + 0x75,0xb0,0x8,0x96,0x44,0x44,0x2e,0xaf,0x6f,0xe4,0xec,0xaa,0xcb,0xf3,0xb3,0x4b, + 0x79,0x76,0x76,0x85,0x27,0xa7,0x57,0x72,0x74,0x72,0x29,0x9f,0x9d,0x9c,0xcb,0xfd, + 0xa7,0x67,0x78,0x78,0x72,0x29,0x4f,0x4e,0x2f,0xe5,0xec,0x6a,0x87,0x9b,0x9b,0x2e, + 0x97,0xbb,0x2e,0xd7,0x37,0xbb,0x29,0x12,0xe1,0x3c,0x78,0x7a,0x36,0x74,0x38,0x27, + 0xbc,0x7b,0x88,0xf,0x15,0xba,0xb1,0xf0,0x84,0x5,0x3b,0xa9,0x26,0x3b,0x7f,0xf, + 0x2b,0xb1,0xf6,0xd,0xf1,0x5,0x87,0x87,0x99,0xa8,0x92,0xc5,0x96,0xe0,0x2a,0x4e, + 0xc9,0x8e,0x92,0x18,0xcd,0x21,0xec,0x4,0x5,0x36,0x68,0xb4,0x83,0x49,0xe4,0xa1, + 0x41,0xaf,0x4b,0xa,0x23,0x4d,0x42,0xf,0xf5,0xa2,0x63,0x7,0xc8,0xf7,0x3f,0x7a, + 0x2a,0x3f,0x7a,0xf0,0x1c,0x87,0x7,0x4d,0x2e,0xaf,0x21,0xe7,0xd7,0xd7,0x63,0xec, + 0xdf,0xa8,0xf3,0xf6,0xd5,0xa7,0xc5,0x5a,0x59,0x62,0x79,0x88,0xf5,0xa6,0x40,0xd3, + 0xe6,0x85,0xa2,0x22,0xfa,0x8b,0xa7,0xe7,0x72,0xf3,0xb3,0xcf,0xf0,0xad,0x2f,0xbd, + 0x2a,0xaf,0xdf,0xbd,0xad,0x6f,0xcf,0x3d,0xdc,0x2f,0x13,0xc8,0xed,0xc3,0xe2,0xd6, + 0xee,0xe7,0xe4,0x72,0x27,0xf7,0x8f,0xcf,0xe5,0xe3,0x27,0xa7,0xf8,0xf4,0xd9,0x99, + 0x7c,0xf2,0xec,0x5c,0x3e,0x79,0x7a,0x8e,0xa3,0xd3,0xb,0x39,0x39,0xbb,0x96,0x8b, + 0x5d,0xc7,0xf5,0xae,0xcb,0xe5,0x75,0xf7,0x67,0x62,0x76,0xbf,0xee,0x2e,0x33,0x4d, + 0x75,0x27,0x97,0x8d,0xb,0xac,0x8c,0x27,0x19,0xc9,0x94,0x44,0x1f,0xf3,0x9e,0x6a, + 0x5e,0x4,0xd6,0x2d,0x68,0xe4,0x79,0x39,0x18,0x26,0x9c,0xcf,0xc,0x97,0xe4,0x5a, + 0xce,0x7b,0x3d,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xfc,0x77,0x26,0xf,0xf2, + 0xc5,0x1e,0x9a,0x14,0xab,0x24,0x15,0x37,0x80,0xfc,0xf5,0x27,0xcf,0xe4,0xf5,0x97, + 0x6f,0xf7,0xff,0xf6,0xdb,0x5f,0x3a,0x78,0xed,0xee,0xa0,0x2f,0xde,0x7b,0x72,0x86, + 0x3f,0xfd,0xd9,0x43,0xf9,0x3f,0x7e,0xf4,0x19,0x4e,0xce,0x6f,0xe4,0xf6,0xe1,0x58, + 0x4d,0xf6,0xe9,0x81,0xbe,0xbe,0xe9,0xb8,0xde,0xd,0xe5,0xfa,0xf5,0xae,0xdb,0x7b, + 0xf,0x32,0x74,0xd8,0x4,0xf,0x14,0xcb,0x4e,0xa3,0xa,0xb8,0xa5,0x58,0x63,0x4c, + 0x1,0xcf,0xf9,0x84,0x5f,0xe2,0xf3,0x4b,0xed,0x2e,0x7c,0x33,0x96,0x50,0xf7,0xf3, + 0x36,0x2e,0xe7,0x2e,0x93,0xcd,0xde,0xe0,0x60,0x18,0x23,0xc0,0x41,0x9a,0x35,0xe9, + 0x30,0x8a,0x5c,0x9f,0x2c,0xf7,0x61,0x4c,0x73,0x5b,0x1a,0x8c,0xda,0xd7,0x27,0xac, + 0xa6,0x3b,0xf1,0xa8,0x31,0x30,0x2b,0xe8,0xcd,0xd0,0xd9,0x6c,0x19,0x8b,0x85,0xb0, + 0xd9,0x1a,0x78,0x4f,0x18,0x2,0x51,0xfd,0x90,0x0,0x7,0x8,0xa2,0xe9,0x20,0xe0, + 0x6d,0x68,0x7b,0xce,0xaf,0x76,0xf2,0xc3,0x7,0xc7,0xf2,0xd1,0xf3,0x33,0xb7,0xc3, + 0x61,0x4c,0x60,0x61,0x81,0xa1,0x31,0x76,0x37,0x42,0x4a,0xb3,0x71,0x7b,0x9f,0xe3, + 0x69,0x47,0xa6,0xc1,0x62,0x31,0x91,0xd5,0x51,0xdd,0x9d,0x93,0x8d,0x88,0xcb,0x73, + 0x6f,0x3d,0xe4,0x56,0xd4,0xa1,0x5b,0xe7,0xe2,0x31,0x5b,0xca,0xe2,0xda,0x4e,0x1f, + 0x95,0x5d,0x9d,0x8f,0x4e,0x2f,0xe5,0x5f,0xff,0xe5,0x3d,0xfc,0xf4,0xe8,0x54,0xff, + 0xc5,0x77,0xbf,0xaa,0xff,0xf5,0xaf,0x7d,0x51,0x5f,0x9b,0xce,0x22,0x7e,0x4f,0x5f, + 0xbe,0xd5,0xe4,0xf,0xbe,0xf5,0x25,0x7d,0x7e,0x7e,0xa3,0x7f,0xf6,0xe1,0xd1,0x14, + 0xb0,0xf9,0x58,0x2f,0x56,0x9e,0x76,0xb8,0x1c,0xcc,0x83,0xb1,0x63,0xda,0xbc,0x6c, + 0x1a,0xaf,0x2e,0x9d,0x0,0xad,0x94,0x35,0xd4,0x83,0xf3,0xb1,0x6d,0x5c,0xf,0x94, + 0x11,0xb6,0x6e,0x2a,0xc2,0x79,0xba,0xa9,0x44,0xf2,0x49,0xe3,0xd8,0x96,0xef,0xdc, + 0xc5,0xfe,0x56,0x66,0x1,0x15,0x13,0xcb,0xbb,0xf9,0x43,0x34,0x52,0x17,0xb3,0xfd, + 0x68,0xd3,0x5b,0xe7,0xba,0x33,0x5f,0xe5,0xf9,0xf,0x39,0x7d,0x5b,0x9a,0xd3,0xc7, + 0xc0,0x22,0x91,0x10,0xb6,0xa8,0xb1,0xf5,0xc7,0xf8,0x45,0x9c,0x6d,0xd5,0x28,0x45, + 0x6b,0xb0,0x97,0xa3,0x3a,0xd6,0xc9,0x5d,0x9e,0xc3,0xb,0x18,0x87,0x76,0x7a,0x29, + 0xed,0x2,0x3b,0xbe,0xdc,0xc9,0xdf,0x7d,0xfa,0x54,0x8e,0xaf,0x6e,0xfa,0xe3,0xd3, + 0x4b,0xfd,0xca,0x1b,0x77,0xf5,0x8d,0xbb,0xb7,0xe5,0xe5,0xdb,0x4d,0x6f,0xcd,0x4e, + 0xbd,0xcf,0xad,0xd8,0x4d,0x1f,0x4c,0xf7,0xf3,0xeb,0x1b,0x39,0xbb,0xda,0xe1,0xc5, + 0xc5,0xb5,0x1c,0x5f,0x5c,0xcb,0xb3,0xf3,0x6b,0x79,0xf2,0xe2,0x2,0x47,0x27,0x57, + 0xf2,0xfc,0xe2,0x26,0x80,0x52,0x49,0xb9,0x36,0xa1,0xbf,0x3e,0x4e,0x77,0xa4,0xc5, + 0xd4,0x15,0x91,0x60,0x47,0xe9,0xf2,0x94,0x24,0x3d,0x46,0xb5,0x34,0x50,0x77,0x6c, + 0x80,0xce,0xac,0x8c,0x17,0xd2,0x4d,0x90,0x1a,0x16,0xa0,0x87,0xb8,0xa4,0x90,0xc6, + 0x2c,0x33,0x7c,0xef,0x3d,0x24,0xf,0x66,0xad,0x80,0x8d,0x86,0xe0,0x49,0x1e,0x91, + 0x77,0x1b,0xb6,0xa,0xa5,0xd,0x51,0xc4,0x3a,0xf7,0x79,0xa4,0xc1,0x9c,0x57,0x6, + 0x5d,0x84,0xca,0xe9,0xcd,0x4e,0x4e,0xaf,0x77,0x1,0xcb,0x30,0x63,0x2c,0x39,0x73, + 0x10,0xd6,0x8d,0x71,0x4,0xb7,0xf4,0xe1,0x84,0x86,0x42,0x12,0x59,0x1e,0x22,0x90, + 0x4f,0x9e,0x5f,0xca,0x1f,0xbd,0xf7,0x99,0x3c,0xbf,0xb8,0x92,0xdf,0xfa,0x95,0x37, + 0xe4,0x9d,0x37,0x5f,0xd1,0x2f,0xdc,0xbd,0x25,0xaf,0xdd,0xbd,0xc5,0xf1,0x0,0x4b, + 0xd7,0x7e,0x79,0x7d,0x23,0x17,0xd7,0x5d,0xce,0xaf,0x6f,0xe4,0xf2,0x6,0x72,0x7e, + 0x7d,0x23,0xe7,0x57,0x37,0x72,0x7e,0xbd,0xc3,0xd9,0xe5,0x4e,0x8e,0x2f,0xae,0xe5, + 0xc9,0xd9,0x95,0x1c,0x9d,0x5c,0xe2,0xe8,0x74,0x30,0xf8,0x8f,0x5e,0x5c,0xc8,0xa3, + 0x17,0x97,0xb8,0xe9,0x6c,0x69,0x56,0xb7,0xd9,0x25,0x62,0x58,0xc4,0x72,0x91,0xb, + 0xc5,0x28,0x66,0xd6,0xb,0x9,0xcc,0xfc,0x3d,0xa7,0xf0,0x7e,0x59,0xd,0x90,0xff, + 0xe8,0xcc,0xbb,0xad,0xc3,0xed,0xa1,0xf1,0xf1,0x72,0xec,0x26,0xe7,0x41,0xc9,0x60, + 0x5e,0xfb,0x58,0x43,0xde,0x64,0x7,0xb2,0x72,0x76,0x26,0x88,0xda,0x18,0x27,0xcf, + 0xe5,0xe,0xf2,0xde,0xc3,0x13,0xf9,0xa3,0xf7,0x3e,0xeb,0xbf,0xf3,0xab,0x5f,0xd0, + 0xbb,0xb7,0xe,0xe4,0xcf,0xde,0x3f,0xc2,0x1f,0xff,0xf4,0x8,0x3f,0x79,0xf4,0x62, + 0xa3,0xb4,0x27,0x18,0x56,0x28,0xf2,0xfc,0xa2,0x2e,0x2a,0x60,0xc4,0x54,0x8e,0x1c, + 0x40,0xf6,0x8e,0x34,0x18,0xa7,0xb,0x25,0x24,0xd7,0x86,0x8,0xb0,0x2d,0xf7,0x78, + 0xf7,0xfa,0xbc,0xb0,0xc9,0x77,0x8e,0x18,0x27,0xcf,0x7c,0x2d,0x1e,0x9b,0xa3,0x2b, + 0x59,0xd6,0xec,0xf7,0x19,0x60,0x70,0xaa,0x31,0xbb,0x34,0x78,0xd,0x9,0xdb,0x85, + 0xcc,0xaf,0xa7,0x95,0x35,0x2b,0x6c,0xd,0x38,0xc4,0xd2,0x23,0xba,0x9b,0x2a,0x26, + 0x6d,0x30,0x7,0x35,0x7c,0x22,0xa3,0x98,0x45,0x2a,0xaf,0x1d,0x11,0x99,0x1d,0xa, + 0x69,0x2a,0x5d,0x55,0x9e,0x5f,0x5c,0xe3,0xd9,0xe9,0x95,0xbe,0xf6,0xd2,0xa1,0xf0, + 0x46,0xe9,0xec,0x7a,0x27,0x3f,0x7c,0x78,0x82,0x8f,0x9e,0x5f,0xb8,0x5d,0x4d,0xd5, + 0x74,0x17,0xe3,0xbf,0x33,0x6d,0xe9,0x90,0x71,0x95,0x99,0x23,0xbb,0xcf,0xc7,0x11, + 0xa2,0xda,0xa5,0xcf,0x22,0x33,0xdd,0xbd,0xe3,0xc4,0x37,0x94,0xa7,0xcd,0xe8,0x89, + 0x24,0xe2,0x17,0xf8,0x8c,0x35,0x6b,0xb6,0x1a,0xad,0xcc,0x89,0x34,0x99,0x34,0xd5, + 0x7b,0x6c,0xe2,0xb5,0x8b,0xe0,0xf9,0xd5,0x8d,0xfe,0xf9,0xbd,0xa7,0x80,0xaa,0x9c, + 0x5d,0x77,0xf9,0x9d,0x77,0xde,0xd0,0x5f,0x9b,0x41,0x34,0xf6,0x90,0xdc,0xbd,0x7d, + 0x28,0xff,0xf9,0xd7,0xde,0xd0,0x1f,0x7f,0x76,0xac,0x7f,0x76,0xcf,0xce,0xa,0xb5, + 0xbb,0x17,0xd3,0xec,0xed,0x2,0x39,0x5b,0x70,0x60,0xa6,0xde,0x41,0xe3,0x22,0x4, + 0x81,0xac,0x24,0x96,0xea,0x69,0xc7,0xc0,0x77,0xb0,0xeb,0x0,0x1a,0x13,0xf4,0x2, + 0xde,0x84,0xd2,0xf9,0x5a,0xd7,0xae,0x34,0xf5,0x16,0x4b,0x58,0x9b,0xc3,0x83,0xad, + 0xb8,0x33,0x4e,0xa1,0xe7,0xc,0x15,0xad,0xea,0xf8,0xd9,0x4,0x1d,0x9a,0xe8,0xca, + 0xe6,0xf6,0x4,0x68,0x20,0x59,0x7d,0x2c,0xf4,0xdd,0x4f,0xa7,0x34,0x86,0xd7,0x52, + 0x3d,0xb0,0xb6,0xbe,0x74,0xa2,0xb1,0x47,0x48,0xf9,0xb3,0x10,0xd,0xe5,0xa4,0x78, + 0x30,0x81,0x9a,0x2f,0x82,0x46,0x54,0xf3,0xe1,0x17,0x41,0xb7,0xc6,0xcd,0xc1,0x56, + 0x2d,0x9,0xf7,0x76,0xad,0xc9,0x87,0x4f,0x4e,0xf1,0xe1,0x93,0xd3,0x4a,0xbd,0x8f, + 0x3a,0x7,0xee,0xc1,0xe2,0x51,0x5,0xd,0xcf,0x50,0xba,0x9a,0x10,0x7f,0x69,0xce, + 0xa7,0xa4,0xa4,0x10,0xe5,0xc,0x46,0x9,0xd7,0x7,0xc3,0xbe,0x62,0xd2,0x89,0xb0, + 0xe,0x95,0xe9,0x88,0x10,0x8b,0x3a,0xfe,0x11,0x21,0x98,0xa2,0x75,0x97,0x19,0x18, + 0x98,0xb2,0x36,0x52,0x72,0xc7,0xe8,0xc0,0x35,0x4e,0xff,0xac,0xfb,0x50,0xee,0x61, + 0x1d,0x46,0xe1,0xa,0x68,0x90,0x30,0x4d,0xd2,0xbf,0xe7,0xcb,0x4c,0x5b,0x4,0xf4, + 0xd1,0x1,0xa9,0x26,0x81,0x7,0xe9,0x3c,0x38,0x4c,0x99,0x1e,0x52,0xe4,0x22,0x6, + 0x3e,0xb1,0x48,0x9d,0x25,0x31,0xde,0x59,0x22,0x2a,0x2a,0x5d,0xa0,0xff,0xe1,0xde, + 0x63,0xbc,0xfb,0xe0,0x39,0xbe,0xfb,0xd5,0xd7,0xf5,0xf7,0xbf,0xf1,0x45,0xf9,0xdd, + 0xaf,0xbf,0x29,0xdf,0xf8,0xe2,0xab,0xfa,0xe6,0xdd,0x43,0xb9,0x73,0x2b,0x23,0x5b, + 0xaf,0xae,0x6f,0xe4,0xf4,0x6a,0x27,0x8f,0xed,0xb2,0x7e,0x71,0x29,0x8f,0x4e,0x2e, + 0xe4,0xe8,0xec,0x4a,0x8e,0x5e,0x5c,0xe0,0xd1,0x8b,0x2b,0xf9,0xe4,0xd9,0xb9,0x3c, + 0x3f,0xbb,0x32,0x55,0x3a,0x5b,0x44,0x6c,0xf2,0x62,0x25,0x4d,0x82,0x8a,0xd8,0xcf, + 0x6d,0xee,0xa5,0xa7,0x13,0x18,0x1e,0xaf,0x89,0xf8,0x11,0xd1,0xe4,0xe,0xb4,0x4f, + 0x75,0x5e,0x15,0x4c,0x0,0xe7,0xb3,0x43,0xf3,0x9,0x23,0xeb,0x10,0x91,0xa9,0x62, + 0x42,0x9c,0x46,0xed,0x71,0xdc,0xe8,0xc0,0xa7,0x8d,0x9f,0x5c,0x97,0xd6,0x75,0x2a, + 0xbd,0xdc,0x2a,0x45,0x70,0xa7,0x3e,0x2f,0xa3,0xfb,0x27,0x17,0xf2,0x3f,0x7d,0xef, + 0x5e,0xff,0xd1,0xc3,0x13,0x7d,0xe7,0x8d,0xbb,0xfa,0xef,0x3e,0x38,0xea,0x3f,0x7b, + 0xf8,0x42,0x52,0xf0,0x7a,0x61,0xe3,0x77,0x49,0x8,0x4a,0x27,0xb9,0xf5,0xd8,0x1, + 0x40,0xe7,0x74,0xd3,0x7,0x8f,0x4,0x5c,0x8a,0x4b,0x65,0xfe,0xb5,0xbd,0x66,0xee, + 0x35,0x57,0x74,0x58,0x3d,0x3d,0x8b,0x9d,0x31,0xc4,0x45,0x8c,0xdd,0x2d,0x96,0x7c, + 0x6a,0x12,0xd4,0x7,0xf5,0x2e,0x6c,0x13,0x83,0xc2,0x4c,0xfb,0x89,0x17,0xd,0xd, + 0x8e,0x79,0x9d,0x20,0xdc,0xe9,0xe3,0xa6,0x55,0x9a,0xdb,0xf,0x72,0x75,0xeb,0xb2, + 0x74,0x22,0x29,0x7a,0x43,0x22,0x92,0x71,0xd6,0x2e,0xf6,0xb4,0x73,0xc0,0x83,0x3d, + 0xd,0xac,0xe1,0xdd,0x12,0x54,0xe4,0xe3,0xe7,0xe7,0xf8,0xf0,0xd9,0x29,0xbe,0xf3, + 0xf6,0xeb,0x7a,0x87,0x38,0xf9,0xcf,0x2e,0xae,0xf1,0xf3,0xa3,0x17,0x38,0xbe,0xda, + 0x41,0x4c,0xee,0x65,0xa3,0x6e,0x4e,0x1d,0xf1,0xae,0x5c,0x30,0x1b,0x6e,0x2b,0x24, + 0x7a,0x8c,0xe0,0xe7,0xf3,0xe5,0xef,0x57,0x3,0xe2,0xd9,0xb0,0xd9,0x81,0x8a,0x3f, + 0x5b,0x33,0x9a,0x74,0x6,0x96,0x76,0xd5,0x3e,0xcd,0x51,0xde,0xa1,0xab,0xb4,0xe6, + 0x9c,0xf2,0x58,0x25,0x44,0x52,0xa2,0x72,0x44,0x1d,0xf0,0xec,0xf2,0x5a,0xfe,0xcf, + 0x9f,0x3c,0x94,0xfb,0x27,0x17,0xf2,0xe8,0xc5,0xa5,0xfc,0xcb,0xff,0xe2,0x1d,0xfd, + 0x22,0x41,0xa3,0xee,0x1c,0x36,0xf9,0xd5,0x37,0x5f,0xd2,0xb7,0x5f,0x7b,0x69,0x3c, + 0x87,0xcd,0xc4,0xa,0xd3,0x1a,0x7c,0x80,0xc8,0xc4,0xa3,0x33,0x75,0x60,0x83,0xe6, + 0x3e,0x82,0x76,0xc7,0x48,0xff,0x1b,0x63,0x6d,0xbb,0xff,0xac,0xb2,0x8c,0x14,0x2a, + 0x13,0x6b,0x43,0x18,0xda,0xb4,0x34,0xc3,0x2c,0x5e,0x4b,0x2f,0xa8,0xa6,0xbc,0xb6, + 0x3c,0x56,0x47,0xe9,0xd0,0x4b,0xe7,0xcf,0x3a,0x47,0x52,0xac,0x1f,0x4e,0xbd,0xc0, + 0xd8,0x43,0x7b,0xd5,0x20,0xce,0xd7,0x6,0x99,0xa5,0xdd,0xf5,0x42,0xf9,0xd7,0x9a, + 0xc6,0xa,0x9a,0x95,0x53,0x9c,0xa2,0x45,0x2,0x6a,0x34,0xa3,0xba,0xf1,0xfe,0x7d, + 0xac,0xc3,0xc7,0xd8,0x70,0xa6,0x37,0x2a,0x65,0x69,0xcd,0x46,0x75,0xa0,0x8e,0xe7, + 0xc5,0x9e,0x32,0x8d,0x5b,0xae,0x23,0xe,0x82,0x9,0xb0,0x84,0x88,0x6b,0xdc,0x1c, + 0x50,0xde,0xd7,0xc5,0x94,0x18,0x24,0xd9,0xe7,0xea,0x32,0xd6,0x50,0x74,0x12,0x1b, + 0xa2,0x33,0xfc,0x2e,0x74,0xb6,0x23,0x79,0x54,0x61,0x4a,0x23,0xb5,0xaa,0xc,0x29, + 0x1d,0xc,0x19,0x7,0xec,0x3,0xee,0x40,0x35,0x6a,0x28,0x91,0x79,0x1a,0x19,0x8e, + 0x6,0x63,0xfb,0x82,0xad,0x6f,0x76,0x58,0x74,0x95,0x44,0xd6,0x12,0xfe,0x98,0xd2, + 0x1e,0x33,0x1c,0xa,0xa8,0xb0,0xa0,0x99,0x19,0x2e,0x60,0xb7,0x48,0x7c,0x8d,0x38, + 0x50,0x8d,0x7c,0x72,0x89,0x11,0x63,0x50,0x2c,0xa6,0x67,0xd,0x2b,0xd0,0x20,0x79, + 0xb1,0xd5,0xa2,0x43,0x92,0xe0,0x92,0x7,0xd8,0x34,0x1c,0xf0,0x7a,0xed,0xe4,0xaa, + 0xcb,0xf,0x3f,0x3b,0xc1,0xd1,0xd9,0xb5,0x7e,0xef,0xa3,0x67,0xfa,0xda,0x4b,0x87, + 0x78,0xe9,0xd6,0x81,0xe5,0xfb,0xf9,0x7f,0x67,0x8,0x6,0xbb,0x5c,0xdc,0x74,0x39, + 0xbf,0xda,0xc9,0xf9,0xf5,0x4e,0x2e,0x6f,0x76,0x38,0xbf,0xde,0xf9,0x5f,0x9f,0x5d, + 0x77,0xe9,0xe8,0x8,0x0,0x13,0x82,0x5d,0x2d,0x2d,0x5c,0x4c,0xda,0x62,0xbf,0x3b, + 0x2a,0x71,0x70,0xa7,0xda,0x3d,0x99,0x4a,0x13,0x24,0x46,0x4d,0x81,0x6e,0x3e,0xe8, + 0x2e,0x90,0x66,0x6a,0xe9,0x18,0x95,0xaa,0xcc,0xce,0x3d,0x26,0x44,0x88,0x1f,0x5d, + 0x9,0x91,0xf7,0x2a,0x5e,0xa7,0x34,0x9b,0x5e,0xcc,0x31,0xe1,0xe8,0x83,0x8b,0x35, + 0x96,0x9f,0x68,0x43,0x1f,0x6e,0x12,0xee,0xc4,0x8d,0x9f,0xef,0xc7,0x55,0x17,0x79, + 0x70,0x7a,0x89,0xeb,0x7b,0x4f,0xf5,0x47,0x2f,0x9d,0xc8,0xc3,0x93,0xb,0xb9,0xa6, + 0x0,0x8f,0x82,0xa,0x93,0x94,0xaf,0x2d,0x69,0x3d,0x13,0x5,0x51,0x1b,0x3e,0xb0, + 0xf1,0xf6,0x4c,0xd5,0x9a,0xa,0xf9,0xc9,0x1d,0x41,0x19,0xe3,0xb0,0x18,0x1d,0xb, + 0x20,0xe8,0x4d,0xc7,0x32,0xc2,0xc0,0x55,0xc1,0xc4,0x83,0x7d,0x78,0x43,0x85,0x38, + 0x47,0xee,0x16,0xb2,0xd2,0x42,0xe4,0x66,0xd3,0xbf,0x1e,0x9b,0x28,0xf8,0x1a,0x53, + 0x7d,0x91,0x3e,0xff,0x3d,0xf5,0xb3,0x7d,0x52,0x4d,0x10,0xcd,0x4d,0xf4,0x53,0xa0, + 0x6c,0x73,0x1b,0xa3,0xcf,0x14,0x42,0x43,0x9b,0x8c,0x1d,0x7e,0x13,0xff,0xd9,0x7, + 0x7e,0x75,0xe6,0x2b,0x33,0x18,0x67,0xbe,0xc0,0x5d,0x5,0x7f,0x7b,0xff,0x18,0x6f, + 0xbf,0xf6,0x12,0xbe,0xf3,0xf6,0xeb,0xde,0x4e,0x1c,0x5f,0xdc,0xc8,0x87,0x4f,0x4e, + 0x71,0x7c,0xb5,0xf3,0x71,0x7b,0x38,0x2,0x42,0xc,0x17,0xfe,0xfa,0xf1,0x35,0xc0, + 0x42,0x69,0x46,0xfd,0x5,0x40,0xbb,0x9,0xe4,0x78,0x18,0x88,0xc4,0xcc,0xb0,0xca, + 0xca,0x72,0x58,0x28,0xc,0xbb,0xe9,0x4c,0x1b,0x1f,0xa,0xe6,0x3e,0x1e,0x43,0x7b, + 0x39,0xba,0x85,0x76,0xf8,0xb5,0xa8,0xcd,0x0,0x0,0x62,0x71,0x80,0x2d,0x87,0x54, + 0xe3,0xbd,0xa3,0x53,0xb9,0xc1,0x67,0x38,0xbb,0xe9,0xfa,0x87,0xdf,0x7e,0x4b,0x7f, + 0x87,0xc4,0x99,0x2f,0xdd,0x3a,0x94,0x57,0x5e,0xba,0xa5,0xbe,0x3a,0x3e,0xc8,0xc5, + 0xe5,0xcc,0x60,0x9b,0xdc,0x77,0x6a,0x3c,0xe7,0xf8,0x5d,0xf,0x62,0x1c,0xa3,0x63, + 0x34,0x11,0x78,0xd7,0xb4,0x3f,0x57,0x91,0x83,0x9e,0x4e,0x47,0x69,0x94,0xe6,0xa8, + 0xf1,0xf5,0xc7,0x2b,0x99,0xe,0xdf,0xd4,0x7e,0x24,0xb5,0xfa,0x96,0x2d,0x76,0xab, + 0x30,0x90,0x2,0xf0,0xa2,0x26,0xd9,0x1a,0xae,0x43,0x34,0x15,0xa8,0x2e,0x87,0x62, + 0x47,0xa8,0xe9,0x7d,0xc6,0xbf,0xe1,0x97,0x86,0x66,0x7a,0x4d,0x1a,0x1b,0x4c,0x82, + 0x8d,0x68,0x2c,0xc5,0x94,0x2c,0x67,0x69,0x37,0x3f,0xba,0x41,0xe8,0x30,0x44,0xfb, + 0x48,0x6a,0x8c,0xa2,0x1a,0x72,0xaa,0xa9,0xda,0x88,0xd2,0x8c,0xd2,0x88,0x3f,0x17, + 0x36,0xa6,0x95,0x36,0x84,0x75,0x6,0xc5,0x1c,0x14,0x21,0x9,0xf5,0x22,0x43,0xec, + 0x4b,0xf2,0x36,0xdd,0x1d,0x52,0xe9,0x1c,0x48,0x8a,0x6b,0xab,0xc6,0x1b,0xe3,0xe2, + 0x8c,0x4e,0x35,0x2f,0x5e,0x7,0x5,0xcd,0x19,0x61,0xb,0xa1,0x49,0x74,0x99,0xab, + 0x38,0xc1,0x46,0xa6,0x8,0x5,0xb4,0x22,0x45,0xe1,0x85,0xc,0x1d,0x9a,0xf6,0x38, + 0xa,0x6,0x53,0x34,0x2,0x3d,0xf2,0x24,0x85,0x32,0x80,0x81,0x84,0x30,0x44,0x59, + 0xb0,0x83,0x73,0x37,0x6d,0x79,0x1b,0xc9,0x78,0x91,0x28,0x38,0x5f,0x72,0xda,0x89, + 0xf9,0xe5,0x3e,0xd1,0xe0,0x14,0x41,0x4,0x75,0xb6,0x14,0xd8,0x2b,0x69,0xd9,0xd1, + 0xcd,0x5e,0x87,0xa0,0xb,0x22,0xf4,0x5d,0xea,0x15,0x83,0x86,0x4f,0xc4,0x7e,0x75, + 0x72,0xbd,0x93,0x17,0x4f,0x4e,0xe5,0xfd,0x27,0xa7,0x58,0x24,0xa9,0xa8,0xf8,0xc4, + 0xa2,0xd3,0xa7,0x87,0xc6,0x3,0x86,0xe0,0xdf,0x35,0x15,0x17,0x5a,0xd1,0x98,0xa9, + 0xa3,0x1c,0x2d,0x30,0xd0,0x99,0x6,0x8a,0xd8,0x8f,0xbb,0x4a,0xba,0x9b,0x20,0x5b, + 0x21,0x7,0xb3,0x50,0xb1,0x0,0x90,0x39,0x52,0xee,0x2a,0xe5,0x90,0x1d,0xcf,0xbf, + 0x15,0xf,0x48,0x9f,0x40,0x74,0x52,0xa3,0x4b,0x1c,0xdf,0x89,0x31,0xad,0x47,0xca, + 0x4d,0x13,0x51,0xe9,0x7d,0xe0,0x37,0xda,0x54,0x94,0xf5,0x9,0x3f,0x97,0x88,0x69, + 0x9b,0x5,0x42,0x53,0xd9,0x89,0xc8,0xa3,0xf3,0x4b,0x3c,0x3a,0xbf,0x22,0x9f,0x31, + 0xdb,0xc2,0xcb,0xce,0x4f,0xa9,0x50,0x84,0xaf,0xe6,0x49,0x32,0x32,0x6f,0x7,0x65, + 0xd3,0x4,0x67,0x8e,0x4e,0x78,0x17,0x38,0x3c,0x44,0x1,0x5a,0xb3,0xdb,0xe7,0x10, + 0x47,0x8c,0x84,0xbf,0x3a,0xbc,0x42,0xa0,0xb0,0x72,0xf,0x5b,0x99,0xcc,0x74,0x98, + 0x6a,0x6e,0xee,0x13,0x1,0xe9,0x18,0x25,0x8f,0x4a,0x6f,0x26,0x50,0x74,0x8b,0xac, + 0x7f,0x7d,0x36,0xf0,0x4f,0x17,0x45,0x64,0xe,0x0,0x2d,0x44,0x4c,0xdd,0xc3,0x58, + 0x8c,0x63,0x62,0x56,0x35,0xe2,0x7c,0xb7,0x39,0x2a,0xb4,0x95,0xcd,0x18,0xc3,0x4f, + 0x7d,0xd0,0xf8,0xc,0x77,0xa2,0xfa,0xd3,0x27,0xa7,0x78,0xeb,0xd3,0xe7,0xf8,0xc3, + 0x6f,0x9f,0xe1,0x1f,0x7d,0xe9,0x55,0xbd,0xba,0xe9,0xf2,0xde,0xa3,0x63,0xfc,0xe8, + 0xe1,0x9,0x2e,0xcc,0x5f,0xef,0x92,0xef,0x98,0x42,0xf8,0x7b,0x6e,0x53,0x67,0xe9, + 0x7d,0x7e,0xc0,0xe3,0x32,0x1f,0xb9,0xe1,0x20,0xb8,0xdb,0x9c,0x66,0x44,0x8c,0x9c, + 0x28,0xaf,0x53,0x4d,0x74,0x3e,0x76,0x1c,0xf3,0x63,0xef,0xfe,0xd,0xda,0xc8,0x54, + 0xfd,0x63,0x68,0x59,0x2f,0x44,0x20,0x2b,0x7b,0x32,0x41,0xcf,0xee,0xfc,0x39,0x5f, + 0x76,0xc8,0xf,0x1f,0xbd,0x90,0x67,0x97,0x37,0x72,0xdd,0xbb,0xbc,0x7e,0xe7,0x50, + 0x7e,0xe5,0xf5,0xbb,0x7a,0xe7,0xb0,0xc5,0x11,0xd5,0x1a,0xc,0x35,0xe0,0x9f,0x2f, + 0xba,0xe0,0x40,0x45,0xfa,0xfc,0x5f,0x90,0x90,0xd0,0x76,0x60,0xb6,0x3b,0x9f,0x76, + 0x5,0x1b,0x1d,0x32,0x7e,0xd5,0x2f,0x3f,0x34,0xbf,0x5b,0xec,0xec,0xe9,0x34,0xa4, + 0xee,0x4,0xbe,0x4e,0xce,0xae,0xe5,0xa2,0xde,0xd8,0x8c,0x6b,0xc4,0x8c,0x2b,0xb2, + 0xbf,0x1c,0xfc,0x3b,0x35,0x23,0x64,0x6d,0xef,0x6a,0xff,0xeb,0x2a,0xf7,0xe4,0x21, + 0x2f,0xf8,0xb9,0x74,0x0,0x2e,0x58,0x38,0x95,0x9a,0x1,0xe5,0x5f,0x5c,0xf5,0xac, + 0xda,0x5b,0x6d,0xb8,0x47,0x16,0x87,0x59,0x5b,0xae,0x53,0x1c,0xd7,0xcc,0x56,0x31, + 0xf6,0x87,0xd3,0x69,0x63,0x33,0xb7,0x18,0xbf,0x8f,0x53,0xa5,0x8f,0xd8,0x37,0x61, + 0xaf,0xaa,0xf1,0x72,0x21,0xcd,0xc4,0x64,0x7c,0xd8,0x8d,0xb,0x5e,0x69,0x7f,0x43, + 0xb3,0xcb,0x74,0xde,0x43,0x9,0x2c,0xa9,0x60,0xeb,0x2,0x54,0x4d,0x2e,0x63,0xdd, + 0x43,0x4e,0xc1,0x32,0x21,0x13,0xd2,0x84,0xa5,0x8,0x99,0xd8,0x6b,0x18,0xdc,0xee, + 0x18,0x98,0x9b,0xca,0x2d,0xa2,0x41,0x59,0x5f,0xa1,0x28,0x21,0x8,0x3e,0xf2,0x6b, + 0xf9,0x12,0xb3,0xdd,0x2e,0x81,0x10,0x78,0x1,0x44,0x44,0xd5,0xc8,0x56,0x42,0x75, + 0xa7,0x8d,0xb1,0x28,0x9d,0xd0,0xee,0x88,0x92,0xf9,0x79,0x62,0x1a,0xdb,0x23,0xc7, + 0x40,0x9,0xa2,0xa8,0xf6,0x35,0x4e,0xc1,0x2f,0x89,0x4f,0xe7,0x21,0xae,0xc1,0x19, + 0xc8,0xd3,0x8e,0x6e,0xab,0x6f,0x18,0x94,0x83,0x67,0x98,0x6d,0x8a,0x5a,0x79,0x7, + 0x4f,0x42,0x7e,0x90,0x18,0xae,0x49,0x7a,0xb0,0x5d,0xb4,0xe6,0xf0,0x12,0x56,0x93, + 0xda,0x17,0xdd,0x91,0xba,0xcf,0x90,0x8c,0xba,0x34,0x1,0xfe,0xc2,0xb5,0xe8,0xbc, + 0xad,0xa6,0xb4,0x54,0xf7,0xd9,0xf0,0x91,0x2b,0x62,0xec,0x3b,0x69,0xfd,0x37,0x26, + 0x18,0x76,0x59,0x35,0xc,0xf2,0x28,0x8f,0x93,0x7d,0xcd,0x3,0xf7,0x6e,0xc5,0xf3, + 0x64,0x45,0xed,0x5c,0x17,0x9a,0x1a,0xb,0x30,0x33,0x8d,0x34,0xd7,0x56,0x36,0x19, + 0x9c,0x8d,0xae,0x7,0xd2,0xfc,0x5d,0xb2,0x97,0xcd,0x33,0x3f,0xd9,0xa2,0xaa,0x8b, + 0x17,0xd7,0x5a,0xd1,0xee,0xda,0x4,0x45,0xda,0x27,0xfa,0xd0,0xab,0x89,0xf4,0x18, + 0x7e,0x75,0xf3,0x71,0xab,0xb0,0x81,0x9d,0xe9,0x46,0x43,0x71,0xd9,0x3c,0x9b,0xdc, + 0x27,0xa6,0x1e,0x77,0x1a,0xe5,0x17,0x40,0x97,0xb7,0x8f,0x94,0x63,0x6a,0x3a,0xbf, + 0xa5,0xf9,0x99,0xdb,0xf0,0x62,0x2c,0x96,0x47,0xd3,0x0,0xc7,0xb9,0x8a,0x1c,0xcc, + 0xbf,0x6a,0x10,0xe9,0xd,0x16,0x58,0x32,0x2,0xba,0x8,0xd9,0xc1,0x53,0x49,0xb2, + 0x67,0x93,0xbe,0xc5,0x38,0x19,0x6,0xd5,0x1a,0x2c,0xf8,0x46,0xf6,0xb0,0x26,0xbe, + 0xe3,0x96,0x83,0x81,0x16,0x97,0x3,0x16,0x82,0xab,0x23,0xde,0xbb,0xa8,0x9c,0xed, + 0xba,0xfc,0xe8,0xe8,0x45,0xff,0x37,0x3f,0x7c,0x20,0xff,0xf4,0xdb,0x6f,0xb5,0xaf, + 0xbf,0x7e,0x57,0xbe,0xff,0xc9,0xf3,0xfe,0x97,0x9f,0x3e,0xc7,0x55,0x7,0xc6,0x99, + 0x3e,0x31,0x6e,0xb1,0xa6,0x1,0xac,0xb,0xf,0xe6,0x8a,0x15,0x2b,0x43,0x14,0x37, + 0x74,0x48,0x9d,0xce,0x2c,0x47,0xc3,0x52,0x40,0xaf,0x78,0x2c,0xaf,0x8f,0xcb,0x9b, + 0x5,0x4a,0xab,0xea,0xf4,0xa2,0x53,0x48,0x47,0x1f,0xf6,0xfb,0x26,0x86,0x29,0x6f, + 0xda,0x38,0x40,0x8,0x29,0x81,0xb4,0x44,0x48,0xcf,0x47,0x58,0x44,0xe5,0xfe,0xe9, + 0x15,0xfe,0xed,0x7b,0xf,0xf5,0xde,0xf3,0x73,0xfd,0x57,0xbf,0xfb,0xf5,0xf6,0x5f, + 0x7d,0xfd,0xb,0x7a,0x71,0xb3,0x93,0x93,0xab,0xdd,0x8,0x90,0xe9,0x3c,0xda,0x76, + 0x70,0x3d,0x70,0xd0,0xe6,0xe1,0xdd,0x21,0xb1,0x8e,0x89,0xe,0x5e,0x3,0x23,0x34, + 0x84,0xf,0x88,0x77,0x29,0x92,0x1a,0x25,0xc1,0xed,0xdb,0x76,0x4a,0xda,0x36,0x54, + 0x86,0x9,0x98,0x34,0xc5,0x29,0x7f,0xdf,0x1c,0x5b,0xe1,0xe6,0x59,0xa9,0x63,0x5d, + 0x3,0x83,0xdd,0xb3,0x44,0x6d,0xc4,0xa7,0x8e,0x51,0x45,0xb4,0xf,0xf0,0x6c,0xea, + 0xea,0x89,0x96,0x1c,0x2d,0x2f,0x6c,0x21,0x6a,0xb,0x84,0xc6,0xc3,0xb,0x53,0x5a, + 0xf6,0xfc,0xb1,0x7b,0x7,0x6b,0x52,0x9d,0x16,0x7e,0xec,0xd9,0xa1,0x8b,0xcd,0x64, + 0x9b,0x6,0xf8,0x41,0xb5,0x2b,0xa4,0xa1,0xb5,0x79,0xc1,0x4b,0x17,0xd5,0xc6,0x97, + 0x6b,0x86,0x18,0x20,0xf6,0x33,0xf0,0xb5,0x88,0xa6,0x11,0x60,0xf2,0x57,0xcf,0xf, + 0xb6,0x69,0x41,0xee,0x21,0x26,0x2f,0x62,0xab,0x8,0xcc,0xcb,0xbc,0x23,0x44,0x50, + 0xea,0x69,0x4f,0xc1,0x98,0xb0,0x9d,0xe1,0xd8,0xf1,0x99,0x90,0x5b,0xc9,0xde,0xf, + 0xcd,0x3d,0xe2,0x4c,0xd3,0x20,0x26,0xa3,0x5a,0xb2,0xf,0xf,0xb1,0xcd,0x89,0x11, + 0xa5,0xec,0xb0,0xb7,0x81,0xf6,0x76,0x1c,0xce,0xe5,0x62,0x27,0xa4,0x12,0x3b,0x75, + 0x27,0x11,0xa5,0xcd,0xa2,0x73,0x76,0x31,0xd8,0xd,0x4f,0xc5,0x82,0x5d,0xd0,0x4d, + 0x9c,0x6e,0xa5,0xe9,0xdb,0xb1,0xdf,0xa1,0x8d,0xc6,0x11,0x4a,0x5b,0x19,0x57,0x33, + 0x4f,0x1d,0xc0,0xec,0x6a,0xa2,0x91,0x77,0x8c,0x5d,0xfa,0xf3,0x69,0x91,0x3,0x13, + 0xe0,0x45,0x21,0x33,0xa,0xee,0x8d,0x7d,0x95,0x7a,0x65,0xa3,0x2e,0xc5,0x5,0xea, + 0x74,0xab,0xec,0xaf,0x32,0xa8,0x1,0x5c,0x27,0x61,0xe,0x4a,0x7c,0xec,0xe1,0xdd, + 0x50,0x8c,0x7b,0xa3,0x3b,0x32,0xc5,0x9b,0xd7,0xa,0x73,0xf4,0xc9,0xf8,0x66,0xb8, + 0xa5,0xa,0x2,0xca,0xde,0x6,0x76,0xdc,0xc0,0x78,0x11,0xa9,0xe1,0x31,0xa5,0x50, + 0xf4,0x71,0x98,0xaa,0x11,0xc6,0xc6,0x1d,0x3a,0x84,0xbd,0x6d,0x64,0xb1,0x4c,0x7b, + 0xf4,0x81,0x4a,0x17,0xe9,0xd,0x73,0xd4,0x15,0x99,0x1a,0xc,0xaf,0x70,0x37,0x43, + 0x19,0x2e,0x47,0x3c,0x57,0x6b,0xec,0x8c,0xc,0x65,0xfb,0xd0,0xe8,0x8c,0x1f,0xfb, + 0x41,0xa3,0xd6,0x1a,0xd9,0xc6,0xe9,0xa6,0x8,0xd,0xdd,0x27,0xe5,0xbe,0x77,0xef, + 0xad,0xfc,0x19,0xf,0x9b,0xd9,0xec,0x9c,0x15,0x9a,0x48,0x6f,0xfe,0xf9,0x4,0x80, + 0xcb,0x3b,0x4f,0x2b,0x58,0xe7,0xc4,0xc,0x44,0xa5,0x41,0x60,0xc9,0x15,0x38,0x10, + 0x2b,0xcc,0xc7,0x21,0x7a,0x50,0x45,0xad,0xac,0x38,0xa2,0x9f,0x89,0x29,0x1d,0x5b, + 0x84,0x11,0x22,0x8,0xe3,0x13,0x9c,0x45,0x5b,0xa5,0x79,0xd6,0xa9,0xdb,0xc8,0x82, + 0xcd,0x15,0x45,0xfb,0xf8,0xbc,0x8f,0xce,0xaf,0xe4,0xdf,0xdd,0x7b,0xd2,0x9f,0x9c, + 0x5f,0xe3,0xab,0xaf,0xdf,0xd1,0xbf,0xfc,0xf8,0x59,0xbf,0x77,0x7c,0x81,0x6b,0x30, + 0xb7,0xc0,0x89,0x83,0x61,0xcd,0x1b,0x35,0x76,0x87,0x5f,0xd8,0x63,0xc4,0xe,0x4c, + 0x61,0xe0,0xb8,0x97,0xc7,0xfa,0xc1,0xc4,0x85,0x2,0x6c,0x5c,0x56,0x86,0x6d,0x84, + 0xb5,0xfc,0x6a,0x87,0xc8,0x38,0x4,0x47,0x12,0xf9,0x38,0xbc,0x5a,0xd7,0xa1,0x41, + 0xd7,0x7c,0xb1,0xeb,0x1c,0xd3,0xf9,0xc2,0x6d,0x4,0xd8,0x38,0x43,0x61,0x7c,0xb5, + 0xcd,0xe9,0x74,0x72,0xff,0xfc,0xa,0xa7,0x9f,0x3c,0xc3,0xeb,0x77,0x6f,0xe3,0x27, + 0x4f,0x4e,0xdb,0xc5,0x75,0xc7,0xf7,0x3f,0x7d,0xde,0xbb,0xd2,0xca,0x62,0xd4,0x8e, + 0xae,0x45,0x89,0x9c,0x84,0x16,0xa,0xb8,0xec,0x34,0xb,0xb5,0x2a,0xa7,0x3d,0x3a, + 0xbd,0x68,0xae,0x4,0xfb,0xf8,0x5f,0x57,0xc1,0xfb,0xef,0x45,0x22,0x7a,0x3a,0xdf, + 0x9d,0xd5,0xec,0x65,0x84,0x9e,0xd2,0x39,0x74,0x8e,0x73,0x8a,0x8,0x2e,0x81,0x66, + 0xca,0x2a,0x1b,0x45,0x41,0xe7,0x7f,0xd6,0x77,0xfe,0xc7,0xff,0xf5,0x7,0xae,0xfa, + 0xc5,0x3e,0x64,0x33,0xa4,0x2,0x8a,0x83,0xbc,0xb8,0xa5,0xcd,0x4b,0x63,0xc8,0x8c, + 0x29,0x17,0xba,0x7d,0x93,0x15,0x58,0xdb,0x84,0x28,0x4c,0xd,0x9c,0xce,0xe3,0xb8, + 0xb5,0x61,0xd6,0x68,0x2a,0x4d,0xda,0x30,0x6d,0xce,0xdf,0xb,0x6d,0x73,0xb2,0xdc, + 0x92,0x7,0x84,0xd2,0x5a,0xd4,0xdf,0xa5,0x65,0xae,0xa0,0xe0,0x5b,0x47,0xf9,0xb1, + 0x55,0xf2,0xc9,0x86,0x86,0xa5,0x23,0x5b,0x76,0x69,0xc3,0x7,0xbe,0x8,0x4d,0x64, + 0x13,0xb,0x28,0xd4,0x2,0x2e,0x7e,0x5f,0x99,0x10,0x6c,0xfa,0xc7,0x65,0xc9,0xa9, + 0x25,0xda,0x4b,0xe,0xb1,0x63,0x7d,0x83,0xd8,0xb,0xb1,0x44,0xd5,0x77,0x14,0xe, + 0xa0,0xc8,0x16,0x3b,0x2,0xd9,0x4a,0xa4,0x59,0x3c,0xa2,0x1a,0xd5,0x49,0x48,0x7e, + 0x94,0x81,0x78,0xe1,0xbb,0xf1,0x7f,0xc5,0x6f,0x2e,0xa5,0x2c,0xa9,0x4a,0xeb,0xa3, + 0x75,0x83,0xf2,0x6,0x55,0x95,0x3f,0x2b,0xa5,0x80,0x61,0xef,0xb1,0x95,0xd6,0x2a, + 0x8e,0x1c,0x23,0xad,0x87,0x22,0xdb,0xfd,0x56,0x81,0x76,0x75,0x78,0x82,0xf9,0xbc, + 0xb3,0x62,0xa2,0x59,0x4e,0x29,0xc8,0xd5,0x17,0x8e,0x28,0x2b,0xb0,0x81,0x3,0xe7, + 0xb1,0x3c,0xac,0x3,0x32,0x43,0x1b,0x20,0xcc,0x12,0xb7,0x79,0xe0,0xb8,0x4e,0x26, + 0xec,0xc4,0x11,0x1e,0x24,0xb7,0x40,0x26,0x5f,0x86,0xc6,0x88,0x65,0x33,0x3a,0x81, + 0x26,0x6d,0x8a,0x9a,0x54,0x21,0x6d,0xe4,0x54,0x4c,0xef,0x48,0xb3,0x77,0x52,0x5b, + 0x52,0x30,0x4b,0x74,0xea,0xa4,0x23,0xd,0x57,0x5,0x55,0xff,0xd1,0x96,0x46,0xad, + 0xcc,0x72,0x93,0x20,0x62,0x49,0x8a,0x39,0xd,0x55,0x7f,0xb0,0xd1,0xe9,0x3b,0x8a, + 0x15,0x2e,0xc4,0x23,0x4b,0x69,0x89,0x81,0x14,0xc,0x36,0x85,0x6b,0x88,0xbf,0x32, + 0x4f,0x52,0xa,0x65,0x61,0xc9,0xcb,0x10,0xd5,0x75,0xfe,0xfb,0x66,0x31,0x4f,0x7a, + 0xaa,0x84,0x34,0xe4,0xd1,0xa9,0x86,0xed,0x43,0x19,0xac,0x32,0x17,0xcb,0x96,0x36, + 0x80,0xa6,0xad,0x89,0x34,0xa8,0xb4,0x36,0xc2,0x2a,0xe8,0xd7,0xd2,0x74,0x70,0x5f, + 0x75,0x20,0x37,0xda,0xc4,0xb5,0x43,0x65,0x8,0xca,0x4a,0xe,0xf5,0xc2,0x28,0xe3, + 0xf7,0xd5,0xd9,0xf4,0xd6,0x1b,0xc0,0x92,0xe3,0x6,0xf8,0x16,0x32,0xec,0xf8,0x7d, + 0xc4,0x8c,0x75,0x84,0xf1,0x7,0xd0,0x81,0x9b,0x1,0xd7,0xd0,0xdd,0x9d,0xb,0x81, + 0x25,0xa2,0x81,0x58,0x9c,0xbd,0xe3,0x7b,0xb1,0x2e,0xbd,0x69,0xf3,0xe4,0xb5,0x36, + 0x87,0xa2,0xea,0x9d,0xba,0xdb,0x2a,0x28,0x62,0x33,0xee,0x6,0xbe,0x1,0x75,0xe3, + 0x9a,0x41,0x71,0xa4,0xfa,0xb3,0xa0,0x98,0x2,0xbf,0x1,0x66,0xef,0x32,0x4,0x94, + 0x7d,0xcc,0x57,0x86,0xc3,0x52,0xd0,0x77,0x18,0xdf,0x67,0xc7,0x40,0xb8,0x77,0xff, + 0x6c,0x26,0x72,0x6,0xc1,0x5b,0x85,0x93,0xee,0x29,0x1f,0x37,0xac,0x7d,0x9c,0x73, + 0x9d,0x5b,0xc1,0xca,0x76,0xaf,0x20,0x39,0x6,0xc6,0x68,0x15,0x99,0x6e,0x64,0xa6, + 0x6b,0xed,0x2a,0x88,0x50,0x72,0x38,0xea,0x23,0x2d,0xd5,0x41,0x41,0xde,0xd9,0x9b, + 0xdc,0x4a,0xd0,0x3a,0x62,0x3c,0xb2,0x97,0x79,0x2d,0x1c,0x8d,0x94,0x72,0x59,0x79, + 0x54,0xe8,0xdf,0x1e,0x6c,0xa4,0xdc,0x80,0xb1,0xb3,0x18,0xb8,0x45,0xf3,0x8f,0xcc, + 0x22,0xb0,0x8b,0x4a,0xc3,0x98,0x40,0x35,0xd1,0x16,0x23,0x44,0x4d,0x66,0x83,0xb9, + 0x37,0x8c,0x26,0xdd,0x56,0x56,0xb6,0x76,0x6,0x7f,0x90,0x15,0xbd,0xe7,0xef,0xe1, + 0x7c,0x60,0x1a,0x5d,0xda,0x81,0xc8,0xb,0xa,0x88,0xba,0xf0,0x1a,0xe1,0x74,0x50, + 0x48,0xd,0xcf,0x89,0x80,0x22,0xda,0x4d,0xe7,0xd7,0x32,0xee,0x90,0x1c,0x41,0x66, + 0x50,0x5c,0xcc,0x16,0x4b,0x9a,0xf3,0x2d,0x3d,0xe3,0x83,0xf,0xdc,0x82,0x6c,0x14, + 0x56,0xac,0xa6,0xe4,0x3e,0x49,0x4b,0x1b,0xf8,0x54,0xa0,0x7b,0x7,0x9f,0x3,0x0, + 0x1b,0xb1,0xa6,0xad,0xc5,0x60,0xaf,0xa1,0x2a,0xc9,0x2e,0x42,0x38,0x93,0x2a,0x22, + 0xd,0x6,0x29,0xab,0x35,0x67,0x67,0x3e,0x1,0x35,0x9,0xca,0xa0,0x31,0x32,0x87, + 0x39,0x50,0x28,0xa,0x50,0xa9,0xd9,0x8e,0x9f,0xb3,0xd,0x90,0x12,0x45,0x2d,0xeb, + 0x14,0xdc,0xa2,0x67,0x3f,0x56,0xaf,0x39,0x29,0x37,0x18,0x46,0x7a,0xf3,0x1f,0xa2, + 0xa4,0x88,0xd3,0x40,0xcc,0x8f,0x29,0xb7,0x20,0xec,0x67,0xe3,0x47,0xdd,0x2c,0x5f, + 0x9b,0x40,0x28,0x82,0x50,0xb8,0xab,0x45,0x5c,0x61,0xaa,0x54,0x89,0xde,0xe5,0xa3, + 0xe4,0x74,0xc1,0x81,0x5c,0x17,0x4,0x6e,0x42,0xc0,0x61,0x10,0x9,0x58,0xe3,0xa6, + 0xe9,0xd3,0x92,0xd0,0xa0,0xd3,0x85,0xab,0xda,0xa4,0xd,0xc2,0xf5,0x14,0x3c,0xda, + 0xd9,0x3d,0x7c,0x53,0x1a,0x2,0x2,0x76,0x33,0xa0,0xd6,0x9b,0x6d,0xb6,0x64,0xcd, + 0x17,0xe1,0xfe,0x8a,0x93,0x75,0x93,0xec,0x64,0x34,0x91,0xe1,0x49,0x11,0x28,0x44, + 0x24,0xaa,0xd7,0xb1,0xeb,0x6e,0xfe,0x2,0x21,0x7a,0x74,0x5b,0xbf,0x59,0xdd,0x64, + 0xda,0x66,0xff,0x4d,0x18,0xb1,0xa8,0x7d,0x46,0xad,0xb8,0xa8,0x76,0x6c,0x5a,0x69, + 0x9a,0xe6,0xd,0x26,0x55,0x97,0x3d,0x5b,0xed,0x10,0x7d,0x79,0x4a,0xbb,0x0,0x54, + 0x74,0x99,0xb0,0xd2,0x7e,0x53,0x62,0x7d,0x91,0x1c,0x3b,0x32,0xbd,0xee,0xa2,0xa4, + 0x7,0x70,0xdd,0x90,0x46,0xf0,0xe,0xcd,0xda,0x72,0xad,0xf,0xdf,0xeb,0xc6,0xbe, + 0x1f,0x3c,0x32,0x1f,0xbf,0xee,0xc6,0x45,0x13,0xcc,0x95,0x2f,0x66,0xcb,0x89,0xb1, + 0xe3,0xe9,0xb3,0x11,0xd1,0x3e,0xdf,0x2e,0x5a,0xeb,0xb0,0x16,0x4b,0x29,0x23,0x60, + 0x4,0xa0,0xf4,0x2c,0xde,0x9e,0x1a,0x72,0x9b,0xbf,0xcd,0x90,0x94,0x26,0xd2,0x2d, + 0xc6,0x6f,0x14,0x96,0x1d,0x6d,0xc2,0xa7,0x59,0x20,0x2d,0xb6,0x2a,0xa2,0x38,0x4a, + 0x4f,0x37,0xd7,0x6a,0x8a,0x94,0xc0,0xd4,0xce,0x77,0x64,0x8e,0x81,0xfb,0x74,0x33, + 0xcc,0xf,0xd6,0x9d,0xc,0xdd,0xd8,0xf5,0x46,0xca,0x9c,0xe5,0x9e,0xc3,0xb6,0xba, + 0x45,0xff,0xcc,0x14,0xbc,0x59,0xe8,0x29,0xf2,0xf9,0xa1,0xa9,0xc5,0xd7,0x85,0xa4, + 0x49,0x42,0xe3,0xd4,0x51,0x25,0xa6,0x7b,0xb2,0x56,0xe5,0x20,0x7a,0xd1,0x2a,0xa8, + 0x42,0x5d,0x1,0xc7,0x75,0x3a,0xc7,0xbe,0x43,0x14,0xc7,0xc2,0xd4,0x85,0xd3,0xce, + 0xca,0x6b,0x8a,0x77,0xe3,0xf6,0xad,0xc,0x8c,0x91,0xb1,0xb6,0xca,0x21,0x59,0xa0, + 0xf4,0x1e,0xcd,0xa4,0x9d,0xa9,0xec,0x74,0xb9,0xa0,0xe8,0x81,0xa3,0x94,0xc6,0xcc, + 0x72,0xec,0x1a,0xfb,0x14,0x57,0xf4,0x59,0xd1,0x76,0xa8,0xd1,0x1c,0x6c,0x37,0x8, + 0x36,0xd3,0x72,0xb,0xaa,0x9d,0x56,0xa5,0xbe,0xe4,0x9f,0xfb,0xbf,0x4,0x59,0x69, + 0xcb,0x5c,0x81,0xbd,0xe4,0x99,0x75,0xec,0x8d,0x8a,0xef,0x13,0x92,0x78,0xc9,0x38, + 0xdd,0x12,0xe1,0xa9,0x53,0xc9,0x6c,0xc8,0x6,0x5d,0x60,0x7e,0xa1,0x30,0xf6,0x10, + 0xb9,0x44,0xff,0x20,0x68,0x5,0x49,0x9c,0x5b,0xc8,0x8b,0xb5,0x52,0xfd,0xc,0xd4, + 0x52,0xac,0xee,0x91,0xba,0x13,0x13,0x5,0xe7,0x9c,0x4c,0x8b,0x37,0xa3,0x8,0x43, + 0xd0,0xe3,0xde,0x32,0x75,0x67,0x9b,0xad,0x50,0x54,0x49,0xa,0x90,0xd5,0x6e,0x29, + 0x52,0x88,0x67,0x7,0xba,0x39,0x9a,0x40,0xfa,0xbe,0x11,0x16,0x8c,0xb0,0x85,0xa9, + 0x96,0x77,0xc7,0xf2,0x1,0x27,0xbc,0x48,0xd3,0x38,0x9d,0x5d,0x1a,0x2c,0x72,0x63, + 0x15,0x3e,0xbd,0x98,0xf3,0x60,0xe3,0xf,0x8c,0x5b,0x4f,0x6b,0x5f,0xd2,0xeb,0x0, + 0xe5,0x48,0x4a,0x65,0x44,0x80,0x1d,0xdc,0x52,0x93,0xbd,0xbc,0xa3,0xa,0x38,0x11, + 0x22,0xbb,0xdb,0x84,0x5b,0x24,0xaa,0xcb,0x7c,0x20,0x24,0x61,0xa7,0x3a,0x64,0x78, + 0x1a,0x65,0x61,0x22,0x25,0x85,0x68,0x1b,0xb2,0x37,0xed,0x24,0x52,0x9a,0xbf,0x96, + 0x1e,0x7e,0xe2,0x29,0x49,0x1d,0xad,0xce,0xec,0xd0,0xfd,0x1,0xd2,0x24,0xe0,0x25, + 0x8d,0x8d,0x59,0xc2,0xad,0x53,0xef,0x31,0x8f,0x86,0x92,0xa8,0x34,0xf2,0xc7,0xa7, + 0x1d,0x8c,0x47,0xed,0x9a,0xa2,0x4,0xd0,0x27,0xc4,0xc5,0xc5,0xa4,0x3d,0x5f,0xd6, + 0x11,0x2b,0x3b,0x35,0x29,0x4d,0x90,0x23,0x67,0x23,0xa8,0x45,0xc4,0x7d,0xfe,0x51, + 0xc,0x45,0xda,0x9a,0x58,0x17,0x86,0x16,0x11,0xb6,0xa8,0xdd,0x38,0xc8,0x31,0x69, + 0xe1,0xf5,0xde,0xc6,0xcd,0x49,0xac,0x46,0x1,0x29,0xcd,0x3a,0xab,0xc6,0x23,0x3f, + 0xbf,0xcc,0x55,0xc6,0x4e,0x5d,0x8a,0x7f,0xde,0xb6,0xa5,0xf3,0xb5,0xee,0x31,0x8d, + 0x43,0xd0,0xa9,0x92,0xda,0x79,0x3e,0x67,0x43,0xcc,0xc0,0x16,0xeb,0xe,0x60,0x8, + 0x2e,0xfb,0xbc,0xa4,0xb5,0x43,0xa4,0x75,0x74,0xf4,0xe1,0x1c,0xea,0x5d,0x7a,0x43, + 0x57,0xf4,0x51,0xf2,0xd,0xa8,0x8e,0x24,0xeb,0xda,0x2a,0x23,0xf5,0xc8,0xd8,0x16, + 0x13,0xd2,0x71,0xb5,0x34,0x9d,0x31,0x5c,0xf3,0x36,0x8c,0xb,0x7c,0xee,0x5f,0xfa, + 0x98,0xd,0xa9,0xcc,0x4a,0x62,0xec,0xe1,0x55,0xd5,0x83,0xbc,0x5b,0x1a,0x32,0x93, + 0xf7,0x51,0x39,0xb2,0x1b,0x31,0x54,0x57,0xd3,0x44,0xce,0x77,0xad,0xc5,0x79,0x3c, + 0x46,0x6b,0xee,0x68,0x18,0xf1,0x79,0xb3,0xa0,0x6e,0x6,0xe7,0x9f,0x1a,0xd5,0x3, + 0x85,0x41,0x64,0xcc,0x9a,0xe6,0x19,0xe6,0x74,0xb7,0x76,0x42,0x50,0xa7,0xd2,0x4e, + 0x91,0x58,0x6a,0xc9,0x9e,0x46,0xe2,0x51,0x83,0xdb,0x48,0xd0,0x76,0x4,0x93,0xe7, + 0xcf,0xb1,0x87,0x5c,0xda,0x8a,0x37,0x1f,0x6d,0x53,0x19,0x3f,0x58,0xee,0xb,0x91, + 0x26,0x59,0x84,0xd2,0x8e,0x60,0x1b,0x3a,0x53,0x46,0xd6,0x6e,0xba,0xb7,0xd1,0x1a, + 0xc5,0x70,0xd,0x2e,0xf2,0xd4,0x96,0x10,0x4,0xc,0x26,0x18,0x99,0x3f,0xac,0xd6, + 0x4c,0xb8,0x26,0x5d,0xa4,0xab,0x6a,0xc3,0x70,0xd6,0xa5,0xcb,0x7c,0x37,0xc6,0x38, + 0x46,0xe3,0x9d,0x8b,0xe0,0x61,0xce,0x24,0x4,0xbe,0xc6,0x26,0x37,0x6a,0xa6,0xae, + 0xa6,0x27,0xcc,0x15,0xaf,0xef,0x3f,0xfa,0xc,0x5d,0xb0,0xe2,0x58,0x39,0x54,0x5, + 0x4e,0xc4,0x35,0x64,0x76,0x9f,0xe2,0x3d,0x6f,0xbe,0x69,0xac,0x7,0x1d,0xe2,0x9a, + 0x18,0xe3,0x92,0xa0,0x8a,0x41,0x45,0x7c,0x3d,0xa5,0x6a,0x81,0xb2,0x63,0xdd,0xb3, + 0x69,0x5f,0x37,0x1d,0x6d,0x31,0x6e,0x9,0xc1,0x4,0xa8,0x1a,0x69,0x61,0xab,0xe4, + 0xfd,0x0,0x41,0xe7,0x1,0xa1,0xbf,0x6e,0xba,0x2,0x6f,0xc2,0x93,0x3e,0x8b,0x87, + 0x16,0xd2,0x7f,0xf1,0x28,0x7b,0xf2,0x1b,0x69,0xda,0xa9,0xbb,0x7a,0x9c,0x66,0xf2, + 0x58,0x66,0x87,0xf4,0x45,0x39,0xa5,0x5f,0xfd,0xb5,0x4f,0x44,0x99,0xb1,0x8e,0x81, + 0xb1,0x6,0x47,0xb,0xd5,0x8c,0x82,0xf,0x8f,0x78,0xb2,0x8d,0x9d,0x90,0x38,0xb3, + 0x5a,0x37,0xb4,0x58,0xf8,0x83,0x27,0x2a,0xae,0x1c,0x4e,0x5d,0x3,0x79,0xc5,0xe8, + 0x33,0x9c,0xd3,0x13,0x4,0x7c,0x2a,0x8d,0x78,0xcd,0x2b,0x5,0x4a,0x5,0x2b,0x17, + 0x53,0x1e,0x15,0x4f,0xf1,0x1a,0x22,0x5c,0xcd,0xbf,0x7e,0x23,0xa2,0xb9,0xee,0x60, + 0xe,0x4b,0x2c,0xd4,0x5b,0x35,0xfb,0xa1,0xfb,0x6e,0xc4,0xb0,0x34,0x91,0x31,0xd9, + 0x82,0x5d,0xe6,0xce,0xe1,0x1e,0x4a,0x27,0x73,0xb1,0xba,0x40,0xce,0x26,0x42,0x94, + 0x9b,0x63,0xf1,0xc8,0x7e,0x44,0x34,0xf5,0x9c,0xc,0xea,0xb6,0xc,0x9a,0xee,0x6b, + 0x61,0x4c,0x6f,0x7e,0x8,0x4d,0xa3,0x2b,0x56,0xb2,0xf6,0xcd,0x14,0xcc,0xf1,0x47, + 0x5a,0x90,0x4f,0xb3,0xe,0x4b,0xa7,0x1d,0x10,0xbe,0x2f,0x9d,0x89,0x61,0x88,0x81, + 0xfb,0xb4,0x4b,0xd8,0xe7,0x9c,0x27,0x83,0x8,0x21,0x1e,0x57,0x47,0xb4,0xc3,0x17, + 0x49,0x13,0x6,0xb8,0x2b,0x24,0x1c,0x35,0x84,0xed,0xf5,0xbd,0x43,0x87,0x31,0xaf, + 0x8c,0x0,0x17,0x2c,0x2d,0x4f,0xd2,0x69,0x80,0xa2,0x4d,0x3b,0x62,0xb3,0xdd,0x79, + 0x47,0x9b,0xcb,0xe9,0x51,0x60,0x35,0x21,0xb6,0xcc,0xf8,0x19,0x7b,0x35,0x6d,0x17, + 0x69,0x1c,0xfb,0xc3,0x7f,0xd,0x16,0x2,0x9a,0xf8,0x52,0xa0,0x7d,0x82,0x76,0x3a, + 0xb4,0xb9,0x40,0x4e,0xfb,0x88,0x86,0x1d,0x17,0x59,0x87,0x1c,0x88,0x4d,0x92,0xe6, + 0x11,0x3d,0xbf,0x77,0x5f,0xd5,0x59,0xdf,0xd3,0x68,0x17,0xc5,0x45,0xf9,0xf8,0xc6, + 0xf2,0xe4,0x54,0x3b,0x20,0xda,0xda,0x30,0xc,0xba,0xe,0xc7,0x3,0x2b,0x7c,0x9a, + 0xda,0xe0,0x13,0x26,0xd8,0xf8,0x98,0x59,0x2e,0xac,0x3b,0x4f,0xd7,0x5d,0x5c,0xda, + 0xb1,0xae,0x4a,0x2,0x40,0xff,0xdf,0x62,0x6b,0x53,0xb7,0xee,0xc9,0x4e,0x1a,0x6, + 0x7f,0x81,0x4c,0xe7,0xbd,0xcf,0xcb,0x3b,0x2a,0x58,0xb0,0x20,0xd4,0xab,0x30,0xf5, + 0x6,0x4a,0x12,0x6a,0x37,0x3,0x73,0x4d,0xc8,0xe1,0x11,0x7c,0x86,0x7f,0x6d,0x51, + 0x28,0xa8,0xe,0x4b,0xa7,0xff,0xcc,0x91,0x37,0xae,0xb2,0x49,0x95,0x53,0x39,0xc, + 0x65,0x5d,0x13,0x56,0x1e,0x6a,0x99,0xdb,0x67,0x23,0x32,0xd8,0xb6,0x55,0x10,0x92, + 0x79,0xcb,0x83,0xb4,0x71,0xe2,0xb4,0x31,0xf,0x64,0x50,0xf0,0xc2,0xe1,0x20,0xbd, + 0x21,0x24,0x8,0xd1,0xf0,0xe7,0x8e,0x6a,0xb7,0x63,0x64,0x4b,0xf6,0x3e,0xaa,0x41, + 0xd,0x3e,0xaf,0x87,0xa7,0xdb,0xfe,0x34,0x5d,0xec,0xde,0x2a,0x28,0x71,0xab,0x9a, + 0xa6,0x50,0x14,0x4e,0x36,0x9b,0xc0,0x21,0x64,0x6d,0xb4,0xe,0x95,0x6e,0xda,0x11, + 0x46,0x70,0x4f,0x5c,0xa,0xae,0xbc,0x35,0xf6,0xb6,0xb5,0xdd,0xf0,0xa2,0x47,0x80, + 0xba,0xe7,0x56,0x86,0xdb,0x36,0xf1,0x64,0x59,0xf0,0xba,0x3c,0x62,0x93,0xd2,0x46, + 0xd9,0x4e,0x64,0xff,0xe2,0x22,0xf5,0xc8,0x85,0xd8,0xbd,0x85,0xdc,0xcd,0x6e,0x42, + 0xfb,0xda,0x54,0x2b,0x64,0xb1,0x48,0x25,0x38,0xf,0x96,0x72,0xc9,0x69,0x7d,0xa2, + 0x65,0xdd,0xa3,0x44,0x7c,0xf,0xb6,0xa5,0x2f,0xe2,0x33,0x81,0xc9,0x6d,0x93,0x24, + 0x4b,0xef,0xf3,0xb2,0xee,0x8e,0xb5,0xb0,0xdb,0x2d,0x74,0x9e,0x50,0x95,0xee,0xd1, + 0x3e,0x36,0x8d,0xf1,0xe,0x9c,0x40,0x50,0x2d,0x9b,0x34,0x12,0x40,0x29,0x6f,0x42, + 0x8,0xa3,0x7,0xcf,0x18,0x88,0x6b,0x2e,0x76,0x77,0x2a,0xa6,0x10,0xb0,0x3,0xd, + 0x51,0x1f,0x7a,0x4e,0xb6,0x7b,0xa4,0x1d,0x1a,0x64,0x8e,0x19,0xf0,0xee,0x73,0xee, + 0xd7,0x4d,0xb8,0x64,0xda,0x23,0x95,0x18,0xd7,0x27,0x6e,0x2,0x5b,0xff,0xbc,0x8, + 0x84,0xaf,0x34,0xe6,0x52,0x51,0x83,0xb9,0xdd,0xba,0xb4,0x3e,0xab,0xaf,0x36,0x58, + 0x40,0xb1,0xf3,0x9c,0xef,0x6d,0x97,0x94,0xa6,0x35,0xb6,0xba,0xd9,0x9d,0xe7,0x4e, + 0x12,0x56,0xda,0x42,0x8,0xd3,0x3b,0x4f,0x4b,0xef,0x82,0xf9,0x5d,0xef,0x94,0x5c, + 0x39,0x7f,0x9e,0x63,0x32,0x3c,0xd3,0xcd,0xec,0x1b,0xeb,0x76,0x3b,0xb7,0x40,0xbe, + 0x92,0x7b,0x10,0xee,0xfa,0x9f,0xdd,0xe9,0x2c,0x2c,0x5c,0xf8,0xe6,0x41,0x24,0x1e, + 0x3c,0x27,0x91,0x4e,0xa7,0xb1,0x3a,0xe9,0x92,0xd5,0xf6,0xa4,0xcd,0x4a,0x74,0x42, + 0x10,0x50,0xa8,0xec,0x35,0x1d,0xb8,0x3f,0x68,0x97,0x84,0x5b,0x8e,0xda,0x76,0x48, + 0xd0,0xe,0x66,0xdc,0xdb,0xb4,0x61,0x7,0xc3,0x7f,0x5c,0x88,0xe2,0x97,0xb9,0xc4, + 0x24,0x25,0x84,0x39,0x46,0x44,0x66,0x6b,0x6c,0xac,0x1,0x85,0x46,0xf4,0x98,0x2, + 0xcb,0xa1,0x73,0xc3,0xfc,0xb9,0xda,0xe5,0xd6,0x61,0xa,0xf8,0x61,0x9f,0xec,0x68, + 0x53,0x8c,0x89,0x31,0x31,0x37,0xed,0x87,0x15,0xc9,0x64,0x79,0x15,0x65,0xe3,0xa9, + 0x3a,0x5d,0x6a,0x78,0x20,0x5b,0x1b,0x6,0xba,0xa6,0xcd,0x87,0x84,0x4d,0xdb,0xe, + 0xda,0xe7,0xf4,0x22,0x51,0x2a,0x44,0x9b,0x75,0x3b,0x5d,0x1b,0x65,0xb6,0xa6,0xd4, + 0x66,0xa5,0x8c,0x14,0x46,0x7f,0x11,0x8c,0x69,0x1e,0xb,0xbd,0xcf,0x95,0xc2,0xa8, + 0x14,0x8c,0x37,0x30,0x4b,0xca,0x1e,0xd6,0xc6,0x3,0x9d,0xd4,0x5b,0x5b,0xa1,0xda, + 0xfc,0x83,0x82,0x81,0xdc,0x46,0xaf,0x5,0xfb,0x8a,0xd5,0xf2,0x2d,0x79,0x62,0x22, + 0xdc,0x34,0xd9,0xf3,0xd2,0xc4,0x55,0xbb,0x92,0x81,0x79,0x12,0x83,0x1,0x12,0xd1, + 0x81,0x1b,0xab,0x7d,0x93,0x12,0x4c,0xb0,0xcc,0x81,0xa,0x43,0x7e,0x75,0xcf,0x8e, + 0x91,0x55,0xc1,0xa2,0x89,0x61,0x99,0xb5,0x41,0x65,0x91,0xaf,0x5e,0x82,0x47,0xc4, + 0x91,0xcc,0xdc,0xd9,0x50,0x3e,0x5b,0xc1,0x3a,0x36,0x2b,0x36,0xe2,0x0,0x75,0xb1, + 0x50,0xe9,0x43,0x3b,0x32,0x84,0xdd,0x5d,0xed,0x7c,0x9f,0x84,0xa2,0xf1,0x22,0x8d, + 0x21,0x86,0x85,0x50,0xc,0x4a,0x81,0xf8,0x2e,0x26,0xf2,0x1e,0xe2,0xe4,0x6b,0x24, + 0x33,0xaf,0x5e,0xfe,0xcd,0x50,0x95,0xc2,0x9b,0x8e,0xa6,0x3e,0xa8,0x8f,0x53,0x4d, + 0x63,0xcb,0x58,0x53,0x2c,0x87,0x8f,0x1d,0xf6,0xd2,0xa,0xed,0xd,0xe3,0xb6,0x15, + 0xba,0xd0,0xdc,0x72,0x16,0xf9,0x87,0x91,0xa5,0xaa,0xa4,0xd8,0x57,0xbe,0x26,0x89, + 0x24,0xa4,0xd4,0xcc,0x25,0x55,0x24,0x23,0x2b,0x11,0xb3,0x2b,0x5b,0xec,0x2a,0x96, + 0x64,0x80,0x96,0x41,0x9,0x4a,0x4,0x79,0x4b,0xf0,0xa,0x9c,0xfc,0x6c,0x5b,0x95, + 0xb4,0xd7,0x13,0x22,0xe0,0x4f,0x55,0xa3,0x92,0x5b,0x69,0x2c,0xa0,0x34,0xe9,0xf1, + 0x1b,0x2b,0xa6,0x13,0xdd,0x52,0x2a,0x88,0x5f,0x1f,0xbb,0x62,0xcd,0xa8,0x36,0x1a, + 0xd6,0xb3,0x6d,0x11,0xc4,0x6d,0x17,0x16,0x58,0xf8,0x8e,0x2a,0x9,0xde,0xac,0x8a, + 0x4f,0x1a,0xa,0xd0,0x4e,0x5b,0x6d,0xf5,0x16,0x8c,0xe3,0xe9,0x6e,0x80,0x67,0x9b, + 0x83,0xe3,0x39,0x43,0x5d,0x84,0x89,0x69,0x77,0x80,0xde,0x18,0xbd,0x2a,0x5c,0x91, + 0x64,0x97,0xbb,0xb2,0xbb,0x30,0xc,0xa9,0xfe,0x9e,0x20,0x19,0x25,0xa2,0xa6,0x6e, + 0xcd,0x31,0x73,0xe3,0x5b,0x1b,0x74,0xb8,0xd9,0x3e,0xd9,0x28,0xb7,0x99,0xec,0x2, + 0xc2,0x8a,0x65,0x62,0x83,0xc1,0x51,0x8e,0x8c,0x54,0x14,0xf0,0x64,0x8b,0xd8,0xd, + 0x2,0x86,0xe8,0xa4,0x9d,0x27,0xfc,0x9f,0xfb,0x45,0x9a,0xf3,0xcc,0xa3,0x89,0x19, + 0xc8,0x53,0x93,0x24,0x79,0x33,0x44,0xa3,0xfb,0x80,0xf6,0x0,0xd2,0x46,0x37,0xde, + 0x41,0x2e,0xe3,0x49,0x5e,0x73,0xd,0x7b,0x2,0xfc,0x8c,0x36,0xbd,0x93,0x48,0x35, + 0x2e,0x12,0xc2,0x92,0x8a,0x46,0x4c,0x83,0xb6,0x2a,0x72,0x52,0xca,0xc8,0xb6,0xc0, + 0xc1,0x41,0x4c,0x74,0x27,0xa3,0x1f,0xcc,0xf1,0x73,0x9e,0xc5,0xe1,0xd0,0x8,0x9, + 0xa0,0xda,0xc7,0x92,0x48,0x5d,0xb2,0x33,0x9f,0xb3,0xf9,0x33,0x81,0xc6,0x68,0x9b, + 0x53,0x60,0x6c,0xcc,0xab,0x90,0x3,0x9f,0xed,0x60,0xba,0x2f,0x5c,0x7f,0x30,0x57, + 0x92,0xb3,0x43,0x57,0xb3,0xf5,0xf5,0x59,0xa0,0x76,0x39,0x30,0x2f,0x77,0xeb,0xa3, + 0x89,0x8e,0x33,0x4d,0x38,0x25,0x90,0x83,0x45,0x8c,0xb4,0xa,0x43,0x9d,0x7b,0xe3, + 0xd2,0x66,0x97,0xda,0xa7,0x48,0xd9,0x8a,0x93,0x71,0x68,0x6b,0x6b,0x10,0xf4,0x49, + 0x78,0x6f,0xd3,0x71,0x31,0xa9,0x62,0x6,0x8c,0x76,0x81,0x1c,0x2c,0x83,0x3d,0xed, + 0xe3,0x66,0x81,0xe8,0x60,0xb0,0x3e,0xa,0xa4,0x3e,0x32,0x8d,0xec,0x47,0xd2,0xfb, + 0x81,0xeb,0x51,0xfa,0x98,0x68,0x35,0xcc,0x8c,0xd5,0x39,0x3e,0x9d,0xd2,0xf5,0x3, + 0xe1,0xf3,0xd,0x5c,0xa6,0x61,0xc3,0xf5,0x23,0x8d,0x5,0x4b,0x8d,0x44,0x70,0xad, + 0x50,0xdd,0x5a,0x28,0x5d,0x28,0x10,0x49,0x19,0xaa,0x2a,0x65,0xec,0xa0,0x39,0x4d, + 0x32,0x3b,0x2a,0x74,0x55,0xf2,0x66,0x52,0xdc,0x86,0x6c,0xb0,0x20,0x52,0x93,0x7a, + 0x7a,0x73,0x69,0xaf,0x39,0xec,0xa9,0xe4,0xab,0xa3,0x69,0xb2,0xa,0x80,0x4b,0x15, + 0xf5,0x9f,0x3c,0x35,0x44,0x49,0x24,0x61,0xa0,0x8f,0xe1,0x37,0x1f,0x1f,0x60,0x77, + 0xa4,0x60,0x13,0xed,0x73,0xd8,0xd7,0x43,0xe2,0xae,0xde,0x88,0xcd,0x8c,0x5e,0xa8, + 0xdd,0x62,0x21,0x82,0xb,0x7e,0x35,0x55,0x5c,0x75,0x83,0xeb,0x59,0xdf,0x36,0x5c, + 0x87,0x77,0xe9,0x8,0xd9,0x36,0x5c,0x82,0x3b,0x6d,0x32,0x7a,0x10,0x8a,0x67,0xbf, + 0xe8,0x4d,0x1a,0xda,0x5d,0xe0,0x43,0xbe,0x74,0xa4,0xd1,0x2f,0xb3,0xd,0xd2,0xb8, + 0xdd,0x40,0x2b,0x8b,0x7c,0x72,0xcc,0x78,0x93,0x23,0x81,0xf9,0x2,0xca,0x58,0x57, + 0x84,0x4d,0x43,0xda,0x3c,0x84,0x3b,0x4a,0x6e,0xdc,0xc6,0x7a,0x3b,0x7c,0xb,0xdd, + 0xec,0xf6,0xc3,0xd8,0x8c,0x16,0x4b,0xad,0xf8,0x6e,0x8a,0xf8,0x17,0x2d,0x4a,0xa6, + 0x28,0x4b,0xe6,0xa8,0x78,0xee,0x51,0xec,0xb,0xee,0x24,0x6e,0x8b,0x9d,0x95,0xaf, + 0x67,0x55,0x25,0xc6,0xef,0x94,0x70,0xa1,0x6c,0x10,0x57,0xd3,0x47,0x68,0x62,0x37, + 0xad,0x3a,0x11,0x5d,0x52,0x94,0x28,0xb1,0x93,0x5e,0x6e,0x55,0xa4,0x12,0x88,0x4, + 0x42,0xa1,0x51,0xb,0x91,0xc9,0x38,0x84,0x1a,0x8f,0x70,0x23,0x5c,0xc5,0xa6,0xe2, + 0xce,0x58,0x98,0x83,0x4d,0xaf,0xaf,0x63,0x54,0xdc,0x1d,0x42,0x17,0x3c,0x53,0xe, + 0x7c,0xa4,0xef,0xc9,0xa5,0xb2,0x60,0x6d,0x86,0x46,0x95,0x3a,0x57,0xe,0xdd,0x8b, + 0xde,0xd1,0x1d,0xf5,0xd1,0xcc,0x34,0x8f,0x4f,0xb2,0xb1,0x14,0x62,0x2,0x16,0xc2, + 0x74,0xd5,0x15,0xce,0xa3,0x99,0xe8,0xeb,0x5e,0xc,0x1a,0xa5,0x23,0x9,0x30,0x67, + 0x91,0xd4,0x19,0xb0,0xa8,0xb0,0x55,0x1d,0xd2,0x7a,0x4a,0xdc,0x5a,0x9,0x1d,0xbc, + 0xb7,0xae,0xa1,0x51,0x8,0x11,0x1b,0x40,0x85,0x56,0x0,0x6c,0xba,0x5b,0xe9,0xc0, + 0x4,0xd0,0x14,0x8c,0xa9,0x5a,0x95,0xec,0x59,0x24,0xaa,0x9a,0xa7,0x96,0xc9,0x66, + 0x40,0xc4,0x19,0x77,0x20,0x45,0x44,0xad,0xe4,0x41,0x94,0x4c,0x68,0xcc,0xb0,0xc1, + 0x8f,0xf,0x77,0x30,0xcd,0x74,0x82,0x5e,0x54,0x5b,0x37,0xd7,0xe1,0xec,0x70,0xa6, + 0x19,0x7e,0xea,0xc8,0x8c,0xd1,0x16,0x85,0x89,0xc7,0x2c,0x7b,0xb1,0xae,0xe8,0xbd, + 0x63,0x64,0x44,0x39,0xcf,0xa0,0x8f,0xdb,0xce,0xf8,0xed,0x3d,0x9e,0xbf,0x31,0xa9, + 0xeb,0xe8,0x1d,0xc4,0x9b,0xf,0xcd,0x0,0x7f,0x4e,0xde,0x20,0x34,0x9f,0x62,0x4a, + 0xe0,0xca,0x55,0xe6,0xf3,0x35,0xb6,0x3d,0xad,0x75,0x41,0x6f,0xbe,0xe,0xc5,0xbc, + 0xcc,0x9b,0x8e,0xce,0xc6,0x2c,0x6d,0xe1,0xc,0x8,0xb5,0xab,0x68,0xfe,0xb4,0x95, + 0xc4,0xc5,0xd4,0x59,0xa9,0x8a,0x1c,0x8,0xad,0xb8,0x4,0xa2,0xad,0xcf,0x81,0x4d, + 0x17,0x4f,0xdd,0x9b,0x4c,0x7b,0x21,0x7e,0x3f,0x61,0x95,0xfb,0x90,0x4c,0xfa,0xb6, + 0xb0,0x4b,0x68,0x68,0x50,0x80,0x6a,0x6,0x97,0xa9,0xf7,0x60,0xb6,0x94,0x55,0x6c, + 0xb6,0x72,0xb3,0x22,0xc5,0xf,0x42,0xec,0x16,0xda,0x99,0x27,0x24,0x7b,0x15,0xf3, + 0x6a,0x92,0xab,0x1e,0xf6,0xd6,0x64,0x2b,0xe1,0x95,0xcc,0xcd,0x2,0x9e,0xa9,0x29, + 0x39,0x2f,0xfd,0x23,0x6e,0x11,0xbc,0x22,0x41,0x97,0x93,0x29,0x54,0xe7,0xbc,0x56, + 0xe5,0xb7,0x19,0x94,0x9c,0x9b,0xc1,0xef,0xa9,0x9c,0x89,0x6c,0x74,0x19,0x74,0x80, + 0x29,0x9c,0x98,0x1,0xc1,0xf6,0xaf,0x74,0xdb,0xff,0x75,0x7,0x5f,0x86,0x8a,0xc2, + 0x11,0xaf,0x4c,0xb2,0x50,0xcd,0x23,0x8b,0x14,0x13,0xca,0x7,0x38,0x2d,0xe,0x22, + 0x70,0xc1,0xfd,0xe5,0xa2,0x46,0xae,0xf4,0x2a,0x0,0x22,0x2a,0x3b,0x15,0xab,0x4, + 0xc7,0xf7,0x4b,0xc,0x77,0xb4,0x58,0xc3,0x29,0x75,0x7e,0xa0,0x91,0x32,0x2d,0x2a, + 0xc8,0xed,0xa0,0x59,0xf2,0xa6,0xaa,0xc2,0xd4,0x76,0x75,0xf4,0xa4,0xd3,0xf,0xa0, + 0x25,0x1,0x91,0xc7,0x88,0x1e,0x72,0xa4,0xe2,0x6e,0x82,0xb9,0x16,0x5a,0xac,0x5d, + 0x52,0xab,0x39,0x5,0x2b,0xcd,0x60,0x5f,0x20,0x51,0xb1,0x48,0x8c,0x19,0x3a,0xa, + 0x98,0x4a,0x3e,0x5f,0x34,0xa2,0x30,0xa2,0x56,0xba,0x70,0xe1,0xb8,0x9c,0x49,0x8c, + 0xf6,0x1f,0x6,0x66,0x7e,0x77,0x4a,0x51,0x8f,0x19,0x44,0x53,0xe5,0xe0,0x1a,0xd, + 0xb5,0x41,0x9e,0xca,0x80,0x81,0x4a,0x33,0x44,0x5e,0x95,0x3d,0xa3,0x84,0xa2,0x45, + 0x78,0x9e,0x85,0x3a,0x76,0x72,0x35,0xc4,0x56,0x89,0xba,0xee,0x18,0x36,0xcc,0xd4, + 0x34,0x1a,0xaf,0xf6,0x1e,0x9d,0x2a,0x1a,0xaf,0xfd,0x28,0x26,0x95,0x2a,0xcc,0x8e, + 0xf0,0xdc,0x16,0x81,0x8c,0x42,0x62,0x79,0x9b,0x1c,0xe,0x1c,0x20,0x60,0xdb,0xf0, + 0x51,0x60,0xc1,0x4d,0x10,0xcd,0xfe,0xe1,0x54,0x22,0xb7,0x94,0x90,0x44,0xdd,0xf8, + 0xe6,0x26,0xd3,0xbe,0xbe,0x6e,0xf3,0x2,0xe7,0xf7,0x2b,0x81,0xe7,0x39,0x8e,0x40, + 0x11,0x14,0x45,0x6f,0xef,0x41,0xeb,0xb8,0x28,0x62,0xa6,0xe7,0x68,0xee,0xd0,0x8c, + 0xed,0x1a,0xf9,0x41,0x54,0x81,0x93,0x6,0xda,0x17,0xe9,0x7a,0xe0,0xa,0x43,0x70, + 0x1d,0x44,0x70,0x18,0x68,0x71,0xfa,0xf0,0x37,0xc1,0xb9,0xb,0x93,0x37,0x2f,0x9a, + 0xa0,0x1e,0xb1,0x41,0x82,0x95,0xf0,0xad,0xe5,0xca,0xb9,0xb5,0xa0,0x4c,0x8c,0xb, + 0xb3,0xf,0xb,0x9b,0x76,0xf1,0xce,0x1c,0x7d,0x84,0xa1,0x8f,0xb,0x51,0x46,0xc8, + 0x49,0x77,0xfa,0xbb,0xce,0x5c,0xb9,0xc1,0x70,0x99,0x93,0x3c,0xc9,0xa6,0xbd,0x10, + 0x93,0xc1,0xba,0xee,0xf1,0x33,0x6e,0x61,0x8b,0x1c,0x17,0x78,0xef,0xda,0xa0,0x40, + 0x77,0xa5,0xbd,0x4c,0xea,0x1a,0x81,0xb1,0x4c,0x18,0x8a,0x56,0xd4,0xb6,0x9a,0xbb, + 0x50,0x25,0xb4,0x20,0x43,0x62,0xec,0xc2,0x9e,0xa4,0xc2,0xa9,0x81,0x8a,0xab,0x10, + 0xb3,0x88,0x74,0x90,0xf0,0x34,0x58,0x8e,0x93,0x53,0x3d,0x85,0x8b,0x34,0xef,0xb9, + 0xc9,0xe8,0x51,0x3c,0x9b,0x20,0xd2,0x78,0x4,0x1e,0x7e,0xd3,0xd1,0xe7,0xab,0xd1, + 0x43,0x30,0xd7,0x19,0xae,0x65,0x3b,0x5b,0x6f,0x7e,0x14,0x19,0xaa,0xb6,0x9c,0x85, + 0x8d,0x32,0x5c,0xb8,0x8f,0xa,0x41,0xdf,0x38,0xf4,0x5a,0x2b,0xee,0xd6,0x96,0x6c, + 0x6e,0x51,0x35,0x36,0x91,0xcd,0x6f,0xb0,0xaa,0xb2,0x4b,0xf3,0xdd,0xa2,0x90,0xf0, + 0xb4,0x35,0x5e,0xf1,0xc7,0xae,0x81,0xaa,0x7a,0x2d,0xd4,0x34,0xab,0x13,0xed,0xc0, + 0xd0,0x22,0xdb,0x37,0xab,0x86,0xda,0xcc,0x85,0x3d,0x29,0x55,0x15,0xaf,0x75,0x9a, + 0x10,0x2b,0xfc,0x4c,0x41,0xa3,0x8,0xd5,0xe9,0x4a,0x1b,0x3d,0xda,0x14,0x4f,0xc4, + 0x63,0xe4,0x27,0xa0,0x36,0xa,0x5b,0x85,0xd0,0xee,0x89,0x86,0x18,0xeb,0x87,0xe8, + 0xfc,0xed,0x62,0x9f,0xa7,0x33,0x89,0xf6,0x7e,0x31,0x9a,0x80,0xb,0x6d,0xec,0x63, + 0x6a,0x92,0xac,0x4b,0x6d,0xf8,0xd9,0xc9,0x8a,0x51,0x88,0x53,0xa6,0x84,0x6a,0x4c, + 0xe,0xf7,0xb,0xb1,0x91,0x8e,0x6f,0x80,0xed,0x87,0xfe,0x88,0x65,0x1,0xac,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x64,0x5e,0xc4,0xe9,0xd3,0x8b,0x35,0x54,0x66, + 0xf2,0xfa,0xa5,0xe4,0x5b,0xcf,0x58,0x29,0x74,0xdb,0xa1,0xeb,0x4a,0x48,0xad,0x71, + 0xd6,0x5c,0x80,0xe8,0x88,0x9a,0x4c,0xc,0xd6,0x9,0x64,0x70,0x1f,0x29,0x3,0x6f, + 0xd4,0x3b,0x6c,0x76,0xf1,0x71,0x16,0x36,0xdb,0xda,0x1d,0xa6,0x27,0x3d,0x74,0x74, + 0x34,0x55,0xd6,0x8c,0x6d,0x53,0x5f,0x22,0x6a,0x19,0x5f,0x69,0x6a,0xe6,0x13,0x26, + 0x55,0x66,0x54,0xad,0xe9,0x38,0xfc,0x3f,0x82,0x20,0x46,0x29,0x1,0x13,0x8d,0x8f, + 0x63,0x92,0xe9,0x8,0x5e,0xa1,0xcb,0x0,0x91,0xa2,0x22,0x1,0x43,0x89,0xeb,0xb, + 0xa1,0x5f,0x88,0xbd,0x38,0x66,0x28,0x11,0xd7,0xc8,0x82,0x80,0x51,0xe,0xb0,0x49, + 0x60,0x71,0xa8,0x1e,0x51,0x1e,0x2b,0x4,0x9a,0x32,0xa2,0x7d,0xd5,0x2f,0x6c,0x77, + 0x1a,0xf9,0x68,0x13,0x4e,0xf4,0xf2,0x97,0xcb,0x49,0xed,0x4d,0x43,0xae,0x9f,0xe7, + 0x19,0x8d,0xfc,0xfa,0x6c,0xde,0xd6,0xb4,0x9d,0xb2,0x22,0xc3,0x9f,0x35,0x0,0x6c, + 0xa2,0x97,0x46,0xbe,0x72,0xe,0x25,0xb2,0x65,0xf7,0x1,0x4d,0x35,0xb8,0x78,0x68, + 0x94,0x93,0x61,0xc5,0x4e,0x74,0xc5,0x19,0x67,0xac,0xb3,0xe5,0x4a,0xcd,0x9e,0x42, + 0x56,0x5a,0x24,0x52,0xc1,0x52,0xe3,0xa3,0x55,0x57,0xc3,0x37,0xe1,0x44,0xa8,0x49, + 0x40,0x8,0x71,0x13,0x59,0xe,0x14,0x70,0xe5,0x2b,0x0,0x15,0x3,0x65,0x85,0x3, + 0x41,0x55,0x7a,0xa7,0x48,0xd2,0xc0,0x4e,0x8a,0x86,0x40,0x2f,0xc6,0xbf,0x96,0xbd, + 0x24,0xc9,0xe,0xd9,0x26,0x21,0xf,0xe8,0xaa,0x7d,0x8,0x4d,0x3a,0xfa,0xa8,0x1c, + 0x47,0xf7,0x6e,0x35,0x17,0xd0,0x55,0x9b,0x3b,0xde,0x66,0x65,0x8c,0xc4,0x37,0x37, + 0x68,0xb9,0x86,0x5c,0x10,0x44,0xc5,0x53,0x86,0xb5,0xb8,0x3d,0xdd,0x1,0x1,0x5d, + 0xac,0x21,0x1b,0x3c,0x91,0xae,0x14,0xe0,0x2,0x76,0x59,0xd0,0x5f,0x83,0x96,0xa5, + 0xd5,0x74,0xaf,0xcd,0x36,0x3e,0x6e,0xf1,0x9c,0x3e,0x4f,0x9d,0x8a,0x7d,0x0,0x7, + 0xea,0x94,0x38,0xa4,0xce,0x7c,0x2a,0xfe,0xb5,0xa1,0x77,0xe4,0xcc,0xfb,0x36,0x15, + 0xdc,0xc9,0x22,0x9a,0x7d,0xe4,0x88,0xac,0xb2,0x29,0x5c,0xe3,0x9a,0x55,0x89,0xac, + 0x48,0x2,0xc9,0x18,0x53,0x53,0xc0,0xd7,0x6,0x1b,0xa3,0x68,0xd4,0x95,0x6d,0x6e, + 0x5a,0xe1,0x20,0xe3,0x1f,0x1d,0xda,0x5e,0x74,0xad,0xe,0x40,0x5d,0xb1,0xe4,0x7, + 0x3e,0xc1,0x4b,0x2a,0x71,0x41,0x23,0xd7,0x1b,0x99,0x3d,0x9b,0x67,0xa,0xdc,0xe3, + 0x5b,0x96,0xf3,0x98,0x44,0xbb,0x63,0xc6,0x8,0x51,0x4a,0x77,0xb0,0xad,0x8,0x6c, + 0xde,0x14,0xaa,0x5c,0xb5,0x41,0x7a,0x57,0x9b,0x46,0xc5,0xf5,0xd1,0x25,0x78,0x85, + 0x16,0xfc,0x92,0x68,0x64,0xac,0xdf,0xb2,0xc5,0x4f,0x20,0x28,0x67,0xc2,0x93,0x4f, + 0x2f,0xe0,0x1e,0x75,0x27,0x1,0xd3,0xc7,0x60,0xa,0xde,0x79,0x76,0x75,0x5b,0xbf, + 0x69,0xdb,0xc2,0x80,0xe7,0xe6,0x75,0xf,0x98,0xc7,0xa6,0xec,0x9d,0x77,0xdb,0x56, + 0xa7,0x34,0x32,0xf3,0x57,0xda,0x6e,0xd,0x45,0x77,0xdf,0x7c,0xfa,0x79,0x21,0x79, + 0xaf,0x50,0xa8,0x32,0xeb,0x4a,0x86,0xbe,0x78,0xd5,0x4e,0x7d,0xb8,0x67,0x10,0x44, + 0x31,0x11,0xc1,0x2c,0x11,0x99,0x36,0x47,0x56,0xe4,0x9e,0x57,0xcd,0x21,0xe1,0xf3, + 0x5f,0xef,0x21,0xc4,0x53,0x1e,0xe5,0x18,0xef,0x97,0xff,0x7b,0x4,0x95,0x49,0x60, + 0x7e,0x57,0x17,0x64,0x88,0x2d,0x4d,0x87,0x34,0x85,0xc4,0x6,0x9c,0x89,0x20,0x23, + 0x86,0x91,0x74,0xc3,0x74,0xd8,0xb4,0x2c,0xfc,0xd,0xee,0xf2,0x9e,0xea,0x2c,0x25, + 0x3e,0x81,0xbb,0x66,0xa6,0x12,0x79,0xda,0x94,0xb4,0x11,0x4c,0x5,0x1a,0x13,0x3b, + 0x5f,0x0,0xc3,0xbb,0xa6,0xba,0xdf,0xdb,0x58,0x95,0x71,0x18,0x8a,0x26,0x95,0x76, + 0x2a,0xa6,0x42,0xa9,0x9b,0x10,0x8,0x63,0xf5,0xd1,0xdd,0x3c,0x17,0xf6,0xa1,0xa9, + 0x90,0x2,0x5d,0x70,0xeb,0x34,0x2d,0xc0,0x18,0x74,0x91,0xa6,0x90,0x1a,0xc8,0x4e, + 0x63,0x13,0x63,0xfa,0x36,0xd0,0x4e,0x5c,0xbd,0xa0,0x81,0x61,0x61,0xc5,0x77,0x26, + 0x4a,0x41,0x81,0xe4,0x1c,0x74,0xbe,0xbf,0x88,0xe0,0x40,0x17,0xf8,0x8b,0xff,0x9c, + 0xe0,0xb1,0xb0,0x69,0x9d,0xe4,0xae,0xf,0xd5,0x9c,0xb2,0xe8,0x4,0x2f,0x2f,0x0, + 0x48,0x39,0xd4,0xfc,0x64,0x73,0x16,0x7b,0xe,0xe6,0x0,0xb3,0x7d,0x90,0x84,0x97, + 0x1a,0x89,0x45,0x31,0xc5,0xef,0x68,0xd3,0x23,0x30,0x84,0x89,0xdd,0x21,0x2b,0xaa, + 0xad,0xc3,0x35,0xb4,0xa4,0x88,0xe1,0x31,0x6d,0x8c,0x71,0x4d,0xb1,0x29,0x1e,0xcc, + 0xd2,0xa7,0xce,0xc0,0x26,0x22,0xe8,0x7d,0x6,0xc2,0x8b,0xd9,0x82,0x69,0xe7,0xde, + 0xe7,0x8a,0x62,0xe8,0x6c,0x68,0xa5,0x31,0x83,0xbc,0x3c,0x6f,0x6a,0x5a,0x1c,0x66, + 0x6f,0x87,0xd4,0x49,0xd2,0x78,0x74,0x7a,0xee,0x5c,0x94,0x39,0x1b,0xee,0x61,0x39, + 0x9e,0xd,0x59,0xc,0xaf,0x67,0x6a,0x8d,0x3a,0x9,0xd5,0x80,0x33,0xac,0xf4,0x8d, + 0x2e,0x9a,0x6d,0xcf,0xf3,0x23,0xee,0x70,0x2f,0x3a,0xe4,0x0,0xc6,0xab,0xb7,0x8f, + 0xc6,0x32,0x40,0xdc,0xbe,0x66,0xc9,0x50,0x23,0x95,0x4e,0xbd,0x42,0x72,0xc2,0x63, + 0x1,0xac,0x99,0x1a,0xa3,0xd7,0x8c,0x93,0x2,0x7a,0x81,0xb0,0x56,0xb1,0xe5,0xc0, + 0xd9,0x64,0x29,0xe6,0x2e,0x7c,0x51,0x67,0xb0,0xd3,0x76,0x36,0xf6,0xcd,0x73,0xd4, + 0xb3,0xd0,0x8e,0xd2,0xd6,0x22,0x67,0x15,0x9,0xa3,0x0,0x4a,0xc2,0x4a,0xf9,0x58, + 0xf5,0xd7,0xc5,0x7f,0x4,0x69,0xb3,0xbb,0x28,0x40,0x12,0x59,0x4c,0xc3,0x71,0x4a, + 0xb9,0x1,0xcf,0xf0,0xa9,0xe6,0x7d,0x1d,0xb,0x5a,0xeb,0x6a,0x74,0x30,0x91,0x95, + 0xd4,0x9d,0x8,0xf,0xa4,0x7,0xe0,0x28,0xc9,0x1a,0x45,0xb9,0x3d,0x22,0x94,0x8, + 0x98,0x4f,0xec,0xfe,0xce,0xf1,0x81,0x75,0xcb,0xcf,0x76,0x13,0x91,0xef,0x33,0x4c, + 0xff,0x5,0x67,0x7c,0xf9,0x88,0x18,0x24,0x90,0xf2,0x30,0xe6,0xc9,0x7f,0x86,0xe4, + 0xb4,0x2d,0xcd,0x28,0xb1,0x42,0xa5,0x50,0x4a,0x69,0x93,0xf8,0x24,0x2,0xd2,0xe6, + 0x52,0x4,0x4d,0x4b,0xfc,0xa4,0x43,0xf0,0x98,0x62,0x8a,0xb6,0x55,0x7f,0xfe,0x61, + 0xd2,0x54,0xea,0x12,0xa2,0x8,0x10,0xc3,0xd9,0x62,0x11,0x72,0xa8,0xab,0xd9,0xe6, + 0xcf,0xac,0x21,0xab,0x7c,0x7,0x67,0x94,0x35,0x6b,0xea,0xce,0x2c,0x9f,0xaa,0xab, + 0x26,0xab,0x1e,0x1f,0x1,0x41,0x13,0x14,0xe1,0x98,0xb2,0x2c,0x8a,0x51,0x14,0xc4, + 0x2c,0xb9,0xa4,0x5d,0x39,0xca,0x3e,0x7,0x54,0x76,0x61,0xde,0xa4,0xfb,0x6c,0xd3, + 0x84,0xb1,0xb1,0x8b,0x45,0xd8,0xd4,0x90,0x47,0xba,0xe1,0x8f,0x12,0xc8,0x81,0xb1, + 0x36,0xdb,0x6c,0x8e,0x62,0x34,0x3,0xc4,0xfe,0xdc,0x9f,0x66,0xe5,0x51,0xbc,0xdb, + 0xa0,0x85,0x2,0xed,0x96,0xc2,0xcf,0xf9,0x83,0xbc,0x13,0x97,0xa,0xe,0xf4,0x40, + 0xd,0xf6,0xe7,0xc7,0xcf,0x2f,0xdd,0x8e,0x3a,0x9b,0xb8,0xe4,0x10,0x31,0x89,0x38, + 0x5b,0x18,0x34,0x6b,0xd7,0xb4,0x4c,0x6,0x35,0x6,0x15,0x56,0xb8,0x35,0x67,0xad, + 0x85,0x75,0xcf,0x66,0xfc,0x83,0x41,0x6a,0x9e,0x6b,0x42,0xc1,0x52,0x52,0x98,0xce, + 0x4d,0x80,0x49,0xff,0x13,0x51,0x26,0xe1,0x62,0x7d,0x12,0xc8,0x11,0x44,0x1d,0xc6, + 0xd7,0x69,0xc4,0x8d,0x50,0xe9,0xe0,0x8d,0x5a,0xf3,0x7b,0x3b,0xb2,0x0,0x94,0xd5, + 0x79,0x29,0x25,0x96,0x3d,0xe7,0x81,0x26,0x4d,0xe,0x18,0xfe,0x94,0x62,0xba,0xe1, + 0xd1,0xb7,0x6a,0x53,0xfb,0xa1,0xdb,0x6d,0x3c,0xf5,0xb1,0x95,0xb4,0x2a,0x9a,0x53, + 0x4b,0xa6,0x91,0x67,0xde,0x42,0x36,0x7c,0xa7,0x1c,0x7b,0x47,0x94,0x66,0x1a,0x25, + 0x3c,0x89,0x72,0xe8,0xfe,0xd8,0x87,0xdd,0x8d,0x79,0xdf,0x4b,0x27,0x3e,0x3c,0xeb, + 0x8d,0x79,0x87,0x30,0xc0,0x4e,0xc4,0xc2,0xc6,0x8e,0x2f,0xc2,0x6a,0xd2,0xb5,0x30, + 0xb9,0xc2,0x9a,0x2e,0x2b,0xd,0xb,0x5f,0xb7,0xc3,0x5e,0xd4,0xd1,0xaf,0x6d,0x7e, + 0xee,0x3b,0xb1,0x5,0xf,0xf9,0xd2,0x11,0xee,0x4b,0x7f,0xf6,0x3a,0x77,0x2e,0x3, + 0x51,0x40,0x11,0xb9,0x1a,0xbc,0x7a,0xd1,0x8e,0xd0,0xb,0xf7,0x79,0xd9,0x38,0xef, + 0x1e,0x14,0xfc,0xa3,0x1e,0x7c,0x9f,0xd3,0xc3,0xfd,0xac,0x6e,0xde,0xd5,0xe6,0x4e, + 0xae,0x9,0x11,0x13,0xd7,0x4,0xcd,0x99,0x1e,0xb9,0xdc,0x85,0xd8,0x10,0xb7,0x31, + 0xe7,0x20,0x80,0x67,0xa1,0xa,0x41,0xa3,0xb3,0x92,0x2c,0x52,0x87,0x68,0x8d,0xc0, + 0x4c,0x76,0x81,0x87,0x8f,0xc5,0xc7,0x92,0x2d,0x94,0xed,0xaa,0x29,0xc4,0x39,0x1f, + 0x26,0x34,0x26,0xee,0x5,0x99,0x2,0xa2,0xbd,0x23,0xab,0xf7,0x60,0xfe,0xac,0x8, + 0xdd,0x98,0x44,0x51,0x2a,0x9a,0xcd,0x3b,0xec,0xa9,0x8d,0x71,0x20,0xfa,0x96,0xb8, + 0xf9,0x1f,0xae,0x2e,0x88,0x4b,0x6a,0x18,0x89,0xbd,0x62,0x2b,0x4c,0x58,0xf0,0x4b, + 0xa5,0x9e,0x31,0x2e,0x3c,0x32,0xc,0xe5,0x7a,0xdc,0x33,0x1e,0xdc,0x63,0xf3,0x6c, + 0x95,0x68,0x41,0xed,0xae,0x3d,0x58,0x3a,0xe3,0xd5,0xfa,0x2f,0x52,0x46,0xcf,0x49, + 0x70,0xe1,0x61,0x24,0x33,0xb,0x5e,0x88,0x79,0x2,0x86,0x7c,0x12,0xce,0xcc,0x7f, + 0xd8,0x4,0xb5,0x93,0x24,0xf0,0x9,0x83,0x6e,0x4c,0x3c,0x51,0x41,0x12,0xa1,0xb3, + 0xe8,0x11,0xc3,0x4a,0x82,0x67,0x35,0x1e,0x75,0x44,0xa8,0xda,0xba,0xdb,0x1,0x91, + 0x21,0x70,0xb7,0xdb,0xb8,0xfb,0xd3,0x55,0xf9,0x7,0xd0,0x62,0x76,0x94,0xf4,0x5b, + 0x67,0xdb,0x40,0x2a,0x7b,0xf5,0xc1,0x69,0x10,0x98,0xfc,0xd4,0x41,0xf3,0xc7,0x6b, + 0x3e,0x58,0x6d,0x8f,0xed,0x83,0xa,0x2c,0xa4,0x49,0x88,0x44,0xfa,0x24,0x5d,0x2e, + 0x2c,0x90,0x33,0x54,0x29,0xb1,0x2f,0xcc,0xa3,0xc6,0xf9,0xe6,0x61,0x6b,0x6e,0xfe, + 0x49,0x97,0x31,0xbd,0x68,0x52,0xd0,0x35,0xef,0x26,0x77,0xe3,0xfa,0x23,0x2b,0x94, + 0xd0,0x5f,0x7b,0xad,0x3b,0x4e,0xca,0xa1,0x91,0xe4,0xf0,0x84,0x31,0x79,0xb2,0x6a, + 0xa7,0x25,0x4b,0x90,0x9a,0xe8,0x65,0xfe,0x4c,0x69,0x9d,0xa8,0x66,0xf4,0x16,0x1e, + 0x1f,0x8b,0x6c,0xe4,0x34,0x49,0xda,0x99,0x8b,0x92,0x3d,0x37,0x34,0xb2,0x1,0x15, + 0xec,0xae,0x5,0x88,0xf0,0x0,0xd,0xe2,0xc,0x68,0x90,0x5d,0x12,0x7a,0xe9,0xc7, + 0x1c,0x7,0xa1,0x47,0xd7,0x7a,0x61,0xc0,0xd3,0x8c,0x26,0x35,0xe2,0x95,0xc4,0x64, + 0xf4,0x98,0x67,0x54,0x6d,0x6a,0x39,0xb8,0xb8,0xed,0x24,0x77,0x8a,0x62,0x17,0x5b, + 0x7b,0x39,0xed,0xa1,0x19,0x30,0x19,0xa8,0xf4,0x66,0x90,0x4,0xea,0xd2,0x54,0xfa, + 0x58,0x2e,0x87,0xe3,0xa0,0x63,0xd8,0xd,0xd5,0xfc,0xa4,0xea,0xbb,0x66,0x20,0xf5, + 0x74,0x9,0xc7,0xcd,0x1f,0x81,0xc1,0x8,0x86,0x92,0xbe,0x9b,0x18,0x4e,0x19,0x3b, + 0x6c,0xa7,0xd5,0xa8,0x27,0x5b,0xa6,0xf5,0xa9,0x5b,0x9,0x9b,0x7b,0xd3,0xc2,0x8b, + 0x4d,0x6d,0x27,0xd,0xc1,0xec,0x8,0xef,0xe4,0x8c,0x12,0x4e,0x75,0x85,0x89,0xe3, + 0x6c,0xc8,0xa,0x4b,0x40,0xa,0xb2,0xa7,0x75,0x40,0xee,0xf2,0xd1,0x34,0xe5,0xcb, + 0x56,0x5a,0x80,0xf6,0x89,0x94,0xac,0x27,0x30,0x83,0xd5,0xb0,0xea,0x6a,0x1f,0x6b, + 0x9f,0x6e,0x23,0xf7,0x38,0xd2,0x13,0xe6,0x1d,0x60,0x12,0xaa,0x65,0x73,0xf8,0x54, + 0xb,0x64,0x2a,0x69,0x99,0xe5,0x8e,0x72,0x71,0xc7,0x33,0xa3,0x99,0x2e,0x27,0x39, + 0xad,0xb4,0x5a,0x84,0xf9,0xcf,0x36,0x52,0x11,0x24,0xac,0x6d,0xc9,0xf2,0x26,0x76, + 0xa1,0x1f,0x88,0xa9,0x6e,0x72,0x9e,0x6b,0xe3,0x8e,0xae,0xd0,0x69,0xd1,0x36,0x68, + 0xaf,0x90,0xd8,0xcb,0x6e,0xa9,0xe5,0xeb,0x34,0x34,0xdf,0x64,0x94,0x92,0x25,0x11, + 0xfa,0x3c,0xbd,0xa3,0x8d,0x71,0x2e,0x1a,0x8,0x5a,0x9d,0x54,0x61,0x83,0xd1,0x4f, + 0x61,0x11,0x85,0x3f,0x2a,0x55,0xfb,0xca,0x5c,0x5d,0x58,0x36,0x38,0x42,0xd,0x9c, + 0xb8,0xee,0xc9,0xcf,0xa5,0x71,0xff,0x1d,0xa8,0x21,0x5,0x9d,0x57,0xe9,0xd5,0x7b, + 0x9f,0x69,0xa6,0x7e,0x77,0x69,0x6a,0xa8,0x34,0x15,0x35,0x14,0x62,0xa3,0x39,0xfc, + 0xc0,0xe1,0x29,0xa5,0x25,0x9d,0xe6,0xe6,0x4,0xe9,0x99,0x41,0x47,0xd4,0xc6,0xd9, + 0x1f,0xd5,0xca,0x10,0x36,0xfb,0x22,0xe3,0xa9,0x5d,0x4,0x18,0xa8,0x3f,0xdb,0x45, + 0x8c,0xc1,0x89,0x67,0x84,0xa4,0x92,0x83,0x44,0x37,0x62,0xf4,0x57,0x2c,0x68,0x94, + 0xe8,0x52,0x2b,0x6b,0x90,0x2e,0xf2,0xb4,0x29,0x57,0x17,0xcf,0x92,0xcd,0xc0,0xb7, + 0x22,0xda,0x54,0xa3,0x7e,0x1a,0x14,0x6c,0x8,0x2d,0xbf,0x9c,0xaa,0x47,0x44,0xb3, + 0x3a,0x25,0xd3,0x92,0x75,0x10,0xaa,0x92,0xee,0x25,0x56,0xc4,0x65,0x6a,0xb,0x7a, + 0x49,0xc4,0x61,0x37,0xc7,0x9d,0x76,0x86,0xcc,0x70,0x3d,0x39,0x93,0x26,0xd1,0xd9, + 0x1,0xd4,0x12,0x59,0x13,0x2c,0x80,0x9b,0x10,0x4a,0xde,0xb9,0x6e,0xac,0x40,0x6c, + 0x91,0x47,0xc2,0x6d,0x9,0x55,0x45,0x6b,0x1a,0x7d,0x3,0x83,0xd0,0x13,0xfa,0x9e, + 0xd8,0xc5,0x33,0xaf,0x33,0xd6,0xee,0x54,0x80,0x69,0x52,0xc1,0xcc,0x49,0x4c,0xc, + 0x2,0x9a,0x7b,0xe0,0x25,0xfc,0x9b,0x98,0xf1,0x92,0x6,0x64,0x9a,0xab,0x88,0x66, + 0x33,0x77,0x4d,0xb4,0x3b,0x1f,0x40,0x28,0x75,0xe9,0xcc,0xbe,0xc,0xfd,0x87,0x7d, + 0xb8,0x42,0xb6,0xbf,0x1c,0xa,0x53,0x4a,0xc4,0xe4,0xb0,0x5d,0x58,0x1b,0x5b,0xd2, + 0x27,0x6,0x24,0xd4,0x9b,0xde,0xc7,0xdb,0xca,0xfb,0x54,0x77,0xee,0x98,0x80,0x2f, + 0x72,0xa3,0xe7,0xaa,0xe,0xc9,0x52,0xea,0x79,0xe0,0x16,0x9e,0xe4,0x77,0xfc,0x18, + 0x11,0xc2,0x2d,0xa1,0xfe,0x2,0x29,0x4a,0xec,0x73,0x74,0xc5,0xee,0x74,0x0,0x69, + 0xba,0x2c,0xf2,0x7b,0xd2,0xf6,0x8c,0x14,0x1b,0xe,0x8b,0xee,0x98,0x0,0x16,0x2a, + 0x5a,0xf7,0xee,0x96,0x71,0xa0,0x7a,0x7a,0x87,0xd6,0xc7,0x19,0x4f,0xea,0xcf,0x84, + 0x51,0xa,0x63,0xdf,0xac,0xd2,0xd0,0xf,0x66,0xdc,0x2a,0x44,0x9a,0xb4,0x3e,0x33, + 0xde,0xbb,0x27,0xb1,0xc6,0xcb,0xcf,0x4c,0x7c,0xf3,0xd0,0xb0,0x52,0xba,0x64,0x96, + 0x64,0xec,0x76,0x68,0x35,0x4,0xd0,0x61,0xd3,0x53,0xb3,0xb5,0x99,0xb2,0xdf,0x52, + 0xf9,0x86,0x7a,0xdb,0x2c,0x91,0x34,0x22,0xa3,0x56,0xbb,0x91,0x98,0x4d,0x24,0x27, + 0xa2,0x6d,0x8,0xd8,0x56,0x38,0x9b,0x2c,0xbf,0x5e,0xfa,0xa5,0xd2,0xd7,0x30,0xaa, + 0x3a,0x59,0xdc,0x50,0x6,0x9a,0x64,0x71,0x3b,0x74,0xb9,0x45,0xb9,0x54,0xe3,0x8b, + 0xad,0xb3,0x14,0xdd,0xd4,0x3c,0xb3,0xaa,0x25,0xff,0xfd,0x75,0x37,0x50,0xe,0x8f, + 0xdc,0x81,0x3a,0x40,0x47,0x1d,0xef,0xd3,0x86,0x8f,0x36,0x1d,0xf2,0x48,0x11,0x1, + 0x2d,0x49,0xf1,0x38,0x5b,0x31,0xf1,0xf6,0x38,0x8b,0x37,0xa0,0x18,0x9c,0x85,0x9, + 0xd0,0xe2,0x9a,0x3f,0x50,0xf4,0xfc,0xed,0x43,0xd9,0xf5,0x62,0x97,0x7d,0xf3,0x8a, + 0xd5,0x47,0x57,0xf1,0x82,0xa5,0x71,0x5d,0x1a,0xb5,0x7b,0x12,0x8c,0x92,0x5c,0x6f, + 0x4e,0x9c,0xb9,0xc8,0x52,0x27,0x95,0xce,0x4a,0xbf,0x31,0xab,0x9c,0x1f,0x73,0x61, + 0x19,0xd8,0xaa,0x54,0x57,0x96,0x42,0xe4,0x95,0x7b,0xd1,0xd7,0xf3,0xba,0x19,0x25, + 0x4d,0x40,0xf9,0xeb,0x9e,0xe1,0x5f,0x8,0x3f,0x85,0xfb,0x56,0x35,0x61,0x78,0x93, + 0x4,0x40,0x4b,0xce,0x3a,0x18,0xbc,0x46,0x55,0x88,0xdb,0x3f,0x51,0xb0,0xc0,0xf3, + 0x2e,0xd4,0x48,0x9b,0x9b,0x62,0x29,0xc2,0xe2,0x12,0x17,0x5f,0x65,0x19,0x53,0xdb, + 0xb2,0x72,0x76,0xc1,0x14,0x65,0xef,0xb9,0xaf,0x94,0xb2,0x28,0xce,0x35,0xd7,0xd4, + 0xe5,0x4d,0x1c,0x76,0xf5,0xb0,0xc6,0x65,0xe5,0x45,0xd0,0xb8,0xc9,0xf5,0xc0,0xbb, + 0xf1,0x14,0x8e,0x13,0xef,0x1c,0xa8,0x3,0xa0,0x65,0xfd,0xda,0x11,0xa7,0x69,0x78, + 0x7a,0xd7,0x69,0xfa,0x87,0x40,0x89,0x6b,0x96,0xc4,0x68,0x55,0xdd,0x10,0x48,0x50, + 0x69,0xa0,0xd7,0x90,0xd0,0x40,0x50,0xb2,0x97,0xb7,0x78,0x4e,0x95,0x13,0xfb,0x5c, + 0x76,0x47,0x22,0x39,0xf5,0x4e,0x8a,0xf,0x2e,0x6,0x17,0x22,0x5,0xea,0xd1,0x3b, + 0xc,0x9a,0x60,0xa8,0xce,0x52,0x87,0x73,0xba,0xab,0xe5,0x6c,0x76,0x91,0x1a,0xcd, + 0x15,0x48,0x88,0xd4,0x5d,0x85,0xcc,0x76,0x3b,0x2c,0x97,0x24,0x38,0x3b,0x84,0xa1, + 0x5a,0x1,0xa6,0x1a,0x79,0xa3,0xc4,0x91,0x18,0xbf,0xb5,0x79,0x24,0x57,0x37,0xae, + 0x69,0x8b,0xc7,0xd5,0x7e,0xbe,0x99,0x11,0xa1,0x2c,0x68,0x34,0x59,0x82,0x7,0x9f, + 0xcc,0xf7,0x5d,0xeb,0xa2,0x25,0xa2,0x39,0x85,0x55,0x81,0x10,0xed,0x6e,0xc5,0xb2, + 0xb5,0x5a,0x17,0xc3,0xa0,0x4d,0xd1,0x98,0x84,0xa6,0x23,0x68,0xaa,0x1,0x63,0x91, + 0xa2,0xb9,0x59,0xa7,0x5b,0xbe,0x3e,0x54,0x90,0xbb,0x5,0x2d,0xf7,0x88,0x81,0x15, + 0x1f,0x9f,0xff,0x2e,0x6a,0x4f,0x9d,0x31,0xd0,0x11,0xa8,0x45,0x56,0x8,0x9b,0xb4, + 0x5a,0x27,0xa1,0x29,0x57,0x62,0xbe,0xc3,0xe4,0x28,0xb1,0x6d,0xad,0xc,0x4,0x9e, + 0x81,0x87,0xe6,0x71,0x69,0x91,0xc4,0x26,0x18,0x94,0xc1,0x27,0x6b,0x26,0xc7,0x50, + 0xf6,0x81,0x2e,0x7a,0x5b,0x3f,0x3b,0x91,0xed,0x6a,0xc0,0xbe,0xb3,0x56,0x8a,0x97, + 0x3c,0x27,0x57,0x66,0x3,0xba,0x86,0xc3,0xb5,0x8c,0xc0,0x52,0xc2,0x9b,0xe6,0x4b, + 0xa,0x94,0x83,0x31,0x54,0xee,0xb4,0xff,0xee,0x2d,0x76,0xe9,0x82,0x72,0xb1,0xd3, + 0x56,0x1,0xd9,0x20,0xb4,0xc1,0x22,0x47,0x4a,0x94,0x59,0xb5,0x1c,0x9a,0x3f,0x2, + 0x35,0x85,0x35,0x94,0xb0,0x69,0xc3,0x30,0xab,0x49,0xf9,0xa1,0x69,0x7c,0xe7,0x2d, + 0xb8,0x4e,0xf7,0x83,0xdb,0xb5,0x15,0x15,0x1d,0x12,0x82,0x86,0x21,0xf1,0x1d,0xa, + 0x7c,0xde,0x4,0x84,0xf8,0x40,0xc1,0xb0,0x8e,0x19,0x5f,0xea,0x11,0x8b,0x92,0xba, + 0x6d,0x9f,0x5,0xf4,0xac,0x53,0xd2,0x96,0xac,0x99,0xf4,0x19,0x62,0xd,0xae,0x77, + 0xa5,0x66,0xee,0xa8,0x23,0xbb,0xdc,0x87,0xb5,0x41,0xdf,0x12,0xd9,0xd4,0xac,0x51, + 0x5,0x1f,0x27,0x95,0x26,0xa1,0x1b,0xab,0x6e,0x13,0x3b,0xc0,0x7d,0xb2,0xe0,0xcc, + 0x9c,0x89,0x14,0x25,0x4a,0x8c,0xc9,0x53,0xc3,0xfc,0xbc,0x7c,0x29,0x1,0x2c,0x4a, + 0xbe,0xc7,0x5c,0x40,0xb0,0x52,0x9e,0xbf,0x26,0xd3,0xcb,0x85,0x16,0x20,0xdc,0xf5, + 0xd6,0xe,0x34,0xd,0x9b,0xd6,0xc8,0xd5,0x35,0x60,0x24,0xb3,0x16,0xf9,0xed,0xe4, + 0x5c,0x13,0xce,0x85,0x8d,0x96,0x9f,0x82,0x78,0x28,0xa8,0x5b,0x5c,0x30,0x61,0xba, + 0x88,0xf0,0x98,0xd2,0xbe,0xca,0xfd,0xbf,0x8c,0xfe,0x9d,0x1,0x24,0xf6,0xe8,0x36, + 0x41,0x1e,0xa5,0x8,0x71,0xc6,0xa5,0x88,0x20,0x62,0x97,0xa7,0xdc,0xfe,0x5,0xaa, + 0x2d,0xad,0xae,0x28,0xc5,0xae,0xc7,0xce,0x3c,0xf6,0xae,0x2,0x34,0x6b,0x43,0x7c, + 0x0,0xec,0x23,0x6f,0xcb,0xcf,0x70,0x83,0x1,0xed,0x83,0x73,0xc8,0xce,0x82,0xc6, + 0xd,0x1,0x61,0xbc,0x4a,0x4a,0x67,0x8d,0x27,0xaf,0x50,0xa7,0x91,0x48,0x84,0x25, + 0xfc,0x84,0x2e,0xab,0xc,0xc0,0x8b,0xcf,0x3e,0xe,0x5c,0xa4,0xe7,0x8a,0x7f,0xea, + 0xaa,0x59,0xa7,0x12,0x1,0x4b,0x5e,0x40,0x3a,0x1f,0xa3,0x14,0x38,0xd8,0x98,0x3e, + 0xf6,0x5c,0x33,0x53,0xd4,0x62,0x64,0x46,0x68,0x9d,0x64,0x5,0x93,0x40,0xd1,0x14, + 0x55,0x42,0xe4,0xaa,0xdb,0x66,0x82,0x6a,0x8f,0x89,0xd2,0x80,0x3a,0xbb,0x6c,0x46, + 0x3d,0xbc,0x4a,0x4a,0xde,0x6f,0xec,0x1f,0x65,0x86,0xac,0xcc,0xc9,0x52,0x9b,0x6c, + 0xfa,0xe1,0x43,0x37,0xb5,0xae,0x8b,0xce,0xf,0x52,0x64,0x2d,0x5c,0xb7,0xae,0x1e, + 0x1d,0xa,0xfe,0x39,0x67,0xa5,0x14,0xaf,0x11,0x5c,0x42,0xa1,0xce,0xda,0x20,0x77, + 0x40,0xd2,0x20,0x84,0xb5,0x45,0xcd,0x2c,0x15,0x19,0xf7,0x2d,0x72,0x9c,0xd5,0x2e, + 0xf7,0xa6,0x71,0x34,0xaa,0xc7,0x28,0xf5,0x94,0xa2,0xdc,0x22,0x8a,0xd0,0x21,0x59, + 0x61,0xd3,0x83,0x17,0x95,0x9e,0x78,0xec,0x96,0x36,0xef,0x32,0x3a,0xa5,0xa7,0xc9, + 0x56,0x94,0x72,0x9e,0x84,0x28,0xc9,0xba,0x91,0x96,0x20,0xab,0x67,0x8a,0xc7,0x45, + 0x76,0x96,0x5a,0xcc,0x42,0x72,0xe2,0x68,0xa3,0x59,0x1a,0xb,0x59,0xe7,0x28,0xbf, + 0x51,0xb1,0x6b,0xb1,0xae,0x34,0x45,0x3f,0xc4,0x41,0xcc,0x21,0x35,0x89,0x3b,0xaa, + 0x57,0x6e,0xdb,0x27,0x97,0x95,0xee,0x1c,0x68,0xd2,0xdc,0x87,0x5e,0xb3,0x5c,0x63, + 0xee,0xaf,0x8b,0xb2,0xc6,0xc2,0x2b,0xa0,0x6b,0x51,0x13,0xd7,0x87,0xd,0x5e,0x15, + 0xd0,0x44,0xd8,0x20,0xa8,0x99,0xa6,0xcc,0xf3,0x8,0x20,0x2b,0x1d,0xb3,0x8f,0x84, + 0x5a,0x52,0x3a,0xa9,0x8e,0xf8,0x29,0xfb,0x36,0x2,0xe3,0x18,0x54,0x83,0x8e,0xe, + 0x27,0xc6,0x4f,0xa2,0x95,0x26,0x98,0xb7,0x4,0x3c,0x87,0x3c,0x88,0x9d,0xef,0x3, + 0xbb,0x79,0x4a,0x4e,0x49,0x1c,0x7c,0x9a,0xa9,0xc5,0xad,0x15,0x1d,0x84,0xe6,0xf0, + 0x21,0x65,0xac,0x8c,0x4a,0x2,0xd6,0xa0,0xf9,0x5c,0x1a,0x74,0x4,0xb9,0x57,0x7d, + 0xaa,0xb3,0x19,0x25,0x9,0xe8,0x22,0x80,0x4a,0xd9,0x33,0x73,0xde,0xbc,0x64,0x39, + 0xae,0x95,0xfc,0x66,0xc6,0x2e,0x8b,0x87,0xe0,0x26,0xa9,0xc8,0x5b,0x7,0x73,0x19, + 0x4c,0x29,0xd0,0xec,0xcc,0x70,0x39,0xb4,0x28,0x54,0x77,0xd,0x60,0xe7,0x1c,0x1c, + 0xd1,0x1c,0x29,0x24,0xd6,0x75,0x77,0x1e,0xb9,0xb7,0xd9,0xf6,0x60,0xaa,0xb0,0x9, + 0xfe,0x4,0x7e,0x7,0x10,0xc8,0x7a,0x48,0x12,0x9e,0xa4,0x84,0x43,0xf,0x86,0x91, + 0xb0,0x11,0x25,0x41,0x5b,0x15,0xd4,0xf1,0x68,0x8f,0x62,0x43,0x73,0x26,0xf,0x6, + 0xd1,0x2a,0x25,0xde,0x52,0x7a,0x5,0x92,0x31,0xf,0x7c,0x93,0xc4,0x3f,0x6d,0x43, + 0x56,0x6c,0x4a,0x3d,0x4d,0xe,0xda,0xb1,0x86,0x5a,0x2c,0xa5,0xbc,0x36,0x54,0xe4, + 0x51,0x7d,0x8e,0xea,0xb3,0x2,0x1,0x59,0xa3,0x37,0x92,0x41,0x12,0x3c,0x4b,0x41, + 0x7b,0x50,0x16,0x20,0x11,0x71,0xb8,0xa5,0x49,0x18,0x24,0x61,0x36,0x9,0x8e,0x48, + 0x5c,0xc,0x46,0x36,0x73,0x10,0x94,0xbd,0x65,0xc4,0xe0,0x2f,0x1a,0xa3,0xad,0x15, + 0x26,0xfd,0xba,0x6d,0x5e,0xf1,0x22,0xba,0x48,0x60,0x9c,0x99,0x48,0x47,0x49,0x20, + 0x1b,0x34,0x1a,0xac,0x56,0x7c,0x7d,0xae,0xc,0x70,0x36,0x0,0x19,0xc5,0x98,0xf1, + 0xaa,0xbc,0x6,0xc9,0xa2,0x2a,0x1b,0x58,0xf7,0xc6,0x6c,0xf3,0xd9,0x7d,0xcf,0x6, + 0x23,0x74,0xbd,0x76,0x91,0x1,0xbc,0x52,0x34,0x14,0xf1,0xe2,0x9a,0x10,0x82,0x1, + 0xf2,0xea,0x74,0x2a,0x3f,0x41,0x4e,0x80,0xa9,0xcd,0x4d,0xab,0x5f,0x6d,0xe4,0x92, + 0x1a,0xff,0x8e,0xa1,0x3c,0x61,0x8d,0x75,0xe3,0x95,0x9b,0x5d,0x71,0x8d,0xc1,0x5, + 0x91,0x7,0x51,0xac,0x3c,0x94,0x78,0x3,0x69,0xae,0x50,0x32,0xb1,0x23,0x72,0x25, + 0xf,0x53,0xef,0xc3,0x3,0xa8,0x86,0x4d,0xcd,0x9a,0x30,0x96,0x85,0xd3,0x84,0x48, + 0x21,0xe9,0xbe,0x29,0xb3,0xf2,0x16,0x41,0x19,0x41,0xfe,0x5c,0x3a,0x28,0x7f,0xbc, + 0x73,0x72,0x69,0xde,0x23,0x70,0xc1,0x66,0x63,0x19,0x53,0xdc,0x63,0x31,0x58,0xf3, + 0xe,0xbd,0x45,0x1c,0x6d,0x46,0x83,0x96,0xc,0x6d,0x13,0x44,0xd0,0xad,0x93,0x44, + 0x6f,0x9a,0xa5,0xef,0x4e,0xe7,0x2c,0x89,0x4c,0xaa,0xe9,0x1e,0x11,0xf,0x86,0xb2, + 0xd6,0xa8,0xd5,0x19,0x4,0x7f,0xbb,0x3a,0x6d,0x6d,0x60,0xf5,0x76,0x54,0x84,0xd1, + 0xf,0x58,0xca,0x93,0x66,0xb6,0x35,0xb7,0xbe,0x4c,0xf,0x90,0xe0,0x9d,0x13,0x33, + 0x97,0xc3,0x90,0xb1,0x95,0x1a,0x2b,0x4d,0xba,0x48,0xa6,0x35,0x51,0x61,0xa2,0xa4, + 0xfc,0x45,0x21,0x51,0x70,0xb4,0x3c,0x88,0xe1,0x6b,0x4f,0x6b,0xf,0x81,0x3f,0xab, + 0x1,0x5c,0x5f,0x9e,0x97,0x81,0x53,0x37,0x1b,0x29,0xb1,0x62,0x5e,0x14,0x3b,0x90, + 0xbc,0x91,0x69,0xcd,0x45,0x46,0x96,0xf6,0xa3,0xac,0x44,0x35,0x1b,0xf2,0x1c,0xe7, + 0x9b,0x5e,0xa1,0xf0,0xba,0x59,0xea,0x3b,0xb9,0xf6,0x61,0x82,0xe7,0x64,0x40,0xd, + 0x6e,0xbf,0x26,0xc3,0x43,0x5,0x93,0xf8,0x94,0x88,0xd5,0xc8,0xa1,0x56,0xb7,0xfa, + 0xa2,0xf3,0xfe,0x81,0xe0,0x70,0x50,0x42,0xa9,0xc5,0xc8,0xdb,0xbd,0x50,0x1d,0xe5, + 0x70,0xa2,0xf1,0x80,0xef,0x6d,0xb5,0x14,0xa9,0x84,0x27,0xe5,0x5c,0x86,0xde,0x32, + 0xbf,0xbc,0x67,0x78,0x9b,0x7b,0xfc,0x55,0x80,0x4e,0x3c,0x1,0xe7,0xc1,0xf,0x8b, + 0xc,0x28,0x3c,0x40,0xfc,0xf0,0x11,0xa9,0x52,0xc1,0xb0,0x85,0xd9,0xb1,0xd5,0x54, + 0x4a,0xc,0xb9,0xcc,0x9c,0x3,0x21,0x38,0xa,0x90,0x8,0x12,0x39,0xd,0x2c,0xd, + 0xef,0x53,0x7c,0xb1,0xd0,0xbe,0x9b,0xec,0x15,0x18,0x6a,0x6d,0x3,0xd1,0x81,0x43, + 0xe6,0xd5,0x57,0x17,0x8,0x6b,0x69,0x50,0xe,0x52,0xa8,0x5e,0xce,0x93,0x4f,0x8f, + 0x71,0x4c,0x8c,0x80,0xba,0x1e,0xca,0x2d,0x1e,0x2d,0x15,0x3d,0xb4,0xa6,0x8c,0x3f, + 0x9b,0x6,0x6b,0x3e,0x7c,0x6e,0xb5,0x8e,0xdd,0xe8,0xc3,0x25,0x9,0x44,0xbd,0xed, + 0xa4,0xc3,0x9b,0xa4,0xdf,0x35,0xc4,0x72,0x3e,0x81,0x6d,0x16,0x46,0x94,0x61,0x33, + 0x58,0x11,0xb0,0x33,0xac,0x31,0xfc,0x7f,0x8d,0x38,0x46,0x18,0xb8,0x55,0x92,0xba, + 0x6a,0x52,0x57,0x92,0x61,0xc5,0xde,0x6f,0x84,0xa8,0xd9,0x82,0x4a,0x62,0x95,0x2f, + 0x6e,0xa2,0x70,0x9d,0x43,0xb3,0xf2,0x48,0xe1,0x4a,0x8d,0xc6,0xa0,0x47,0x2d,0xa2, + 0xd0,0x3c,0x15,0xc,0xda,0xe7,0x40,0xee,0xd2,0x3e,0xc4,0xab,0x8c,0xae,0x54,0xde, + 0x29,0xbf,0x9b,0x10,0x4,0x78,0xc7,0x98,0xdf,0x4e,0x76,0xd7,0x94,0x92,0xc9,0x5d, + 0x8d,0xea,0x52,0x58,0xa9,0x50,0x93,0x36,0x9e,0xb8,0x4e,0xd9,0x51,0xe2,0x91,0xbb, + 0x53,0x54,0x3a,0xe3,0x73,0xb5,0x47,0xea,0x65,0xd6,0xb1,0xb8,0x63,0x62,0xd9,0x7d, + 0x27,0xd4,0x5,0x5f,0xba,0x1a,0x97,0xb9,0xc6,0x7,0x2b,0xe,0x69,0xb3,0x96,0x42, + 0x4b,0xfe,0x79,0xf1,0x9f,0x6b,0xdd,0xb5,0x23,0xe4,0x3,0xb9,0xc8,0x54,0x22,0x49, + 0x85,0x60,0xf3,0x50,0x5a,0x73,0xda,0xd0,0x2a,0xa7,0x5f,0xc7,0x51,0x28,0x5b,0x7c, + 0xb0,0x33,0x18,0x39,0x10,0x93,0xf,0x46,0x4b,0x96,0x28,0x97,0x42,0xe,0xa4,0x9, + 0x40,0x8a,0x45,0x76,0xfa,0x47,0xe4,0xd5,0xa0,0x68,0x32,0x8,0x37,0x2e,0x30,0xe, + 0xc4,0xbd,0x4,0x81,0x83,0x52,0xe5,0xc7,0x1,0x51,0xf4,0x65,0x2b,0x82,0xae,0xbe, + 0xb,0x1f,0xb9,0x37,0x1e,0x35,0xad,0x59,0xb4,0x8e,0xe9,0xa6,0x31,0x7a,0x14,0x3, + 0x94,0x38,0xe2,0xf,0xf7,0x3c,0xb9,0xc3,0xac,0xc1,0x12,0xe1,0xdc,0x1d,0x6b,0x8a, + 0xf4,0x64,0x9c,0x5c,0x3a,0x91,0x23,0xac,0x8d,0x9f,0x9a,0x58,0x75,0xa6,0xb5,0x48, + 0xf3,0x54,0x20,0x6c,0xb5,0x27,0xe3,0xb8,0x19,0x5b,0xe,0xdb,0x2f,0xdb,0x61,0x13, + 0xcf,0x8a,0x30,0xb,0xdb,0x7d,0xb9,0x11,0x48,0x6a,0x5f,0xbb,0xe7,0x9d,0xa6,0xae, + 0xcd,0xbe,0x56,0x57,0xf5,0x33,0xef,0x60,0x10,0x30,0x1d,0x92,0xa2,0x1,0x2c,0xb7, + 0xb9,0x5c,0xc2,0x29,0xe4,0x5d,0x3f,0xf3,0x4,0xfc,0xbc,0xe4,0xb8,0x45,0x8d,0x97, + 0x4c,0x96,0x29,0x13,0x89,0x28,0x59,0x35,0x3c,0x26,0x5,0x9e,0x87,0xe,0xeb,0xa2, + 0x50,0x6c,0x8f,0x49,0x64,0x48,0xc8,0xb3,0x79,0x4f,0xf7,0x12,0xf0,0x90,0xd7,0x3d, + 0xa9,0xdd,0x9e,0x48,0xab,0x74,0xd8,0x63,0x65,0xd1,0x53,0xa4,0x67,0x5a,0xcd,0x18, + 0xd7,0xd5,0xf5,0xff,0xf1,0x22,0x78,0xc7,0x13,0x91,0xe5,0x4c,0x47,0x1b,0xc5,0x59, + 0xe4,0x1e,0x4f,0xcf,0xd6,0x40,0xf1,0x7a,0x2c,0x82,0x47,0xa4,0xb2,0xbe,0x43,0x88, + 0x32,0x6f,0xa9,0x66,0xcc,0xc8,0x2f,0xea,0x60,0xe,0x45,0xd1,0x7a,0xa1,0xf2,0x94, + 0x52,0x65,0xa9,0xc6,0xd4,0x30,0xb0,0xf6,0x87,0x2a,0xa9,0x45,0x1b,0x92,0xe8,0x76, + 0xa2,0x93,0x5c,0x79,0x92,0xad,0xb4,0x9b,0xe7,0x51,0x79,0x36,0x5a,0x51,0x6,0xb1, + 0x62,0x3b,0x5b,0x4f,0x45,0x78,0x2f,0xa7,0x61,0xaf,0x9b,0xf,0x51,0x9f,0xea,0x92, + 0x9d,0x8,0x1a,0xc2,0xea,0x84,0x22,0xc6,0x95,0x98,0x78,0xb8,0xb2,0x6e,0xe8,0xc2, + 0x2d,0xc9,0x69,0xf6,0x30,0xf3,0xd7,0x66,0xff,0xa3,0x75,0x83,0xb,0x12,0x45,0x15, + 0xa4,0x48,0xf7,0x0,0x21,0x9d,0x48,0x61,0xd3,0xba,0x20,0x24,0x4c,0x88,0xe7,0xde, + 0x3e,0xbd,0x32,0x32,0x8d,0xf5,0x65,0x10,0x43,0x9a,0xc3,0x3f,0xd5,0x83,0xb4,0xe0, + 0x11,0xc6,0x61,0x34,0x30,0x0,0x9c,0xee,0xa3,0x50,0x26,0xb5,0xbc,0x46,0xf4,0x2e, + 0x1,0x2,0x12,0xd,0x83,0x0,0x65,0x36,0xe1,0xf0,0xf1,0x9c,0x3a,0xd2,0x7a,0xc6, + 0xda,0xb9,0x84,0x61,0x4c,0xa7,0x31,0x79,0x11,0x16,0xd6,0xb9,0x91,0xd0,0x54,0x2e, + 0xef,0x64,0x7f,0xd6,0xf2,0x65,0x64,0xbb,0x23,0x19,0xa4,0xb7,0xfc,0xea,0x44,0xfa, + 0x13,0xd9,0x78,0xfe,0xc8,0x9b,0xac,0xba,0x14,0x94,0xe2,0xe9,0x33,0xb6,0x9d,0x6e, + 0x72,0x8,0xd5,0x45,0x4,0xa7,0x8b,0xb4,0xd,0xe9,0x7,0x97,0xd,0x1c,0xd4,0xfc, + 0x37,0x2d,0xf3,0xb6,0x3a,0xf6,0xd5,0x25,0xfc,0x25,0x61,0x3d,0x5a,0x20,0xa3,0x94, + 0x98,0x90,0xe2,0xb8,0xd3,0x26,0x91,0x6f,0x2b,0x33,0xd4,0x99,0xa0,0x5d,0x84,0x42, + 0x74,0x21,0x85,0xed,0x84,0x1b,0x7f,0x19,0x14,0x6c,0x2f,0x4a,0x62,0xa7,0xfc,0xfd, + 0xa2,0x4c,0x4b,0x20,0xc4,0x47,0x21,0x83,0x1e,0x94,0xd6,0x2f,0xf9,0xc3,0x5e,0x6c, + 0xcf,0xa0,0x99,0x11,0x8,0x96,0xb1,0xd8,0xa3,0xfd,0x20,0x54,0x2d,0x0,0xa2,0x3c, + 0xbd,0xa2,0xae,0xaa,0x16,0x27,0x2c,0x58,0x5a,0xc4,0x15,0x65,0x18,0x9b,0xd5,0xc0, + 0x4e,0x8d,0xb0,0x58,0xec,0x68,0xc6,0xcb,0xb8,0x51,0x43,0x43,0x41,0x73,0x46,0xd, + 0xd5,0x1c,0xaf,0x9f,0x93,0x68,0x58,0xe3,0x92,0x9a,0xdb,0x1d,0xcf,0xd0,0x71,0x1b, + 0x62,0x54,0x31,0xe,0x8a,0x9f,0x9d,0x39,0xe1,0x4c,0x53,0x15,0x6a,0xd3,0x1a,0xd0, + 0x8c,0xe,0xfc,0xdc,0xce,0x73,0xad,0x53,0x21,0x41,0xba,0x2a,0x36,0xc3,0x4d,0x16, + 0x41,0x13,0xca,0x20,0xf4,0xd4,0x24,0x2c,0x97,0x10,0xef,0xc3,0x4b,0xc8,0x8b,0xd0, + 0x5a,0x47,0xa4,0xd6,0x20,0xf1,0x75,0x48,0xa4,0x6c,0x42,0xb7,0xd6,0x12,0x61,0x55, + 0x63,0xa5,0x74,0x4c,0xb6,0xf2,0xb,0x19,0x2b,0x32,0x1e,0xa6,0xb4,0xa2,0x18,0x8f, + 0x4b,0x42,0x93,0x5a,0x70,0x16,0x3f,0x4d,0xe8,0x76,0x5f,0x55,0xac,0x2b,0x3e,0x40, + 0x53,0xd7,0x44,0x7b,0x57,0xbe,0x1c,0x81,0x22,0x6b,0x5a,0x80,0x45,0x42,0xb0,0x21, + 0x2f,0x3b,0x62,0x5d,0x1e,0xd1,0x92,0x74,0xb0,0x5,0xd1,0x8,0x2b,0xb2,0xb3,0x6d, + 0xa8,0xc2,0x29,0xee,0x52,0x73,0x22,0x64,0x29,0xd8,0xf9,0x82,0xa5,0x6d,0x93,0xa, + 0xf,0x2a,0x8,0x6b,0x1c,0xc1,0x97,0x6e,0x83,0x89,0xb2,0x1c,0x21,0x6d,0xca,0x27, + 0x35,0x2b,0xfa,0x5d,0xc,0x4f,0x91,0xac,0xce,0xbf,0xa0,0x91,0x54,0xa3,0xdc,0xcd, + 0xd0,0x9f,0xf0,0x4a,0x82,0x84,0x5e,0x1a,0x47,0xe9,0xdc,0xe0,0x98,0x1e,0xa7,0x13, + 0xcb,0x88,0x8a,0xd0,0x9,0xf6,0x8a,0x6f,0xd,0x25,0x78,0x2b,0x26,0x44,0xb3,0x61, + 0x73,0xda,0xf4,0xb4,0x38,0xc6,0xca,0x52,0x7b,0xa8,0xa3,0xc0,0x5,0x94,0x32,0xf, + 0x3f,0x78,0x74,0xd0,0x99,0x11,0xe1,0xe5,0x38,0x1,0x95,0x1a,0x1c,0x69,0xc9,0x7a, + 0x96,0x81,0xd2,0x8c,0x89,0x27,0x22,0x1c,0xcc,0x36,0xb4,0x1a,0x45,0xe9,0x58,0x2f, + 0x3a,0x36,0x38,0x9b,0xcc,0x4a,0xa4,0x32,0x89,0x38,0x5,0x75,0xc5,0xa8,0x21,0x83, + 0xa9,0x9c,0x7f,0x96,0xa6,0xb7,0x50,0xcc,0x43,0xb6,0x2f,0xe8,0xc5,0x61,0xe1,0xf1, + 0xac,0xe9,0x6b,0x49,0xd3,0x72,0x50,0xe0,0xc5,0xa1,0x1c,0x54,0xce,0x2c,0xfb,0xe5, + 0x74,0x7d,0xe9,0xa,0x7f,0x96,0x95,0xf,0xbd,0x6,0xaf,0xa7,0xf0,0x76,0xf5,0xce, + 0x62,0x8b,0x88,0xc6,0x79,0x8b,0xd5,0xde,0x16,0xc9,0x3a,0xac,0x79,0x23,0x5f,0xea, + 0x94,0x81,0x76,0xf6,0xab,0xf3,0xd6,0xb6,0x2a,0xd7,0xb5,0x8a,0x5b,0x24,0x9b,0x65, + 0x17,0x9d,0x0,0xa,0xcc,0x20,0xbe,0x94,0xd8,0xdd,0xb9,0xd7,0x75,0x39,0xb,0x40, + 0x97,0x5,0x95,0xbf,0x8b,0x27,0xa0,0x6f,0xe4,0xe8,0xa0,0x8a,0x84,0x72,0xa1,0x31, + 0xe3,0x44,0x67,0xe7,0x2c,0x65,0x94,0x9d,0xb1,0x67,0x71,0xf8,0x70,0x14,0x24,0xd9, + 0x2d,0x7b,0x2a,0xb7,0x94,0x34,0x78,0x92,0xb4,0x76,0xf5,0x67,0x98,0x88,0x76,0xb4, + 0x66,0x89,0xf5,0xde,0xea,0x1b,0x5,0x4f,0x74,0x9c,0x3c,0x86,0xd8,0xc1,0x26,0x20, + 0x4e,0x4c,0x2f,0x34,0xf,0xf2,0xb7,0xa5,0xa5,0x6,0xfd,0x61,0xa5,0x54,0x43,0xe, + 0x4e,0xb0,0x9f,0xa5,0x92,0xaf,0x56,0x8b,0xb7,0xc9,0xf2,0xeb,0x35,0x73,0x70,0x41, + 0x2c,0xdf,0xfa,0x33,0xb4,0x5b,0xa7,0x73,0x3d,0x6f,0x2c,0xca,0x16,0x8b,0xee,0x28, + 0xe2,0x92,0xe,0x72,0x25,0xda,0x69,0xac,0xba,0xed,0x57,0x5d,0x79,0xcb,0xb8,0x68, + 0x5a,0x36,0xf2,0x9a,0x78,0x37,0x83,0xe1,0xeb,0x53,0xda,0xd3,0x22,0x98,0x33,0xf6, + 0x75,0xb5,0xc8,0x82,0xdd,0x48,0xea,0xdb,0xb2,0xe7,0xc4,0xa0,0x3c,0xa,0x4e,0xa5, + 0x29,0x6,0xd,0x1a,0xcd,0xaa,0x7,0x54,0xe3,0x2d,0x69,0x1,0x48,0xb7,0xe0,0x90, + 0x3c,0xa5,0xea,0x55,0xb,0x3f,0x80,0x27,0x46,0x45,0x79,0xb6,0x21,0xd6,0xac,0x8b, + 0x45,0x48,0xe2,0xb2,0xa7,0x5f,0xdb,0xef,0xee,0xc8,0xf9,0xef,0xbe,0x2e,0x93,0x20, + 0x91,0xdb,0xb9,0x69,0xd4,0x94,0x9e,0xf7,0xf0,0x64,0x80,0x6b,0x1,0xa8,0xe3,0x1d, + 0x3a,0x1,0x7f,0x18,0xdd,0x5b,0xb0,0x23,0x8,0xe1,0xa7,0x86,0xc8,0x6c,0xf9,0x5d, + 0x62,0x58,0xe1,0xb8,0xb0,0x28,0x76,0xce,0x78,0x12,0xc4,0xbf,0xdb,0x38,0x96,0x35, + 0xa8,0x9f,0x7e,0xc,0x6b,0xc4,0x32,0x13,0x17,0x8e,0x6c,0x4,0xfe,0x1c,0x7a,0xe2, + 0x65,0x59,0x4b,0xc6,0x8f,0x7a,0x2e,0x74,0x52,0x7,0x6a,0x79,0xe0,0x42,0xda,0x6e, + 0x46,0x3b,0x4f,0x60,0x50,0xfd,0x29,0x5a,0xf0,0x4e,0xb,0x2d,0x96,0xc4,0x88,0x7d, + 0x4,0xa7,0xa6,0x41,0x67,0x43,0x5e,0x93,0x21,0x7d,0xdf,0x49,0xe,0xab,0x42,0x49, + 0x51,0xa1,0x59,0xea,0x9e,0x7b,0xd2,0x38,0xa3,0xcb,0xd3,0xf5,0x92,0x30,0xb0,0xd8, + 0xa3,0xb3,0x85,0x3b,0x4d,0xa7,0xa8,0xd4,0x2b,0x4d,0x5a,0xe8,0xcf,0x4c,0x4b,0xc6, + 0x8a,0x6f,0x39,0x44,0xdb,0x7a,0x49,0x35,0xe1,0x5d,0x75,0x69,0x33,0x6b,0x72,0x4c, + 0xcb,0x6c,0x6c,0x9a,0x8,0xaf,0x7,0xc1,0xe7,0xfd,0x5f,0x79,0x74,0x6c,0x4,0x68, + 0x43,0x56,0x90,0x72,0x95,0x5a,0xa,0xaa,0x7a,0x85,0xb5,0xe8,0x4e,0x30,0x6a,0x24, + 0xf7,0x5f,0x52,0xb5,0xaa,0x12,0x29,0xbf,0x40,0x8b,0xf1,0x40,0xc1,0x1f,0x32,0x58, + 0xd7,0x8a,0xd2,0xf1,0xf9,0xf9,0xd5,0x32,0xe9,0x67,0xcb,0xcb,0x9b,0xfe,0x7e,0x1a, + 0x9f,0x42,0x56,0x84,0x31,0x8d,0xf2,0x62,0x86,0x19,0x7,0x4b,0xcc,0x43,0xa7,0xc3, + 0xaa,0x69,0xda,0x5f,0x4e,0x48,0x78,0xe4,0xec,0x6,0x21,0x6d,0xf5,0xd9,0xae,0x36, + 0xa9,0x74,0x29,0x66,0x87,0x42,0xe4,0xbc,0xd4,0x15,0x4c,0xe3,0x61,0x16,0x3d,0x53, + 0xe1,0xaf,0x42,0x7a,0x89,0xd2,0x8e,0xb2,0x31,0x12,0x10,0x1c,0x11,0xeb,0xe5,0x9e, + 0x51,0x6,0x2,0x29,0x2b,0xba,0x3c,0xc3,0xae,0x1d,0x4e,0xc7,0x28,0x47,0xe8,0xf2, + 0x28,0x51,0xe,0x80,0xfd,0x6,0x14,0x95,0xbe,0x7,0xbb,0x2c,0xde,0x38,0x37,0x21, + 0xc7,0x5a,0x72,0x33,0x24,0x8e,0x7c,0xe9,0xfc,0xdc,0xd5,0x5,0xd,0xd,0x86,0xb6, + 0x34,0x8f,0xa8,0x5e,0xe0,0xe5,0x70,0x63,0x2f,0x8a,0x66,0x91,0xd8,0xe4,0x9f,0xab, + 0x48,0xc1,0xaa,0xd1,0xa8,0xad,0xfb,0x8,0x0,0x9b,0x85,0xb8,0xd2,0x51,0x2f,0x7b, + 0x38,0x5,0xf9,0xc2,0x9c,0x80,0x92,0xf9,0xb5,0x2a,0x9,0x2e,0xfd,0xc2,0xb,0xc, + 0xac,0x48,0x9,0x4b,0xca,0x5b,0x4b,0xcd,0x5,0x2f,0x74,0x59,0xaf,0x2e,0xcd,0x52, + 0x12,0x78,0x4a,0xed,0xbe,0xf2,0x99,0xa0,0x90,0x92,0xb7,0x2d,0xc9,0x64,0x22,0xb2, + 0x8c,0xf5,0x59,0xa0,0x58,0x8a,0xab,0xb8,0xd4,0x47,0xa5,0x3,0xd0,0x36,0xc3,0x61, + 0x29,0x8,0x73,0x80,0x10,0xa9,0xe,0x46,0xc6,0x24,0x60,0x13,0xd7,0x26,0x11,0xe3, + 0xd9,0x72,0x41,0xe2,0xf5,0x29,0x45,0xc7,0xce,0xa4,0x3a,0x7f,0x7e,0xe3,0xbf,0x85, + 0x30,0x5a,0x68,0x5c,0x60,0xf4,0x33,0xf4,0x88,0xd2,0xb9,0x7f,0xf4,0xd0,0x1a,0x49, + 0xca,0x70,0xc5,0xaa,0xef,0x26,0x8b,0xb2,0x6e,0x6a,0x38,0x3,0xf2,0xdd,0xd8,0xb7, + 0xaa,0x68,0x9e,0x83,0x53,0x86,0x4e,0xaa,0x49,0x60,0x4d,0x6a,0x21,0xb,0xd3,0x10, + 0xad,0xa2,0xce,0xe0,0x59,0xc3,0x61,0x60,0x3e,0x43,0x89,0xff,0x7e,0xda,0x8b,0x4b, + 0x1a,0x33,0x61,0x29,0xb,0x5b,0xe8,0x9d,0xe8,0xf9,0xe0,0x15,0x13,0x4f,0x72,0x7b, + 0x79,0x36,0x91,0x27,0xeb,0xae,0x55,0xf2,0xe7,0x6f,0x40,0xc,0xa3,0x21,0x6e,0x74, + 0x17,0xc0,0xac,0xb9,0xb9,0x4b,0x3a,0x44,0x6b,0xb2,0x17,0xa9,0x90,0xaa,0xd4,0x56, + 0x66,0xf9,0x84,0x6,0x22,0x3d,0x6d,0xfa,0x1f,0xcd,0x1e,0x49,0x3a,0xe9,0x96,0x60, + 0xb5,0x8d,0x24,0x19,0x4e,0xdd,0xcc,0x1,0xf1,0x3e,0x23,0x87,0xe7,0xfb,0xf9,0x4b, + 0xc5,0xbe,0xc9,0x0,0xa5,0x4a,0xf,0x43,0xb4,0xf0,0xb,0xa3,0x91,0xa1,0x9a,0xfe, + 0x78,0x1a,0xc3,0x25,0xad,0x47,0xf0,0xa0,0x73,0x95,0xce,0x3f,0x98,0x18,0xf9,0x65, + 0x5a,0x9b,0x44,0x51,0x92,0xbc,0xe5,0xbc,0x7d,0xc4,0x22,0x13,0x8f,0x87,0xa5,0x97, + 0xae,0x43,0xf9,0xcf,0xf1,0x8b,0xc3,0x89,0x42,0x64,0xed,0x33,0xd5,0x26,0x29,0xa9, + 0x93,0x21,0x39,0x3f,0xb0,0x5b,0xc0,0x15,0x29,0x94,0x1b,0x94,0xfd,0x95,0xdb,0x77, + 0x54,0xb2,0xf5,0x2b,0x49,0x65,0x4d,0xbd,0xe4,0xa3,0x94,0xa2,0x8a,0x47,0x2a,0x24, + 0xb2,0x4c,0x70,0x13,0xd4,0xc0,0xa0,0x69,0x92,0x9a,0x7,0xe2,0x8a,0x75,0x77,0x48, + 0x5f,0xbf,0x2c,0x3a,0x2b,0x7b,0x39,0xe3,0x3c,0xd0,0xc5,0x26,0x26,0xa4,0x7a,0xe6, + 0x70,0x94,0xa5,0xd8,0x13,0x42,0x22,0x83,0x8c,0x8,0x8a,0x32,0x7,0xc9,0x41,0x1f, + 0xc2,0xfa,0x47,0x37,0x46,0xe8,0x3e,0x96,0xc0,0x9e,0x2e,0x34,0xf3,0xb4,0x59,0xc6, + 0x80,0xc8,0x63,0x40,0x8a,0x75,0xd4,0x54,0x8d,0x23,0xe7,0x3c,0x9b,0xc,0x3a,0xdd, + 0xfe,0x20,0x51,0x54,0x36,0x3e,0x92,0x4d,0x20,0xbf,0xae,0x9a,0x9d,0x13,0x43,0xf7, + 0xe5,0x1e,0x7f,0xa4,0x8d,0x80,0xa6,0xc2,0x4e,0xeb,0x58,0x1e,0x36,0x11,0xd4,0x85, + 0x79,0x11,0x53,0x14,0x59,0x57,0x50,0xda,0x92,0x89,0x0,0xb6,0xc9,0xcb,0xe3,0x22, + 0x7f,0x9e,0x81,0xe8,0xbc,0x29,0xcc,0x28,0x8a,0xc7,0xe5,0xbf,0x9e,0x17,0xbe,0x1c, + 0x64,0x42,0x45,0x1b,0x34,0xb2,0xc9,0x7c,0x20,0x39,0x50,0xb8,0x22,0x83,0xbb,0x61, + 0xb7,0x4c,0x8b,0xf4,0x18,0x65,0xc4,0x8,0xf3,0xf8,0x91,0x2,0x3e,0x24,0x80,0x7c, + 0x12,0x2f,0xe4,0x24,0x9f,0x6a,0x73,0xea,0x99,0x8f,0xe0,0x13,0x9c,0xb1,0xec,0x49, + 0xa2,0xd8,0x44,0xd7,0x75,0x25,0xcb,0x9a,0xaa,0xc0,0xb,0x85,0x21,0xb2,0x8b,0x67, + 0xab,0xf8,0x42,0x9c,0x6,0x5c,0xa,0xf5,0xd4,0xca,0x18,0xf3,0xa8,0x8e,0xdc,0x58, + 0x81,0xec,0x24,0x65,0xd8,0x79,0x61,0x91,0xb5,0x58,0x6a,0x31,0x83,0x91,0x26,0xc8, + 0xa9,0xd4,0xf4,0x2b,0x52,0xaf,0x46,0x9e,0x15,0xb1,0xb1,0x6c,0xc9,0xe1,0x7,0x8b, + 0xae,0x3e,0xf2,0x7c,0x16,0x94,0xb0,0x94,0x4,0x81,0xe0,0x28,0x37,0x2d,0x2c,0xd9, + 0xa2,0x8,0x95,0x1c,0x66,0x13,0x70,0x37,0x95,0xfa,0x94,0xc7,0x64,0x68,0x7d,0x3f, + 0xe,0x3,0xc0,0x43,0x3b,0x12,0x1a,0xe3,0xb2,0x28,0x25,0xd4,0xce,0x6d,0x19,0x62, + 0xd1,0x68,0x3c,0x3f,0xa5,0xc5,0xf2,0xb6,0x88,0x5f,0x6a,0xca,0x8c,0xea,0x46,0xdc, + 0xb0,0xcd,0x44,0xb4,0xe8,0x1e,0x1d,0x63,0x89,0x3c,0x14,0x97,0x65,0xec,0x66,0x67, + 0x19,0xfb,0xb3,0x39,0xdd,0x73,0xd3,0x1c,0x2d,0x99,0x2c,0x56,0xb5,0x97,0x7e,0x5d, + 0xb4,0x7d,0x69,0xa7,0xba,0x2d,0x74,0x20,0x25,0x9d,0x2e,0xa2,0x1a,0xcd,0xf6,0xf1, + 0x2c,0xc0,0x48,0x91,0x2e,0xbc,0xfb,0xcb,0xa0,0x9a,0x5c,0x54,0xd9,0xc1,0xa4,0x95, + 0x92,0x6,0xb6,0xce,0x31,0xb2,0x17,0x45,0x4,0xb8,0xc8,0x87,0x14,0xad,0xa5,0x7e, + 0x39,0x7d,0xed,0x3c,0xc3,0xa5,0xf9,0xfb,0xfc,0x9c,0x92,0x5a,0x56,0x93,0xea,0x58, + 0xb7,0x40,0xc,0x39,0x7f,0x2f,0xc7,0x11,0x71,0x86,0x6f,0x2c,0xe7,0x34,0x2b,0x9a, + 0x53,0x75,0xad,0x21,0x74,0x4,0xb0,0xf1,0xc4,0xc4,0x4e,0x76,0x75,0x94,0xf2,0xf, + 0xb8,0x84,0xa3,0x14,0xa6,0x32,0xef,0x83,0xd1,0xca,0x6a,0x5,0x7c,0xe4,0x49,0xb2, + 0x6f,0x69,0xfd,0xc1,0x27,0xab,0x4a,0x7d,0xb7,0xb0,0x91,0x14,0x88,0xf0,0xe7,0x86, + 0x5b,0xcd,0x4,0x7a,0x8e,0xff,0xe,0x85,0x6d,0x7c,0x6f,0x2a,0x1,0xd6,0x57,0xb3, + 0x38,0x8,0xdf,0xf6,0x5a,0x7c,0xef,0x5a,0xec,0x36,0x69,0x62,0x56,0x34,0x1a,0x33, + 0xa,0x9b,0x3a,0x7a,0xfe,0xfe,0xa1,0xeb,0xa,0x4a,0xd2,0x4e,0xb7,0x94,0x2b,0x61, + 0x61,0x2b,0xcb,0x28,0x8d,0x9d,0x22,0x17,0x20,0x69,0xc7,0x4c,0xbc,0x9,0x2f,0xe0, + 0x43,0x91,0xa1,0xed,0xf3,0x68,0x5f,0xe1,0x47,0xf,0x11,0xaa,0x8,0xf1,0xe9,0x59, + 0xcc,0x21,0x60,0xec,0x3b,0x19,0x5d,0xe6,0xa,0x58,0x19,0x63,0x61,0x79,0xa9,0x3b, + 0x37,0x6b,0x68,0x61,0x59,0x1a,0x9a,0xb1,0xf9,0xde,0x38,0xb3,0x9e,0x78,0xa5,0x4, + 0x96,0x38,0x48,0x9f,0xad,0x1e,0x9d,0x8b,0xc0,0xba,0x8b,0xd8,0xf0,0x9f,0x22,0xa4, + 0xd4,0xdc,0xbd,0x24,0x4c,0x5b,0xe8,0x66,0xa0,0x64,0xdf,0x23,0x7,0x4,0xf1,0xfc, + 0xb5,0xc,0x94,0x7c,0x44,0x0,0xd,0xf6,0x1c,0x7f,0xe6,0x6b,0xd3,0xd1,0xca,0xcb, + 0x62,0x9a,0xea,0x45,0x42,0x3e,0xc0,0xed,0x6a,0x58,0x42,0x64,0x1f,0xbd,0x4d,0xc0, + 0x48,0x0,0xa7,0xfe,0xfe,0xf8,0xed,0x22,0x48,0x32,0x68,0x9e,0x44,0x29,0xfb,0x18, + 0xd6,0xc7,0x13,0x49,0x83,0xb4,0xa5,0x4a,0x93,0x7d,0x36,0xde,0xed,0x2,0x7d,0x1d, + 0xbb,0x23,0x9d,0xc1,0x2a,0x87,0x72,0x40,0x5f,0x54,0xaa,0xf4,0x2,0x98,0xe,0x32, + 0x17,0xb0,0x52,0xf,0x8a,0x3d,0x17,0x57,0x4d,0x93,0x59,0xff,0xba,0x6b,0x4e,0xdb, + 0xe0,0xcb,0x48,0x41,0xaa,0x6a,0x53,0x3d,0x4b,0xda,0xe8,0xf9,0xbf,0xdf,0x49,0x46, + 0x11,0x5d,0x6e,0x70,0x93,0xec,0x25,0xea,0xd5,0xef,0x20,0xf1,0xc2,0xf1,0x85,0xc8, + 0x2,0xb9,0xc4,0x18,0xe5,0x95,0xb9,0x50,0x50,0x89,0xac,0xdc,0xf5,0x64,0x49,0x28, + 0xf,0x98,0x6c,0x7c,0x46,0xd8,0x18,0xa7,0x8b,0x4,0x1f,0x3a,0x7d,0xe4,0x9,0x41, + 0x9,0x7a,0xa7,0xeb,0x8c,0x1b,0x75,0x9f,0x16,0x63,0x5f,0x21,0xce,0xbe,0x63,0xb4, + 0x5a,0xb2,0xa2,0x20,0x95,0xb6,0xb6,0xf2,0xd0,0xec,0x19,0xa7,0x94,0x29,0x4d,0x4f, + 0x7b,0x2d,0x2,0x22,0x58,0x52,0x37,0xbf,0x67,0x49,0x9d,0x6,0x78,0x77,0x6f,0x4, + 0xa8,0x6c,0x1,0x75,0xe3,0x2c,0x5f,0x18,0xa6,0xe8,0xcd,0x2f,0x13,0xaa,0x5f,0x2e, + 0x8d,0xcd,0xa3,0xf3,0xca,0xdb,0x2c,0xce,0x74,0x49,0xff,0x96,0x2a,0x47,0xcd,0x95, + 0xb7,0x57,0xf6,0x94,0x95,0x6b,0x75,0xcf,0x8c,0x84,0xba,0xe2,0x48,0xba,0xb9,0xf0, + 0xc,0xd0,0xbe,0x5f,0xf3,0xa8,0x6f,0xc9,0x56,0xde,0x76,0xa9,0x68,0x1a,0x1,0xab, + 0xa0,0x7c,0x22,0x1e,0x73,0x3c,0x9d,0xe,0x93,0xf3,0x54,0x3a,0x89,0x89,0x4c,0xa6, + 0xb6,0x93,0xc7,0x20,0x50,0x8e,0xe4,0xc5,0xe2,0xd9,0xee,0xf4,0xef,0x68,0x7c,0x76, + 0xe,0xe6,0x70,0xbd,0x57,0xb6,0xf4,0x65,0xe4,0x18,0x65,0x2,0x40,0x57,0x5f,0x78, + 0x14,0x72,0x2d,0x69,0x79,0x56,0x41,0x1f,0xb2,0x87,0x3e,0x62,0xef,0xf3,0x88,0xb1, + 0xfe,0x4c,0x84,0xd6,0x56,0x69,0xf2,0x28,0x6b,0xf0,0xf,0x58,0xf4,0xd5,0x9c,0xe8, + 0x12,0xf1,0xcc,0x8c,0x6f,0x1a,0x7f,0x4f,0xb5,0xa,0x67,0x9a,0x15,0xd9,0xea,0x17, + 0xbf,0x1b,0xad,0x69,0x9d,0x24,0xb9,0x38,0xc7,0xcc,0x2e,0xee,0x39,0x1e,0x7b,0xfe, + 0xbd,0xf4,0xfc,0x23,0x3d,0x81,0xe1,0x3b,0x45,0xee,0x82,0xc5,0xf7,0xb6,0xca,0xb6, + 0x9b,0x96,0x6d,0xad,0x34,0xd5,0xd2,0x8d,0xcb,0xb,0x4b,0xa2,0x88,0x50,0x90,0xba, + 0xad,0x2,0x24,0x6f,0x28,0x51,0x27,0xa2,0xad,0x62,0xc5,0x97,0x9,0x1f,0x72,0x28, + 0x4c,0x84,0x29,0x94,0xb3,0x7,0x59,0x84,0x1a,0x13,0x5b,0x58,0x6,0x82,0x8a,0xac, + 0x45,0xe5,0xf6,0x65,0xbc,0xae,0x45,0x65,0x63,0x6d,0x99,0x79,0x8d,0x5c,0xac,0x27, + 0x37,0x1,0x1b,0x4c,0x13,0xea,0x50,0x37,0xd6,0x80,0xe3,0xdf,0xf,0xf4,0x2b,0x72, + 0x9a,0x56,0xd2,0x10,0x53,0x60,0xbb,0x6c,0x79,0xe1,0x20,0x15,0xd4,0xb4,0xf9,0x31, + 0xd3,0xc,0x9b,0x3,0xcf,0xf3,0xcd,0xce,0xff,0x4d,0x2a,0xf1,0xe1,0x4a,0x9b,0x48, + 0x1f,0x23,0xb5,0x68,0x28,0xb3,0x95,0x55,0x81,0x59,0x1d,0x8c,0xcd,0x8f,0xbe,0x55, + 0x8f,0xb9,0xe4,0x30,0x70,0xcd,0xd3,0xb,0xaa,0x2,0x7b,0xba,0x23,0x52,0x90,0x9f, + 0x91,0x8b,0xb4,0x42,0x54,0x91,0x1a,0xfd,0xa8,0xa8,0xbb,0x84,0x19,0xcb,0xb2,0xe6, + 0x11,0x58,0xca,0x32,0x96,0x55,0xb7,0xf6,0x81,0xc7,0x9c,0x9b,0x7b,0x46,0x6c,0xf0, + 0x86,0xd9,0x45,0x90,0x47,0x39,0xbc,0x77,0x50,0x84,0xc5,0x2d,0x33,0x2,0xf6,0x46, + 0xbd,0xa2,0x74,0xb6,0x54,0x10,0xb7,0xd2,0x6,0x24,0x71,0x92,0x56,0x55,0x29,0x8a, + 0xb7,0xd7,0x7f,0xa6,0xa0,0x2,0xdd,0xed,0x59,0xe1,0x6f,0xa9,0x16,0xcb,0x7d,0x23, + 0x2b,0x56,0xa1,0xc6,0x69,0xd6,0x18,0xf0,0x96,0x58,0xdf,0x50,0x62,0x8c,0xa7,0x28, + 0x83,0x26,0x75,0xf4,0xac,0xb2,0xf,0x3c,0xc2,0xbc,0x71,0xb2,0x5e,0x94,0xf,0x54, + 0xa5,0xec,0xd5,0x83,0xd9,0xe0,0x9c,0x4,0xe5,0x39,0xfe,0x6,0xf8,0x24,0xdb,0x2b, + 0x93,0xd,0x12,0x9e,0x18,0x5d,0x74,0x2f,0x59,0xb7,0x31,0x16,0xc5,0xbe,0x3b,0xd1, + 0xa,0xa9,0xd0,0x35,0x25,0xa,0x6c,0xf,0x4,0x7d,0x36,0x5a,0x57,0xea,0x79,0xb9, + 0xd9,0xdc,0x5e,0x80,0xc4,0x28,0x47,0x3c,0xbd,0x5d,0x73,0xd1,0x5,0xd9,0x26,0x72, + 0xf5,0x75,0xe,0x66,0xd,0x81,0x64,0x36,0x42,0x1a,0x6f,0x11,0x1f,0x82,0x95,0xe9, + 0x95,0xc2,0x57,0xd4,0xcf,0x1b,0x2b,0x8f,0x85,0x98,0xa8,0x69,0x6e,0xeb,0x1f,0x46, + 0x3a,0x73,0x90,0xd2,0xa2,0xfd,0x32,0x45,0xcb,0x37,0x36,0xa8,0xbc,0xdf,0x28,0xe, + 0xcb,0x74,0x89,0x27,0xa3,0x33,0xed,0xcf,0x5d,0x39,0xc1,0xbe,0xef,0xe4,0x99,0xd2, + 0xe8,0x3a,0xa1,0x3c,0x19,0xac,0xc5,0xf,0xfd,0xf7,0xeb,0x7f,0xbd,0x6f,0xae,0xca, + 0x38,0x4d,0xc7,0xd6,0x1d,0x2d,0x55,0xac,0x5d,0x95,0x2,0x91,0x40,0xa,0x37,0x72, + 0x98,0xb4,0x55,0x29,0xa2,0x1b,0xd3,0xd8,0x74,0x94,0x41,0xd2,0x3b,0xc7,0x79,0x21, + 0xeb,0x3,0xa4,0x85,0x4d,0xbd,0x46,0x48,0x63,0x63,0x0,0x9f,0x9f,0xb6,0xd0,0xe8, + 0xb3,0x76,0xa7,0x67,0x5f,0xc9,0x64,0x7,0x24,0x8b,0x6b,0x72,0xb7,0xa0,0x4e,0x3, + 0x8a,0x66,0x68,0x5d,0x89,0x8e,0x7f,0x36,0x48,0x71,0xf4,0x3b,0x3a,0xb6,0x5a,0x7b, + 0x49,0xf9,0xe7,0x69,0x2c,0xb8,0x31,0x2a,0x48,0x56,0x9e,0x14,0xb,0xa1,0x1,0x3e, + 0x40,0x15,0xb6,0xe7,0x11,0x1c,0x77,0x24,0x48,0x49,0x3d,0xcd,0x57,0x95,0x2a,0x89, + 0x72,0xaa,0x55,0x30,0x93,0xc6,0xfe,0x49,0x5c,0x91,0x2f,0x8f,0xba,0xea,0xce,0x5e, + 0xef,0xd2,0xf5,0x72,0x8,0x3,0x77,0x17,0x52,0x7d,0xb,0x42,0x88,0x4c,0xee,0xba, + 0xa5,0xaa,0x5f,0xca,0xfe,0x8b,0x15,0xd7,0xd5,0x37,0xbb,0x5a,0xe9,0x64,0x63,0x2, + 0xc2,0x76,0xa8,0x5e,0x5e,0x3b,0x4d,0xea,0x92,0x5c,0x2c,0x7b,0xbd,0xd4,0xe2,0xb2, + 0xcc,0xaf,0x6d,0xbe,0xa4,0xb0,0x8c,0xa9,0xa5,0x88,0x8c,0x24,0xa9,0xc4,0x85,0xc5, + 0x69,0x99,0x8c,0xc4,0xbc,0x6e,0x66,0x14,0x69,0x8a,0xb2,0xac,0xaa,0xaf,0xbc,0x2f, + 0x6,0xb2,0x3c,0xdc,0x91,0x43,0xe9,0xf0,0x26,0xb9,0x45,0xd4,0x19,0x58,0x4,0x66, + 0x89,0x93,0xdb,0x78,0xb5,0xd4,0x16,0x71,0xa4,0x8b,0xef,0x66,0x41,0xdc,0x79,0x7, + 0x97,0xfe,0xf4,0x96,0x1d,0x8,0x52,0xec,0x3f,0x9b,0xdd,0x3a,0xf6,0x88,0x47,0xc9, + 0x62,0x87,0xac,0x94,0x35,0xb0,0x10,0xa5,0x7e,0x47,0xcb,0xc3,0x63,0xf4,0x78,0x96, + 0x35,0x6f,0x35,0x34,0xb1,0xc5,0x55,0xf6,0x84,0x4a,0xa4,0x4b,0xcd,0x22,0x91,0x50, + 0x58,0x15,0x61,0xa9,0xa2,0x2,0x5,0x1b,0x95,0x95,0x5d,0xec,0xc9,0xce,0x83,0x24, + 0x36,0xdb,0xd0,0xc,0x84,0xad,0x2d,0x41,0xf2,0x3a,0xad,0x71,0xc6,0xc4,0x4f,0x33, + 0xac,0x4b,0x65,0x39,0x20,0xf9,0x19,0xe7,0x89,0x2e,0xd6,0xc2,0xac,0x14,0x15,0xb9, + 0x7c,0xe6,0xfd,0xb3,0x12,0x2b,0xc9,0x44,0x14,0x83,0x4c,0xa8,0xca,0x3f,0x77,0xc3, + 0xd7,0x78,0xf4,0xb7,0xe3,0x38,0x36,0x18,0xf5,0x21,0x24,0x53,0x21,0xdf,0x87,0x54, + 0xdd,0x1f,0xaf,0x44,0x72,0x91,0x68,0x70,0x99,0xa4,0x5f,0x1,0xc2,0x39,0x84,0xb4, + 0xa,0x65,0x46,0x17,0x5,0x5e,0xa4,0x40,0xae,0xca,0x1,0x4b,0x67,0x8a,0x3f,0x12, + 0x98,0x38,0xb8,0x98,0x10,0x36,0xf,0xd7,0xa3,0x0,0x1a,0x2a,0x2a,0x5a,0x96,0x8f, + 0x69,0x8c,0xdc,0xed,0x74,0x84,0xb2,0x7a,0x50,0x13,0x4d,0x19,0x5c,0x64,0x9a,0x64, + 0x5d,0x79,0xc5,0x88,0xb5,0x10,0x73,0x70,0xa3,0x96,0xc2,0xa1,0x54,0xf9,0x7c,0x91, + 0xe5,0xcc,0x6a,0x37,0xdd,0x63,0x63,0x77,0x6c,0x42,0x91,0xfd,0xe3,0xf5,0x5a,0x8c, + 0xc7,0xe2,0xbd,0xd3,0xa7,0x44,0xa4,0x13,0x7f,0x47,0xc3,0x87,0x2e,0x9a,0x97,0x59, + 0xd,0x1b,0x73,0x7e,0x48,0xa,0x6e,0xdf,0x20,0xd1,0x67,0x8a,0x92,0x8d,0x70,0x5a, + 0xe2,0xa9,0x88,0xef,0x69,0x95,0x11,0x82,0xa1,0x1c,0x21,0xdb,0x4b,0xdf,0x1c,0x85, + 0xe6,0x2,0xa3,0x7,0x25,0xda,0x9,0x69,0x1e,0x4c,0x41,0x9d,0xb4,0x6a,0xfd,0x4e, + 0x38,0x8e,0xae,0xf2,0x7b,0xb6,0x2a,0x6e,0xda,0xcc,0xf9,0x58,0x97,0x84,0x33,0xc8, + 0x23,0xaf,0x6c,0x99,0xdb,0xf2,0x16,0x17,0xb,0x60,0x9,0x68,0xd8,0xe0,0x6,0x6e, + 0x8c,0x6d,0xc8,0x6a,0x67,0x86,0x4f,0x36,0xc8,0x90,0x40,0x83,0x3d,0xa5,0xfb,0xc6, + 0x46,0x75,0xf4,0xcb,0x0,0x85,0x45,0xf0,0x88,0x72,0x39,0xdb,0x77,0xd5,0x36,0x46, + 0x50,0x30,0x88,0x88,0xfa,0x74,0x60,0xdf,0x95,0x55,0x14,0xb1,0x92,0xe1,0xbe,0x99, + 0xe2,0xc9,0x9d,0xb6,0x81,0x6a,0xa2,0xc3,0x52,0xb,0xe4,0xb,0x95,0x5e,0xcb,0xfb, + 0xe9,0xad,0xae,0x2b,0x7d,0x7b,0xa8,0x23,0x32,0x9a,0x1a,0x70,0x72,0x56,0x7c,0x1d, + 0x70,0xa6,0x1,0xb2,0x62,0xda,0xf9,0xf7,0xc,0xbe,0xe6,0x62,0xa5,0xbe,0x5f,0x55, + 0x10,0x56,0xa0,0x14,0xbc,0x4a,0xc1,0xc6,0x3f,0xc3,0xd2,0x47,0x68,0x2a,0xec,0xc0, + 0xc,0x3b,0x89,0x1d,0x70,0x47,0x9e,0x39,0x6d,0xed,0xeb,0x53,0xcf,0x46,0xab,0xb8, + 0xac,0x7e,0x4e,0x81,0x10,0x25,0xd1,0x4c,0xca,0x34,0x49,0x53,0x97,0x58,0x38,0xb6, + 0x69,0x82,0x96,0xd3,0x65,0x1a,0xc5,0x70,0x3b,0x60,0x97,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x57,0x4e,0xdc,0x9e,0x16,0x8f,0x7b,0x71,0x6,0x64,0x30,0x7,0x36, + 0xa8,0x98,0xe5,0xf3,0xe3,0x9f,0xbd,0xd2,0x88,0x48,0xca,0x8e,0x38,0xd9,0x39,0x68, + 0x32,0x61,0x67,0x54,0x9,0x68,0xea,0x8b,0x34,0xd8,0xa2,0x3c,0x63,0x6d,0xd8,0x93, + 0x6f,0x2b,0x5b,0x99,0xd0,0x90,0xbe,0xb4,0xa,0xd1,0x2b,0x5a,0x21,0xac,0xb4,0xb1, + 0xb2,0x25,0x33,0x7b,0xd7,0xea,0x50,0xc8,0x7f,0xbe,0x6a,0x16,0xa0,0x96,0xe7,0x31, + 0xe9,0x5d,0x52,0x71,0x17,0x27,0x93,0x6c,0xaf,0xc1,0x52,0xf,0x1f,0x97,0x72,0x5b, + 0x7,0x20,0x4b,0xa4,0xed,0xd8,0xd,0xf7,0x96,0xef,0x15,0x2e,0xce,0x21,0xeb,0xe8, + 0x1c,0x84,0xe6,0xc6,0xc6,0x5a,0x6d,0x4b,0xdf,0x95,0xb4,0x22,0xf4,0xbc,0x29,0x22, + 0x5c,0x65,0x29,0xb0,0x4b,0x6f,0xbd,0x69,0x50,0x96,0x2d,0x57,0x7,0x81,0xc9,0x0, + 0x42,0x6d,0xe7,0x55,0xa1,0xad,0x28,0xe7,0xe,0xdd,0x5e,0xef,0x96,0x5f,0x7e,0xea, + 0x26,0xbc,0x53,0x2e,0xca,0x1d,0xb4,0xfa,0x33,0x59,0x47,0x38,0xfb,0x2f,0x8d,0xc, + 0xc0,0x43,0x75,0xed,0xa7,0x3,0x91,0x66,0x28,0xe2,0x6a,0x47,0x17,0x5b,0xa1,0xda, + 0x77,0x26,0xe0,0x1,0xf4,0x5f,0xe8,0x65,0xb8,0x8c,0x44,0x7c,0x53,0x76,0xc3,0xf9, + 0x44,0x10,0x1b,0x4,0x72,0xee,0xe0,0xbb,0x92,0x40,0xb8,0x65,0x4c,0x6e,0x16,0x9, + 0x41,0x6a,0x3a,0x3c,0xd6,0x39,0x42,0xea,0xcc,0x34,0x75,0xe9,0x4d,0x16,0x39,0x74, + 0xdd,0xd5,0x4e,0xc7,0xc2,0x18,0x8f,0x17,0xf7,0xc2,0x2f,0x49,0x3,0x2a,0xa8,0xb6, + 0x2a,0x3e,0x23,0x82,0x5f,0x79,0x6,0x2a,0x10,0xbb,0x24,0x21,0xf9,0x87,0xd8,0x48, + 0x3f,0x21,0x1a,0x97,0xfb,0x9a,0x5f,0x99,0xbb,0x2f,0x4f,0xae,0x93,0x6c,0x9,0xa0, + 0x57,0xdc,0x8a,0xde,0xee,0x93,0x1d,0x8f,0x7b,0x4c,0x90,0xa2,0x8a,0x5b,0x5c,0x5a, + 0xd3,0x32,0x66,0x83,0xb0,0x36,0x83,0xa2,0xa3,0xc2,0xde,0x23,0x11,0xb8,0x91,0x89, + 0x40,0x29,0x11,0xa8,0x6c,0xeb,0xd3,0xf3,0x96,0x15,0x7b,0x79,0x54,0xbb,0xee,0x61, + 0x25,0x53,0x3d,0xf6,0x4c,0x2d,0x96,0x35,0x96,0x2e,0xaa,0xa7,0xec,0x9d,0xf,0x7b, + 0x5f,0xfc,0x88,0x49,0x45,0x39,0x53,0x4c,0xc0,0xe4,0xbc,0x32,0xe6,0x9e,0x5,0x2b, + 0xb2,0x23,0x43,0x56,0xd1,0x6b,0x99,0x9e,0x61,0xa1,0x60,0xe4,0xbb,0x13,0x6b,0xd3, + 0x17,0x6b,0x92,0xb6,0x8f,0xf2,0xa6,0xb2,0x9d,0xd6,0x4e,0x87,0xa5,0xf2,0x2a,0x85, + 0x68,0x8c,0x28,0xeb,0xf3,0xaa,0x1d,0xda,0xca,0xa5,0x20,0x81,0xd5,0xbe,0x2,0x9c, + 0xcf,0xbb,0x2e,0x1e,0x19,0xe5,0x79,0xa5,0x4a,0x54,0x48,0x9d,0x55,0xb1,0xa5,0xc1, + 0x75,0xb5,0x69,0x8a,0xe1,0x6e,0xe7,0x27,0xad,0x9a,0x63,0x9e,0xd3,0xde,0xb6,0x90, + 0x19,0xb1,0x4d,0xc2,0xeb,0xfe,0xed,0x85,0xc0,0xae,0x4f,0x37,0x80,0x2,0x79,0x85, + 0xa1,0x12,0xca,0x75,0x80,0xa3,0x77,0x4b,0x81,0x90,0x27,0x82,0x20,0xf3,0xbe,0x69, + 0x24,0x14,0x5,0x98,0xa5,0x41,0x1b,0x81,0xae,0xe2,0x59,0xe2,0x99,0x5,0xc7,0x4d, + 0xdb,0x56,0xd3,0x55,0x2e,0xf0,0x2c,0x6a,0x86,0x20,0x13,0x39,0x29,0xd,0x20,0xbb, + 0xb3,0xe2,0x61,0x48,0xab,0x57,0x73,0x39,0x28,0x96,0x46,0x80,0xf5,0x40,0xaa,0xc2, + 0x39,0xb8,0x89,0x2f,0x90,0x6b,0x41,0x95,0xec,0x91,0x93,0x82,0xd7,0x5d,0x2f,0x79, + 0x6e,0x98,0xc7,0xdf,0x8d,0x4b,0xf8,0x70,0xf2,0x74,0xc5,0xf6,0x29,0xba,0x48,0xe9, + 0xb3,0x22,0x74,0x51,0x7e,0x12,0xa5,0x4a,0x37,0xba,0x2c,0xae,0x26,0xea,0x91,0x26, + 0x5c,0x6d,0xfa,0xe8,0x32,0x14,0x11,0x66,0xf,0x59,0x3b,0x93,0x5a,0xe5,0x48,0xd9, + 0x1f,0xb7,0xf2,0x5d,0xc4,0x5f,0x43,0x97,0x84,0xac,0x32,0x7a,0xc6,0x46,0xa8,0x9, + 0x8d,0xc2,0xa5,0xa4,0xa4,0xa5,0x0,0x9a,0x8d,0xfd,0x56,0xea,0x36,0x90,0x4,0x57, + 0xa9,0xf8,0x90,0x75,0x8f,0x8f,0xd,0x3b,0x4e,0x56,0x10,0xd7,0x82,0x67,0xbd,0x38, + 0x90,0x83,0xbf,0x18,0x81,0x4a,0x9d,0xe,0xed,0x57,0x94,0x7e,0x5e,0x8d,0x3b,0x4d, + 0x52,0x2d,0xfb,0xe8,0x36,0xa,0xd,0x5d,0xaa,0x5f,0x5d,0xb5,0x16,0x2a,0x8b,0x75, + 0x3,0x79,0x41,0x59,0x4e,0x8f,0xf5,0xa,0xd8,0x10,0x35,0x61,0xe3,0x72,0xd0,0xae, + 0x64,0x31,0x4a,0x18,0xb6,0xb6,0x5e,0x46,0xe5,0xc3,0x4f,0xec,0x92,0x79,0x51,0xa1, + 0x8e,0x31,0xb9,0x60,0x48,0x48,0xf3,0x28,0xc2,0xd8,0x10,0xd1,0xa5,0x5e,0xc,0x95, + 0xb,0x1d,0x6f,0x73,0xfc,0xa7,0xe0,0x3f,0xa7,0xb0,0xc,0x71,0xa9,0x48,0xef,0x17, + 0xad,0x3a,0x74,0x9,0x52,0xda,0x3f,0x89,0x90,0xad,0x60,0x92,0x85,0x56,0xc7,0xdd, + 0xd3,0x76,0x78,0x33,0x5c,0x61,0x9f,0x7a,0xb,0x52,0x5f,0x83,0xf6,0x18,0x59,0x3d, + 0xd5,0x59,0xb7,0xc2,0x5a,0x92,0xcf,0x89,0x13,0x4c,0x40,0x98,0xbc,0x33,0x95,0xc4, + 0x9f,0xca,0x71,0xe6,0x94,0xe6,0x87,0xd4,0x41,0x6a,0xc3,0xa6,0x58,0xb3,0xbe,0x53, + 0x1b,0xe4,0xf6,0xb2,0xd1,0xd4,0x74,0xa8,0xa7,0x2d,0x10,0x3d,0x3f,0xd4,0x5a,0xc3, + 0xcf,0x25,0x37,0x18,0x30,0x5f,0x79,0xd5,0x85,0x54,0xd1,0x91,0x4a,0x15,0x88,0x65, + 0x71,0xa6,0x6b,0x71,0xd2,0xfb,0x1e,0x28,0x6a,0x24,0x41,0x9d,0x2c,0xe7,0x18,0x58, + 0xc4,0xb8,0x8e,0xef,0xd3,0x4,0xa3,0xf3,0x8,0x8d,0x9e,0x5b,0x4a,0xdd,0xe3,0x11, + 0xb9,0xbd,0x5f,0xa4,0x8f,0xd4,0xbc,0xfa,0x94,0xf5,0x68,0xec,0x25,0x69,0x30,0x89, + 0x1a,0xb5,0x7c,0x26,0xa4,0xb4,0x77,0xd,0xbd,0x99,0xe,0x92,0xb0,0x73,0xc3,0x1a, + 0x3a,0x6d,0x94,0xeb,0x33,0xa7,0x6b,0x77,0x54,0x84,0x94,0xa0,0xc1,0x4,0xaa,0xbd, + 0x68,0x23,0x52,0x5c,0xf6,0x38,0x58,0x2a,0xed,0x7d,0x1f,0xa2,0xd8,0x45,0x71,0xb6, + 0x43,0x47,0x4,0xc9,0x3a,0xa1,0xc8,0xbe,0xd9,0xae,0x9b,0x3a,0x5c,0xa9,0xf1,0x60, + 0x5b,0x17,0x53,0xaa,0x4a,0xaa,0xda,0x9d,0x1b,0x4f,0x68,0x9,0x86,0xa1,0xb8,0xc2, + 0x6d,0xd7,0x6e,0xc1,0x38,0x22,0x55,0x2d,0x75,0x3e,0xa3,0xe,0x47,0xa0,0xbd,0x57, + 0x82,0xcd,0x24,0x50,0x42,0xb1,0xf4,0xc8,0x22,0x1e,0x4b,0x7c,0xa7,0x3a,0x7e,0xaa, + 0x87,0x7f,0x2b,0xda,0x2f,0xa8,0x50,0x78,0x18,0x61,0x3c,0xf7,0xed,0x53,0x36,0x26, + 0x96,0xe0,0xdd,0xd6,0x6,0x73,0x9f,0x33,0xbd,0x55,0x45,0x36,0x69,0x5f,0xf9,0xeb, + 0xd6,0x65,0xe4,0xb8,0x16,0x12,0x79,0x78,0x44,0xd9,0xcd,0xc8,0x7d,0xaf,0xad,0xc6, + 0x3b,0xb2,0xc2,0xcc,0x26,0x3a,0x29,0x38,0x2b,0x55,0xbc,0x20,0xa,0x9a,0x16,0xb7, + 0x67,0xcb,0xbb,0x13,0x9a,0x26,0x68,0x56,0xcb,0x85,0x76,0x21,0x92,0xb7,0x82,0x15, + 0xba,0x54,0xc1,0x39,0x75,0x6c,0xbb,0xdb,0xd3,0xbc,0x43,0x63,0x65,0x37,0x15,0x7b, + 0x14,0xe1,0x56,0x12,0x8,0x53,0x0,0x69,0xda,0xf3,0xf6,0x32,0x45,0xa8,0xa3,0x5f, + 0x4e,0x86,0x43,0x32,0x33,0x91,0xb0,0x8f,0x9e,0xab,0x4e,0x8a,0x64,0x2e,0xa,0x12, + 0x7e,0x98,0xd0,0xb1,0xb5,0x50,0xd2,0xcd,0xc3,0x46,0xb2,0x52,0x5,0x92,0x8b,0x23, + 0xdd,0xa3,0xb0,0x5f,0xf4,0x36,0x75,0x5a,0xa0,0x7b,0xf5,0x1,0x7b,0xce,0x2c,0x91, + 0x25,0x3a,0x98,0x46,0xe7,0x26,0xa4,0x6b,0x9c,0xbf,0xbd,0x45,0x87,0xab,0xd0,0x2b, + 0xa2,0xbc,0xc9,0x1a,0x9e,0x81,0xb2,0x75,0xcd,0x54,0xaf,0xc4,0xa5,0x5f,0xa,0x10, + 0x94,0xd5,0xab,0x1a,0xd4,0x3c,0x4d,0x16,0x91,0x9d,0x2c,0x29,0x6e,0x82,0xde,0x4c, + 0x84,0xe3,0x3,0x7c,0xee,0x6e,0x84,0x19,0xc6,0xcf,0xb8,0x65,0x47,0x5f,0xcb,0xe9, + 0x47,0xfb,0x45,0x5f,0x1b,0x8d,0x84,0x16,0x2a,0xc,0x17,0x7f,0x95,0x3b,0x2,0x2d, + 0x3b,0x7a,0xa5,0x55,0x2e,0xd7,0xb0,0x1a,0xc1,0x4a,0xe,0xa2,0x29,0xcf,0x24,0x65, + 0x7f,0xbb,0x3e,0x44,0x13,0xb5,0x31,0xe0,0x3a,0xcc,0x0,0x91,0x96,0x5e,0xf3,0xcf, + 0xa3,0x82,0x62,0xe3,0x27,0xdc,0xa5,0x14,0x88,0xa5,0xd1,0xe2,0xf7,0x39,0x2d,0xa5, + 0x58,0x5c,0x9e,0xce,0x77,0xa5,0xa7,0xad,0x6a,0xa6,0xdb,0xfa,0x99,0x4a,0xc9,0x91, + 0xdf,0x57,0xe5,0xcc,0xdf,0x73,0x28,0xad,0xed,0x71,0x91,0x6f,0x8c,0x9e,0x44,0xb6, + 0x3b,0x66,0x3a,0x3c,0xf7,0xf9,0x68,0xa3,0xa3,0x97,0x65,0xc7,0xb5,0x8c,0xdc,0x96, + 0x8e,0x8c,0xc2,0x60,0x94,0x53,0x42,0x87,0x70,0x2e,0x58,0xd8,0x4a,0x96,0x37,0xa5, + 0xf3,0x9e,0x2a,0xc3,0x32,0x22,0xa9,0x82,0x17,0xf0,0xb,0x5a,0x26,0x9c,0x35,0x3a, + 0x52,0x7c,0xfc,0xc7,0xf9,0x63,0x79,0x8f,0x12,0x40,0xc1,0x9,0xcd,0x10,0xec,0x41, + 0x67,0xb2,0x3e,0x60,0x43,0x60,0xb2,0x21,0xda,0xd3,0x82,0x24,0x5d,0xd6,0x31,0x4b, + 0x96,0x7a,0xdd,0x25,0x4a,0xbe,0x6c,0x5d,0x64,0xa4,0x1b,0xd6,0x5,0xe6,0xa8,0x53, + 0x6c,0x8a,0xb9,0x16,0x9a,0x8d,0xd0,0x1d,0x8f,0xeb,0xa3,0xa0,0x5a,0x74,0x2c,0x23, + 0xdf,0x54,0x9c,0xe5,0x68,0x53,0xa1,0x69,0x46,0x46,0x65,0x51,0xb0,0xa4,0x84,0x1d, + 0x4a,0xfc,0xb0,0xac,0xe3,0xe5,0x50,0xcb,0xe6,0xea,0x58,0xf3,0x3b,0x51,0x2f,0x6e, + 0x89,0x74,0x1e,0x45,0xe6,0xbc,0x4b,0x6b,0xcb,0x7b,0x91,0xf1,0xc2,0x5b,0xa2,0x32, + 0x5d,0x6c,0x2d,0xeb,0x48,0x54,0xcb,0xcf,0x21,0xbf,0x77,0x58,0x78,0x7,0x75,0x72, + 0xe1,0x5c,0xeb,0x65,0xa2,0x84,0xba,0xae,0x1,0x6d,0xd4,0x55,0x43,0xdf,0xc2,0x90, + 0x95,0xb2,0x5f,0x5c,0xb,0xc2,0xfc,0xa5,0xf4,0x65,0x6b,0xa3,0xc2,0x6,0xd0,0x25, + 0xcb,0xbb,0x8,0xde,0xfc,0xf0,0x76,0x1f,0x8b,0xd6,0xb8,0x8e,0x12,0x6b,0x2b,0x4, + 0xc4,0x5b,0x5d,0x2e,0xba,0x31,0x39,0x5a,0x9e,0x6f,0xc9,0x14,0x11,0x14,0xb6,0x3, + 0x4d,0x6b,0xd6,0xb3,0xb,0x4a,0xa9,0x33,0x15,0x3a,0x42,0x4f,0x9b,0x89,0x68,0x53, + 0xd2,0xa0,0x4a,0xce,0x27,0x88,0xf4,0x3c,0x91,0x44,0x14,0xa4,0xc4,0x79,0xa6,0x86, + 0xa9,0x8b,0x6c,0xd7,0x70,0x2c,0xad,0x0,0x42,0xa7,0x1b,0x6a,0x5d,0x29,0x15,0xf2, + 0x63,0xda,0xa4,0x2d,0xe2,0x39,0x8d,0xf5,0x53,0x29,0x5,0x91,0x1c,0x37,0x7c,0xc5, + 0xb5,0xe2,0xbe,0xd8,0xa2,0x5f,0x5a,0x4b,0x55,0x4c,0xf4,0x44,0xed,0xdf,0x67,0x91, + 0x6,0x9a,0xbf,0xf3,0x16,0x3e,0xb3,0x3d,0x17,0x5e,0x82,0x7b,0xf2,0xaa,0x63,0x36, + 0xe,0x51,0x18,0x84,0xb0,0x91,0x8d,0x7f,0x5d,0x65,0xf,0x59,0x33,0xfe,0x9b,0x15, + 0xed,0x9a,0xb,0x81,0xe2,0x18,0xe0,0x90,0x70,0xa,0xc5,0x2,0x68,0x52,0x5a,0xba, + 0x7c,0xa5,0xd1,0x93,0xfd,0xf3,0x43,0xb4,0x8,0xaf,0xb0,0x18,0x4c,0xab,0xec,0x97, + 0x3b,0x75,0x99,0xce,0x96,0x7,0x56,0x78,0xec,0xa1,0x7b,0x6a,0xff,0x2a,0xf4,0x41, + 0xc2,0xf1,0xe7,0xa2,0x85,0xd2,0x6c,0xb6,0xb9,0xd5,0xf4,0x82,0x66,0xe5,0xe0,0x7a, + 0x68,0x6a,0xd8,0xc3,0xa,0xe0,0x1d,0x54,0x61,0x87,0x6a,0xbd,0x64,0x80,0x13,0x4b, + 0x1b,0x45,0x21,0x1b,0x3f,0xe0,0x40,0xf0,0xad,0x63,0x23,0x5d,0xb,0x88,0x32,0xe, + 0xcc,0xda,0x1,0xaa,0xde,0x4b,0x9a,0x24,0x36,0xdb,0x96,0xda,0x1f,0x63,0xbb,0xdb, + 0x5a,0x26,0xd9,0x4d,0x42,0xed,0x3c,0x47,0x52,0xba,0x71,0x88,0x92,0x7d,0x4e,0x9d, + 0x5b,0xcf,0xaa,0xe9,0x2c,0x40,0xaa,0x21,0x7,0x19,0x25,0xb9,0x7a,0x48,0x84,0xe0, + 0xbb,0x49,0xab,0x91,0x3e,0xbb,0x55,0x71,0xbf,0x6e,0x60,0x37,0x5e,0xfc,0x45,0xc0, + 0xc7,0xe3,0x48,0x49,0x7c,0x74,0x56,0x35,0xf3,0x8,0x7e,0x29,0x3a,0x69,0x15,0xa5, + 0x7b,0x5,0x68,0x21,0x6c,0x92,0xd,0x37,0xbc,0xa7,0x7,0x25,0x3b,0x7b,0x2e,0x22, + 0x96,0xb1,0x8c,0xdb,0x49,0x59,0x3f,0xd1,0x24,0x7,0x26,0xe5,0xcf,0x21,0x69,0x59, + 0x50,0xde,0xcb,0x46,0xda,0x14,0x9a,0x2e,0xb8,0xf6,0x84,0xe,0x10,0x8,0x36,0x6d, + 0xa6,0x5b,0x7,0xac,0xb,0x54,0x89,0xac,0x66,0x2,0x33,0xcb,0x9e,0x5f,0x2e,0xd4, + 0x3a,0x21,0x62,0x2a,0x23,0x7d,0x7a,0x5e,0x20,0x7e,0x8e,0x3b,0x80,0x3f,0xb6,0xac, + 0x78,0x47,0xd6,0xca,0x24,0x3,0x8d,0x2e,0x13,0x95,0x9c,0xaa,0x90,0x87,0x3c,0xb9, + 0x38,0x28,0xa3,0xa7,0x1c,0xf,0xb6,0xae,0x93,0x28,0x41,0x64,0x5d,0xb7,0x49,0x54, + 0x85,0xd,0xd4,0x6f,0x4b,0x5a,0x23,0x4a,0xf2,0x8c,0x6f,0xad,0x91,0xb2,0xf8,0x2f, + 0x15,0xc7,0xdc,0xbd,0x67,0xc5,0xdb,0xc6,0xb3,0xbc,0x7e,0xbe,0xd8,0x8c,0x17,0x25, + 0xa4,0xb4,0x64,0x46,0x47,0xf6,0xbd,0x64,0x7e,0xfe,0x3e,0xf9,0x2f,0x92,0x4f,0x7e, + 0x41,0x85,0x6d,0x44,0x9a,0xe8,0x76,0x17,0x4c,0x2b,0x54,0x17,0xd8,0x15,0x8b,0xf6, + 0xfa,0xae,0xc7,0xef,0x5d,0xa7,0xf,0x1b,0x53,0x4e,0x29,0xeb,0x4f,0xe8,0xca,0x85, + 0xae,0xc9,0x6c,0xf5,0xbf,0x3f,0xbb,0xaa,0xae,0x9a,0xa4,0xab,0x79,0x7d,0x56,0xcf, + 0xbf,0xd9,0x38,0x29,0x91,0xe2,0x9c,0x67,0x5d,0xaa,0x7c,0x2c,0x3f,0xb6,0x32,0x4a, + 0x92,0xed,0x2a,0x45,0x58,0x2d,0x9b,0xc0,0x2d,0xb4,0x4b,0xd3,0xbc,0x57,0x61,0x51, + 0x80,0x83,0xf0,0x5d,0xf5,0x19,0x41,0x22,0x4b,0x6a,0xd9,0x86,0xb8,0x4d,0x37,0xc4, + 0xd,0x5e,0xe9,0x6b,0x1,0xe4,0x1b,0x19,0x6a,0xe9,0xe0,0x75,0xef,0xe8,0xbb,0xee, + 0xe5,0xd7,0x11,0x3f,0x55,0xec,0x15,0xc8,0x80,0xfc,0xb5,0x25,0x64,0xae,0x56,0x95, + 0xbd,0x6e,0x8,0x4d,0xea,0xf6,0x45,0x97,0xee,0xcc,0xf6,0xe4,0x29,0xf9,0x8c,0x3b, + 0xfd,0x96,0xa3,0xc8,0x9d,0x71,0xbe,0x74,0x4d,0xcd,0x62,0x11,0x53,0xa7,0x87,0x8d, + 0xbd,0x22,0xea,0xee,0x54,0x73,0x22,0x37,0x80,0x39,0x6a,0x6c,0x41,0xb2,0x96,0x56, + 0x3a,0x65,0x2d,0x16,0xae,0xad,0xe,0x80,0xbe,0xce,0x14,0xd2,0xae,0xfb,0x84,0x1c, + 0xfb,0xc5,0xfc,0x1c,0x31,0xbb,0x39,0x7a,0x94,0x8d,0x95,0x43,0x15,0xda,0x48,0xb2, + 0xf1,0x4,0x4,0x46,0x8b,0x12,0x3d,0x8a,0x33,0x10,0x10,0x26,0x71,0xa0,0x25,0x17, + 0xaf,0xba,0xa8,0x65,0xb7,0xf6,0xaa,0x2d,0xb1,0xe9,0x73,0xb7,0xd,0x9f,0x20,0x2d, + 0x64,0x2f,0x8e,0xa0,0x54,0xf5,0xf7,0x4b,0x1b,0x97,0x4c,0xad,0x40,0xf9,0x74,0x7d, + 0xc7,0x96,0x7b,0x9c,0x12,0x4c,0x36,0xf2,0x1c,0xb6,0x42,0x7f,0x64,0xaf,0xcb,0x1, + 0xcb,0x44,0xae,0x16,0xe8,0x4c,0x30,0x83,0x64,0x30,0x95,0x50,0xa,0x95,0x15,0xe9, + 0x3d,0x8d,0xb7,0x63,0x22,0x11,0xdd,0x6d,0x2b,0x85,0x81,0x96,0xa7,0xaf,0x15,0xea, + 0x60,0x4a,0x14,0xc8,0xe4,0x89,0x46,0xe2,0xb,0xad,0xbb,0xf6,0x96,0xc5,0x63,0x69, + 0x8f,0x8b,0x45,0xd,0x53,0xb9,0x1c,0x69,0x5,0xd5,0xb6,0x83,0xde,0x91,0x56,0x13, + 0xba,0x8a,0x2b,0xf7,0xae,0x44,0x56,0x7e,0x1,0xf6,0x94,0xcf,0x39,0xad,0x52,0x6b, + 0xb4,0x40,0xce,0x96,0xdf,0xf0,0xb3,0xc7,0x5d,0x82,0x3d,0x65,0x48,0xa3,0xf5,0xa5, + 0xfd,0x8c,0x5b,0x7e,0xf5,0x5,0x39,0xb2,0x92,0x34,0x3f,0x89,0x19,0x52,0xa7,0xb1, + 0xe5,0x68,0xe8,0xdb,0x1e,0x8e,0xd,0xf,0x84,0x2e,0x81,0x5d,0x71,0x97,0x21,0x83, + 0x8f,0xf6,0x68,0x2d,0x62,0x90,0x81,0x8d,0x22,0x4d,0x69,0x5a,0x54,0x47,0x42,0x45, + 0xbc,0x39,0xcf,0x50,0xfb,0x2c,0xe,0x71,0x50,0xab,0xc4,0x96,0x3b,0x6e,0xd9,0x27, + 0x52,0x2f,0xb9,0xe0,0x5,0x89,0xca,0x41,0x9b,0xf9,0xf7,0xa8,0xec,0xdb,0xc8,0xaf, + 0x55,0xaa,0x10,0x8e,0x74,0xed,0x52,0x3a,0xa9,0x5e,0xb3,0x9d,0xac,0x8,0x64,0x18, + 0x7a,0x41,0xf,0x42,0xe7,0x96,0xb7,0xc5,0xb8,0x45,0xdd,0xcb,0x8a,0x94,0x13,0xcd, + 0xa2,0xa5,0x34,0x4e,0xa4,0x51,0x68,0xd8,0xd5,0x5b,0x22,0xeb,0x68,0xcb,0x5f,0xc7, + 0x3e,0x84,0xe8,0x3e,0xab,0x4e,0x8a,0x30,0x4a,0x23,0x72,0xd9,0x8,0xa1,0x97,0x3c, + 0x65,0xa0,0x3c,0xf1,0xaa,0x42,0xdd,0x12,0x88,0x55,0xe2,0x42,0xe7,0x9a,0x97,0x27, + 0x1d,0xce,0xc5,0x5e,0x11,0x8d,0x32,0x23,0x4f,0x63,0xc2,0xa3,0x85,0x9a,0xb4,0x56, + 0xfa,0x9b,0x54,0xa5,0x42,0xf2,0x43,0x8a,0x37,0x6d,0x11,0x92,0x91,0xbc,0xa3,0x65, + 0xff,0xb,0x6c,0x78,0x2c,0x75,0xcf,0x82,0x56,0x97,0xbf,0x95,0x87,0xb,0x48,0xb6, + 0x16,0xe7,0x81,0x57,0xbb,0xd8,0xd2,0x3d,0x6a,0xe5,0x5e,0xfb,0xb3,0xb6,0x3d,0xe, + 0xce,0x85,0x12,0x24,0x63,0x8a,0x42,0xc3,0xa9,0xce,0x9f,0x4f,0xcc,0x5,0x2e,0x4c, + 0xcb,0xe5,0xd9,0xe5,0xf3,0xa7,0x5d,0x58,0xba,0x1f,0xa6,0x21,0x62,0x59,0xdf,0x14, + 0x68,0xac,0x7f,0x1e,0x79,0x13,0xba,0xa,0x6e,0xf3,0xe7,0xba,0x5,0xeb,0xd0,0xe4, + 0x76,0x88,0xf3,0x4c,0xa9,0xd0,0x6c,0x65,0x62,0xb1,0xa1,0x15,0xa9,0xd6,0xaa,0xc5, + 0xcb,0xae,0x44,0xed,0xca,0x72,0xa,0x6c,0xec,0x90,0x43,0x38,0x19,0x6b,0x97,0x8, + 0x60,0x29,0xee,0x83,0xa6,0xe5,0x2a,0xb0,0x77,0x8d,0x4,0xa5,0xa6,0xa7,0x28,0x93, + 0x8e,0xae,0xeb,0xbe,0x4c,0xcb,0xbe,0x3a,0x65,0x50,0x80,0x89,0x71,0x3c,0x36,0xaf, + 0x54,0xbc,0x3a,0xa9,0x42,0x50,0x31,0xe7,0x67,0x11,0xaf,0x32,0x9,0xb1,0x90,0xcb, + 0xf8,0xcc,0x40,0xd0,0x24,0xa8,0x5d,0x2d,0x18,0x5b,0x24,0xc3,0xfd,0xe7,0x5e,0x2a, + 0xda,0x44,0x16,0xe8,0x15,0x40,0xa2,0xe3,0xd,0x5b,0x98,0xff,0xec,0x36,0x2c,0xc9, + 0xeb,0xe4,0x82,0x5,0xcc,0xa0,0x7b,0x40,0x64,0x8b,0xee,0x9,0xda,0xbf,0x6b,0x99, + 0x4e,0x6,0xf8,0x89,0x68,0xa7,0x9f,0x93,0xbb,0xa0,0x89,0x3c,0x29,0x45,0x1f,0x84, + 0x7c,0x7f,0x90,0x6e,0x20,0x9,0x33,0xad,0x49,0x1a,0x69,0x6b,0xa4,0xce,0x4c,0x54, + 0x36,0x94,0xb1,0x28,0xb6,0xb0,0x49,0xf1,0x45,0xb6,0xb2,0x70,0xd6,0xad,0xec,0xf3, + 0x7d,0xad,0x52,0x11,0x66,0xa2,0x64,0xef,0xa2,0x86,0x15,0x6b,0x56,0xad,0x4b,0x8, + 0x43,0x20,0x1b,0xcf,0x12,0x1d,0x25,0x8b,0x3e,0x60,0x45,0x87,0xa6,0x1d,0xa4,0xe7, + 0x2e,0x3b,0xf8,0x1f,0x94,0xbb,0x4e,0x4a,0xcf,0xb6,0x25,0x22,0x91,0xe5,0xb2,0xca, + 0x3f,0x8a,0xb5,0xf2,0xab,0xd0,0xff,0x75,0x7d,0x91,0x41,0x46,0xac,0x13,0x90,0xb4, + 0xbf,0x85,0x8f,0xd3,0xd9,0x4a,0x96,0xf7,0x3a,0x1a,0x87,0x10,0xef,0xf,0x45,0x37, + 0x3e,0xbf,0x72,0x58,0xea,0xe7,0x88,0x97,0x36,0x96,0x2d,0x28,0x9e,0x87,0xba,0x42, + 0x0,0x72,0x22,0x56,0x46,0x81,0x22,0xf9,0xb6,0xa3,0x9b,0x35,0xeb,0x4a,0x74,0x4e, + 0x6b,0xda,0x93,0x48,0xe,0x0,0x58,0x1a,0xf4,0xe4,0xd3,0x8f,0x5a,0x35,0x3f,0x4f, + 0x48,0x21,0x29,0xf9,0x79,0x5b,0x64,0x9b,0xe6,0x7c,0xa0,0xcb,0x2a,0x8b,0x39,0x9b, + 0xe3,0xb1,0x37,0x29,0x7e,0x25,0x19,0xcc,0x30,0xbb,0xfc,0xe5,0x2f,0xf4,0xc0,0xa6, + 0x45,0x40,0xb3,0xe7,0xe7,0xa1,0x7b,0x1e,0x4e,0x17,0xea,0x71,0x3c,0x50,0x62,0x3a, + 0x6c,0x8b,0x91,0xdc,0xe5,0xd2,0x36,0xfc,0xf4,0xba,0x3d,0xe1,0x50,0xb7,0x63,0x25, + 0xd7,0xa5,0x8f,0xf,0x4b,0x2d,0x96,0xbb,0x14,0x95,0xb0,0x29,0x36,0xba,0xc4,0x91, + 0xc1,0x38,0x7b,0xf4,0xea,0xee,0x1e,0x48,0x2b,0x8b,0x6c,0x1d,0xd4,0xe4,0xa7,0xc7, + 0xca,0x96,0xf0,0xaf,0x76,0x6b,0x14,0xca,0xce,0x3,0x5d,0x6b,0xcb,0x2a,0x4e,0xe2, + 0x3c,0x71,0x29,0x29,0x4f,0xe9,0xe6,0x6d,0x31,0x89,0x54,0x95,0x7a,0xac,0xbb,0xf6, + 0x81,0xbe,0xe7,0x9e,0x9e,0xa7,0x66,0x9,0xed,0x69,0x57,0xaf,0x99,0xb5,0x9e,0x43, + 0x44,0x24,0x21,0x98,0x23,0x38,0xa4,0x14,0x12,0xfc,0x75,0xf4,0x4d,0xa7,0x3b,0x59, + 0xbe,0x8a,0xf0,0x1c,0x5b,0x71,0x8e,0xac,0xed,0x68,0x28,0x6f,0x32,0x28,0x25,0x52, + 0xb7,0xd5,0xe7,0xfb,0xce,0x23,0x7,0x64,0x68,0x16,0x9f,0xb1,0x32,0x7f,0xeb,0xac, + 0x93,0x2d,0x36,0xdd,0x5a,0x4,0xc8,0xd2,0xed,0x6b,0x1a,0x85,0xf6,0x74,0xbe,0x90, + 0x0,0x53,0x91,0x58,0xfc,0x5a,0x4,0xcb,0xaa,0x42,0xfc,0x90,0xe2,0x3f,0x27,0x21, + 0xed,0x60,0xb9,0xcf,0xf,0xa6,0xab,0x50,0x24,0xd0,0x7c,0x79,0x95,0xc9,0x59,0xba, + 0x71,0x16,0x68,0xe9,0x22,0xea,0x3,0xa6,0x6e,0xa9,0xa9,0x6c,0xff,0x54,0x74,0x31, + 0x39,0xcd,0x13,0x67,0xb2,0x78,0xcc,0x33,0x66,0xd3,0xce,0x6a,0x6b,0x5f,0x58,0xfc, + 0xdd,0xfe,0xe7,0xb6,0x5c,0x30,0x14,0xad,0x86,0xd6,0x2b,0x95,0x80,0x1,0xe2,0xc8, + 0xcd,0x95,0xda,0xb6,0xb5,0xaf,0xf,0xe,0x38,0x16,0xe1,0x9,0x57,0x6e,0xf5,0x6b, + 0x7,0xef,0x4e,0x45,0xf6,0xc4,0xa8,0xea,0x62,0xa3,0xc8,0xfb,0xc7,0x2c,0x5e,0xea, + 0x69,0xe2,0xa7,0xb1,0x23,0x4e,0x19,0xf6,0xc1,0x2c,0x47,0x92,0xf,0xa8,0x54,0x19, + 0x5f,0x15,0x11,0xb2,0x16,0x22,0xd9,0xa6,0xa6,0xca,0x5b,0xb7,0x2c,0x6a,0xc4,0xdf, + 0xdf,0x5b,0x9d,0xa7,0xef,0x55,0x23,0x64,0x64,0x4b,0x11,0xad,0x45,0x67,0x90,0x46, + 0x9f,0x58,0x5,0x3d,0xc4,0x3a,0xe8,0x58,0x45,0xd3,0x9d,0xb8,0xc,0x31,0xa1,0xc0, + 0xa6,0x80,0x2f,0x56,0x3e,0x15,0x0,0x53,0x84,0x8c,0x96,0x99,0x4c,0x45,0x44,0xcd, + 0x91,0x54,0x1f,0xf,0x6a,0x1a,0xc1,0x8a,0x6c,0xd0,0xa3,0xea,0x21,0x97,0x4,0x93, + 0xd1,0xd9,0x46,0x1d,0xdc,0x4,0x9b,0x8e,0xf0,0xea,0xc2,0x6d,0x92,0xa7,0xb7,0x5b, + 0x62,0x46,0xa6,0x64,0xb5,0xb5,0xdb,0xdd,0x48,0x5e,0xd4,0xa2,0x84,0x7,0xe8,0x70, + 0x6a,0x48,0xd9,0xce,0x8b,0xc8,0xa8,0x14,0xe6,0x9a,0xc4,0xb1,0xf9,0x22,0x15,0xfa, + 0xac,0xfd,0x1c,0x13,0x49,0xa3,0x71,0x9e,0xf2,0xa0,0x44,0x5f,0x4a,0x21,0xc3,0x81, + 0x19,0xf4,0x1b,0x5,0x92,0xa6,0xf5,0x92,0xa4,0x55,0x87,0x6c,0xc,0xcf,0x54,0xf7, + 0xa5,0xe6,0xd5,0x30,0x2b,0xd6,0x4a,0x44,0xe2,0x50,0x2a,0x96,0xd2,0xba,0x87,0x95, + 0xd1,0xba,0x58,0x20,0xad,0x8,0xef,0xfc,0x4e,0xf2,0x6b,0xd3,0xf2,0xcf,0x6d,0x71, + 0xdd,0x68,0x4b,0xbb,0xf7,0x14,0xce,0x27,0x4c,0xa8,0x24,0x3f,0x79,0xd1,0x6f,0xc0, + 0x27,0x2b,0xeb,0xd8,0x1b,0xb,0xec,0x54,0x32,0x52,0xd9,0xa7,0x92,0x9a,0xf5,0xaa, + 0x29,0x2,0x97,0xc1,0x94,0xfb,0x9d,0x1c,0x4c,0xfe,0xdc,0x1e,0xa6,0x6f,0x23,0x78, + 0x40,0xb4,0xd2,0x3c,0x2,0x57,0xd9,0x84,0xe5,0x95,0xe9,0x6a,0x42,0x9c,0xd6,0x69, + 0xc3,0x46,0xb1,0xce,0xdf,0xb3,0x88,0xac,0xa8,0xe5,0xd2,0xd4,0x8a,0x58,0x7c,0xaa, + 0xca,0xc6,0xe,0x19,0x9b,0x15,0x76,0x55,0xcb,0xfa,0xf8,0x1a,0xb9,0x4e,0x45,0x11, + 0x7e,0x10,0x97,0xb8,0x74,0xcd,0x9a,0x78,0xd9,0xfc,0xc3,0xe5,0x57,0xb0,0xcf,0xbd, + 0x89,0x24,0x48,0xc8,0xda,0x78,0xb9,0x58,0x29,0xed,0xe5,0xe9,0x43,0x17,0x3a,0x3c, + 0xa8,0x90,0x80,0xac,0x17,0xf6,0xfa,0x53,0xfa,0xbc,0x9,0x3,0xb2,0xed,0x80,0xc7, + 0xbf,0xd3,0x4e,0x11,0x21,0x14,0x1b,0x7b,0xab,0xd2,0x59,0x61,0xb3,0x2f,0xcf,0x5d, + 0xfb,0x42,0xe9,0x4b,0x23,0x30,0xa4,0x3,0xad,0xdb,0x88,0x50,0x9,0x6e,0x41,0x15, + 0x4d,0xbd,0xb4,0x72,0xa7,0x55,0xc4,0x4e,0x55,0x1c,0xc2,0xea,0xe3,0x74,0x88,0xd6, + 0xa9,0x89,0xd2,0x67,0x3e,0x3b,0x55,0x94,0x54,0x7a,0x91,0xc5,0x86,0xc7,0xaa,0xf6, + 0x0,0x43,0x6e,0x6b,0x1e,0x12,0x39,0x6b,0xb9,0x94,0xf6,0xed,0x6f,0xb1,0x69,0x51, + 0x64,0xd7,0x1,0x96,0x9f,0xad,0x2c,0x4e,0xf,0xf6,0x82,0xb3,0x5b,0x66,0x7d,0x16, + 0xd7,0x98,0x58,0x94,0x45,0x7,0x92,0x60,0x33,0x6c,0x97,0x34,0xca,0x48,0x60,0xa6, + 0xf4,0xd,0xb5,0x6a,0x17,0xcd,0xef,0x57,0x75,0x58,0xf4,0xe5,0x42,0xc9,0x13,0x2d, + 0x2d,0xef,0x3e,0x4f,0xcb,0x7c,0xfc,0x2d,0x48,0x6a,0xfd,0xbc,0x8a,0x40,0xfa,0xbe, + 0xd5,0x47,0x93,0x9f,0x3f,0xfa,0x67,0x2a,0x5a,0x7a,0x1e,0x69,0x7f,0xbe,0x58,0x19, + 0xa9,0x9b,0xd5,0x32,0x5d,0xb1,0xcf,0x3f,0x46,0xc9,0xf9,0xf9,0xdd,0xf4,0x5,0x17, + 0x56,0x2,0x8,0xf8,0x64,0x1a,0x8,0x21,0x2a,0xa3,0x29,0xae,0x8b,0x84,0x62,0x53, + 0x3c,0xb9,0x5a,0xc6,0x4c,0x5f,0xa1,0x89,0x8c,0x82,0x14,0xc9,0x5a,0x8c,0xc3,0x9a, + 0xe9,0x99,0xaa,0xb2,0xe8,0x39,0xb6,0x34,0x47,0x81,0x8c,0xc5,0xfa,0x73,0xe7,0xe9, + 0x18,0xef,0x80,0x49,0x47,0xe1,0x2a,0xfb,0x2d,0x97,0x4d,0x7a,0xf7,0x75,0x13,0xd7, + 0xbc,0xee,0xeb,0xd7,0xa2,0xde,0x75,0x6,0x1b,0x82,0x4e,0xc7,0xdf,0x5b,0xc4,0x62, + 0x13,0x17,0x5b,0x76,0xd6,0xd,0x2c,0xfe,0x2d,0x2d,0xc3,0xf,0xdd,0xd0,0x85,0x91, + 0xc5,0x19,0xec,0xbe,0xc8,0x15,0x1a,0x4a,0xb5,0x96,0xf2,0x91,0xe8,0x39,0x93,0x14, + 0x26,0xa3,0x1b,0xa7,0x7b,0x71,0xa6,0xab,0x16,0x34,0x3a,0x29,0xf3,0x92,0xc3,0xa5, + 0x2d,0x67,0xd6,0xa1,0x1c,0xb4,0xcd,0x3,0x4d,0xb7,0x90,0x9e,0x5c,0x1,0x16,0x7, + 0x38,0x5f,0x4a,0xcb,0xde,0x70,0x41,0x9a,0x6e,0x2d,0xf8,0xc9,0xf7,0x37,0x85,0x3e, + 0xf5,0x90,0x64,0x55,0x26,0x38,0xad,0x86,0xd8,0xb6,0x59,0xa9,0x5a,0xa3,0x5d,0x65, + 0xff,0x21,0x48,0x55,0x7e,0x95,0x6d,0xe4,0xd0,0x1a,0x2,0x33,0x2e,0xde,0x6d,0x1a, + 0xf6,0xf1,0xc2,0xbe,0xd5,0x3d,0x76,0x4d,0x56,0xd3,0x65,0xc3,0xa3,0x1b,0x14,0xb1, + 0x88,0x8c,0x45,0x70,0x9e,0x79,0x35,0x62,0xc2,0xbb,0x12,0xd9,0x87,0x2d,0xd1,0x5e, + 0x15,0x9d,0xcb,0xa,0x80,0x9,0x70,0x8a,0x16,0x5d,0x44,0xcc,0xcd,0xd6,0xc3,0x2a, + 0xa7,0x78,0xd5,0xfe,0x2f,0xd9,0x38,0x34,0xf6,0xaf,0xa0,0x13,0x9,0x64,0x38,0x91, + 0xc,0xa3,0x98,0xcf,0x57,0xf1,0x82,0xab,0x6e,0x2a,0xcd,0xeb,0xa5,0x59,0xe0,0x77, + 0x45,0x85,0xbc,0x7a,0xb6,0x63,0x4f,0x4e,0xcf,0x74,0xd3,0x4,0x77,0xd9,0x46,0x37, + 0xd6,0xbf,0xb7,0x7e,0xae,0x4b,0x8f,0xc6,0x97,0x14,0xf2,0x8a,0x20,0x8d,0x6e,0x4d, + 0xc0,0x69,0xf1,0xb5,0x44,0x89,0x72,0xb6,0x83,0xae,0x5f,0x17,0x52,0x31,0x96,0x31, + 0x4c,0x96,0x5e,0x18,0x23,0x48,0xcf,0xcd,0x4e,0x99,0xdb,0x86,0xd7,0x65,0x81,0x55, + 0x77,0x12,0x79,0x11,0x60,0xa5,0x41,0xf5,0x6,0xd1,0x8b,0xce,0x17,0x25,0x1,0xa9, + 0xb2,0xe,0xc7,0x2e,0xd4,0x12,0x98,0xb2,0xee,0xe4,0xdb,0x6,0x41,0x40,0x97,0x45, + 0x56,0xba,0xc4,0x73,0xa0,0x44,0xba,0x8,0xe3,0xb9,0x2d,0xa1,0x32,0x34,0x9e,0xb6, + 0xf7,0x4f,0x36,0xf9,0x1,0xfb,0x54,0xff,0x79,0xd7,0x97,0x77,0xb6,0xb9,0xb,0x16, + 0x95,0xc5,0x5e,0xa5,0xde,0x21,0x13,0x43,0xa3,0xa0,0x60,0x3a,0x89,0xf7,0xfc,0x27, + 0xee,0xd3,0xba,0xc2,0x90,0x60,0xbb,0xe4,0x46,0xfc,0x2d,0xa4,0x3c,0xaf,0xda,0xb6, + 0x35,0xe,0xb2,0x15,0xd3,0xb2,0xa7,0x1,0x4a,0x79,0x1,0x28,0xeb,0xb0,0x6c,0xf9, + 0xc1,0xc6,0x8e,0x88,0x27,0x44,0xeb,0xaf,0xf7,0xa8,0xd0,0xf5,0x73,0xd6,0x1c,0xa9, + 0xd0,0x5,0x4d,0x31,0xd9,0xae,0x9c,0x85,0xb3,0xeb,0x1c,0x78,0x6d,0x0,0xf3,0x24, + 0x89,0x84,0x83,0x64,0x7,0xcd,0xac,0x7c,0x22,0xbe,0x69,0xe,0x7,0xb,0x5d,0x56, + 0x76,0x15,0xe5,0x64,0xc1,0xf9,0x1c,0xbf,0xf6,0x17,0x3f,0xff,0x81,0x26,0x31,0x9, + 0x12,0x77,0x3c,0xef,0x5a,0xb2,0x46,0x43,0xab,0x30,0x6e,0xd3,0xf2,0x51,0x52,0x70, + 0x58,0x40,0x6,0x59,0x11,0x81,0x89,0x6b,0xbe,0xad,0x72,0xae,0x87,0xf9,0x2f,0xdb, + 0xc9,0xcb,0x3e,0xbc,0xe8,0x5e,0xe,0x6a,0x7e,0x44,0x45,0xb5,0x98,0xc0,0x74,0xd9, + 0xa,0xaf,0x7f,0xe0,0x1e,0x1f,0xb9,0xbf,0x90,0x34,0xc6,0x99,0x1f,0xbe,0x32,0xfe, + 0x4f,0xd6,0x51,0x30,0xf6,0x7c,0xd9,0xba,0xe7,0x9f,0xed,0x7b,0xbd,0x50,0x56,0xaa, + 0x48,0xac,0x79,0x1b,0xc1,0x63,0xe9,0xf0,0x72,0x8e,0xf6,0x3a,0xb7,0x59,0x7d,0xeb, + 0x22,0x5b,0x9,0x67,0x9b,0xc1,0x60,0xb2,0xa7,0x75,0xa9,0x19,0xf4,0x1b,0x44,0xa5, + 0x2d,0xc1,0x26,0x90,0x9,0xe4,0xca,0xc2,0xb1,0xff,0xb7,0xb4,0xab,0xeb,0x95,0x24, + 0x4b,0x6a,0xe1,0x62,0x16,0xd,0xfb,0xff,0xff,0xd7,0x7d,0x42,0x48,0x20,0x21,0xa4, + 0x11,0xcb,0xd7,0x2,0x2b,0x16,0x78,0x6c,0xf3,0xd0,0x5d,0x99,0x11,0xb6,0xe3,0x64, + 0xb5,0x40,0x42,0xbb,0x3b,0xd3,0x7d,0x6f,0x55,0xe6,0x39,0xf1,0xe1,0x70,0xd8,0x3, + 0xe7,0x6e,0xbf,0x76,0x74,0x18,0x97,0x33,0x4c,0x14,0xa6,0x55,0x7a,0xe4,0xf0,0x72, + 0x97,0x97,0x40,0x19,0x3d,0xcc,0xb5,0xa6,0x30,0x87,0x43,0xda,0xdb,0x2e,0xb3,0xd7, + 0x49,0x4e,0x86,0x46,0x30,0x33,0x36,0x78,0xd,0x9b,0x6b,0x55,0xd8,0x39,0x6f,0x4, + 0x2c,0xf7,0xc3,0x50,0xa5,0xfe,0xc7,0x28,0xcb,0xcc,0xf4,0x0,0xdf,0xd6,0x55,0x27, + 0x7a,0x31,0x2d,0x5a,0x61,0x88,0xa,0xa3,0x71,0xc,0xc,0x7b,0x99,0x1,0x36,0xd5, + 0x5c,0x28,0x47,0x29,0xe7,0x24,0x7e,0x6a,0x21,0x3a,0xb9,0x2f,0xc8,0xc2,0xf5,0x9f, + 0xd5,0x2d,0x62,0x21,0x9a,0x1c,0xba,0xd7,0x45,0x11,0xf2,0x59,0x1b,0xa2,0x33,0x5e, + 0x78,0x8d,0xfd,0x84,0x2e,0x50,0x91,0xb4,0x59,0x62,0x78,0xea,0x4,0x4d,0xd4,0x34, + 0xa9,0x1a,0xef,0x8,0x53,0xad,0x1d,0xda,0x88,0xf1,0xd6,0x17,0xb8,0x1a,0xb2,0xb0, + 0x2d,0x81,0x52,0x1e,0xa0,0x93,0x29,0x95,0x3f,0x66,0xeb,0xd2,0xe4,0xcc,0xdf,0xad, + 0x38,0xbc,0x38,0x20,0xa4,0x6c,0xc7,0xa4,0x35,0xc5,0x8a,0xa6,0xdb,0x75,0xd8,0xfc, + 0x42,0x46,0xeb,0x73,0x9d,0x5f,0x6e,0x9f,0x5a,0x86,0xa8,0x30,0x70,0x5,0x2e,0x2f, + 0xba,0x51,0x1c,0xa1,0xea,0xfb,0xc,0xfd,0x82,0x9c,0x5e,0x1c,0x6,0xe,0x13,0x16, + 0xf,0x33,0x85,0xf1,0x45,0x6e,0xdf,0xeb,0x7b,0x25,0xe3,0xf5,0x63,0x7d,0x8d,0x15, + 0xed,0x50,0xc7,0xf9,0xc5,0x80,0x48,0xbd,0x3c,0x48,0xd6,0x88,0x70,0xfe,0xac,0xa2, + 0x12,0xf5,0x1d,0xde,0x43,0x13,0x4e,0x89,0xc,0xe8,0xd9,0xe8,0x8e,0x19,0x2a,0x8d, + 0x11,0xa9,0x1d,0x70,0xb0,0x1f,0xad,0x7c,0x9,0xaf,0x79,0x89,0x2a,0xe3,0xb1,0x8b, + 0xd,0xa4,0x4e,0x33,0x98,0x64,0xf4,0x4e,0xba,0x89,0x70,0x70,0xcc,0x6b,0xd8,0xdc, + 0x86,0xe7,0x6e,0x39,0x51,0xe3,0xfd,0xc2,0xbc,0xed,0x33,0x1c,0xf5,0xd,0xea,0x43, + 0xae,0xc5,0xda,0x9c,0x11,0xd,0xc6,0x2f,0x9b,0x9d,0x5a,0x5,0xc2,0x4b,0x28,0xac, + 0x30,0x5c,0xac,0xd4,0x66,0x15,0x79,0x3d,0xad,0xa9,0xa7,0x8d,0xb9,0x6a,0x58,0xdb, + 0xd9,0xa1,0xd1,0x8d,0x91,0x2b,0x64,0xbf,0x2e,0xef,0x8b,0xbb,0x30,0xd6,0xd1,0x92, + 0x8f,0x9f,0xdf,0x6b,0x54,0x89,0x9f,0x70,0x77,0x87,0x14,0xb6,0xf3,0x7b,0xdb,0x80, + 0xb2,0x75,0x51,0xb7,0x3,0xe7,0x7c,0x36,0xaf,0x56,0xb0,0x2d,0x26,0x29,0x15,0x67, + 0xf4,0xc1,0xfe,0xb8,0x66,0x75,0xaf,0x9a,0x12,0xbd,0xab,0x29,0xd9,0xf1,0xcd,0x49, + 0xc9,0x3b,0xea,0x34,0xe,0x98,0x63,0xe,0x88,0xfd,0x70,0x3f,0xe7,0xed,0x4c,0xff, + 0xf8,0x67,0xdf,0x8c,0x43,0x30,0x27,0x92,0xae,0x80,0x48,0x11,0xfb,0x69,0x64,0xc8, + 0x1f,0x1a,0xe7,0x9d,0xb4,0xd9,0x45,0x46,0xde,0xeb,0x88,0xb4,0x6a,0x1c,0x93,0x70, + 0xba,0x22,0x48,0xf7,0x7e,0x39,0x44,0xb4,0x8a,0xc3,0x71,0xa5,0x43,0xf0,0x61,0x23, + 0xfb,0x8d,0x74,0xd,0x83,0xa6,0x76,0x87,0x5e,0x7b,0xb2,0x18,0x84,0x8e,0xf6,0xe0, + 0xd9,0x67,0xc6,0xa5,0xa3,0xc5,0x49,0xe4,0x22,0x9c,0x7,0xd1,0x25,0x50,0x55,0xb5, + 0xf3,0xe6,0xaf,0x68,0xf4,0xff,0xb1,0x97,0xcd,0xfe,0x4e,0xdb,0x48,0xf7,0xfa,0x7d, + 0x41,0xb1,0xf3,0x22,0x2c,0x4f,0xd7,0x3e,0x4,0x42,0xe3,0xfb,0x7b,0x81,0x13,0xc1, + 0xf0,0x4e,0xea,0x95,0x89,0x96,0x6d,0x54,0x31,0xe5,0x5,0xb0,0x6c,0xb2,0x94,0xf1, + 0x70,0xe6,0x86,0xcd,0xbb,0x48,0x79,0x45,0x75,0x44,0x6,0xa9,0x71,0x16,0xbf,0x43, + 0xee,0xbe,0x5a,0xd3,0x49,0x67,0x50,0x4b,0xcc,0x9a,0x58,0xb3,0xc0,0xb7,0x2f,0x11, + 0x14,0x69,0xf3,0xab,0x9,0x75,0x4d,0x58,0x56,0xbb,0x91,0xf7,0x85,0xf9,0x16,0x94, + 0x37,0xba,0x48,0xc5,0xf7,0xb5,0x9d,0x1f,0xc9,0xb7,0x41,0xa5,0xac,0xd9,0x81,0x7c, + 0xb3,0x24,0x11,0x20,0x31,0x7b,0xa0,0x2e,0x71,0x88,0xa6,0xbb,0xc9,0x30,0x2b,0xac, + 0xb6,0x42,0xd5,0x2d,0xee,0x92,0x40,0x88,0xa6,0xa,0xca,0x4c,0x9,0xa6,0xee,0xa5, + 0xb0,0xa5,0x4e,0x60,0xd2,0x4a,0xa0,0x13,0xcb,0x52,0x7b,0xcc,0x20,0x1f,0x8b,0x72, + 0xfd,0xa7,0x6f,0x3,0x22,0x2d,0x53,0xc6,0x7a,0x13,0x1b,0xfb,0xec,0xfa,0x6d,0x2c, + 0x11,0x5c,0x90,0x6,0xdc,0xdc,0x99,0xa1,0xa0,0xae,0xc7,0xdc,0x8e,0x7d,0xe0,0x14, + 0x85,0xb1,0x2,0x81,0xc1,0x6a,0xbc,0x8f,0x3e,0x56,0x2b,0xc8,0x3c,0x3f,0xae,0x6, + 0xb9,0xd9,0xf2,0xf5,0xe5,0xac,0x56,0x4d,0x50,0xc7,0x57,0x75,0xb8,0xc2,0x47,0xd5, + 0x82,0x96,0x6f,0x61,0x4c,0xad,0x80,0xbb,0x12,0xe7,0x5,0xbf,0x7f,0xff,0xc,0xdf, + 0xa4,0x21,0x36,0xbf,0xe4,0x6,0x9f,0x1b,0xb2,0xd0,0x58,0xb7,0xe3,0x7d,0xf7,0x75, + 0x2a,0x74,0x38,0x5f,0x8a,0x1a,0x4e,0x82,0x59,0x5c,0x3f,0x3c,0x41,0x68,0xc1,0x8c, + 0x5,0x74,0x43,0xd,0x55,0xdf,0x9b,0xb3,0xf9,0xd7,0xa8,0xf5,0xfa,0x2c,0x3d,0x17, + 0xa9,0xfd,0xdd,0xc1,0x2d,0x7a,0x7b,0x0,0xed,0x9c,0x9c,0x26,0xfc,0xd1,0x2d,0x48, + 0xcd,0xe3,0xa1,0xc2,0x28,0x6b,0x8c,0x3c,0xfa,0x3a,0xe0,0xec,0x78,0x2f,0x7b,0x4d, + 0x62,0xf0,0x94,0x38,0x40,0x97,0xee,0x4f,0xa0,0xd6,0xc6,0x10,0xcd,0x79,0x6d,0x80, + 0x1a,0xef,0xa5,0xea,0xe0,0x97,0x51,0x2d,0x9e,0xbd,0xe4,0x6e,0x57,0xb3,0x2,0xdd, + 0xe0,0x1c,0xf1,0x68,0x97,0x66,0x98,0x35,0xbb,0x7d,0x27,0xf6,0xcd,0x99,0x3c,0xc7, + 0xf8,0x4b,0x93,0xb4,0xba,0xea,0x79,0x2c,0xeb,0xa4,0x57,0x55,0x5,0x18,0x56,0xd8, + 0xd0,0x2e,0xbd,0xc6,0xb6,0x15,0xde,0xb2,0xce,0x43,0x7b,0xa1,0x13,0xc1,0x27,0xb5, + 0xf1,0xdb,0x10,0x48,0xbb,0xd1,0xd8,0xbc,0xae,0x26,0xe7,0xd,0x12,0xc3,0xe0,0xa0, + 0x7f,0xf7,0x30,0xf9,0xe5,0xdb,0xcb,0x61,0xe8,0x2e,0x71,0x79,0x5,0xcd,0x57,0xba, + 0x58,0x75,0xe8,0x27,0x1d,0x67,0x98,0x2e,0xb4,0x82,0x77,0x51,0xc5,0x60,0xe6,0xd0, + 0xa5,0x2b,0x11,0x8d,0x7d,0xf7,0xd7,0xe6,0xd5,0xac,0x33,0xe3,0xcc,0xa8,0xd6,0xcf, + 0xfb,0xad,0xc3,0xd1,0x2f,0x59,0x51,0xe0,0xac,0x5c,0x5d,0x2c,0xe1,0xe5,0x7a,0xe8, + 0xbd,0xba,0xac,0x1a,0xe2,0x14,0xc3,0x2a,0x32,0xc8,0x4f,0xde,0x84,0x20,0xb8,0xd5, + 0x70,0x27,0x5a,0xc5,0xa9,0x4e,0x7a,0x2f,0x8,0x10,0x39,0xdb,0x6e,0x2f,0xdb,0xeb, + 0x68,0x2b,0x4b,0x4d,0x10,0xa5,0x86,0x4f,0x73,0xd2,0xe3,0x5e,0xf6,0xe8,0x1b,0xb9, + 0x49,0x9d,0xb8,0x3a,0x9a,0x31,0x8a,0xb5,0xc6,0x60,0xe7,0xab,0x89,0x36,0x8,0x4d, + 0x8a,0x4d,0xfa,0xb3,0xc2,0x2c,0xcd,0xe6,0xb,0x4d,0x9a,0xb1,0xda,0xda,0x26,0x25, + 0x58,0x66,0xe3,0x9b,0x89,0x3a,0x4e,0xfb,0xd3,0x64,0xe,0x4,0xff,0xc,0xad,0x8b, + 0x85,0xf8,0x1e,0xb3,0x31,0xf0,0xa7,0x63,0xab,0xe8,0x55,0x57,0x2d,0xdb,0xe,0x4a, + 0x56,0x9c,0x10,0xec,0x5c,0x9b,0x42,0xc,0x1e,0xc,0x4,0xa5,0xcd,0xe2,0x56,0x4f, + 0x59,0x37,0xe7,0xf8,0xd6,0x46,0xa,0xdd,0xd2,0x17,0x32,0x53,0xe2,0xe0,0x65,0x4c, + 0x42,0x58,0x89,0x51,0x11,0xd9,0x35,0xd3,0xa7,0x9f,0x42,0x2f,0x4a,0x4a,0x7c,0xe2, + 0xfb,0xbb,0x9a,0x52,0xa7,0xc2,0x2d,0xb2,0x95,0xa8,0x53,0xfc,0x18,0x16,0x70,0xb3, + 0x20,0x92,0x19,0xe5,0x20,0x70,0x76,0xeb,0xe7,0x62,0x81,0xaf,0x46,0x64,0xf4,0xf9, + 0x74,0x49,0x91,0x96,0xc4,0xa2,0xde,0xbf,0xa3,0x4b,0x98,0x16,0x4,0x8e,0xa6,0xac, + 0xc3,0xe,0xd4,0x66,0x7a,0xd6,0xe3,0xbd,0x39,0xf2,0x83,0xb3,0xa2,0xc4,0x35,0x84, + 0x38,0x33,0x58,0xed,0x94,0xe,0x54,0x34,0x1d,0x54,0x43,0x3,0x69,0x3c,0xf5,0xd2, + 0x16,0x4c,0x5,0x5a,0x7a,0xf1,0x2f,0xcd,0x12,0x74,0xd3,0x62,0xfa,0xee,0x52,0x56, + 0xd4,0xaa,0x3b,0x54,0xea,0xaa,0x24,0xe6,0xef,0x64,0x1c,0xcf,0x2a,0x37,0xa4,0xf3, + 0x7d,0x9a,0xe8,0xd1,0x8f,0xef,0x7c,0x3b,0xee,0x71,0xf0,0xa,0xae,0x97,0xfd,0xe2, + 0xe2,0x1e,0xf8,0xb2,0xe2,0xb4,0x6f,0x27,0xe1,0xf7,0x7f,0xfd,0xdb,0x17,0x28,0x7a, + 0x36,0x28,0xab,0x61,0x1c,0x96,0x69,0x40,0x14,0xc4,0x32,0x35,0xe4,0x7c,0x2e,0x39, + 0xc6,0x9a,0xff,0x3,0x50,0xc1,0xe0,0xe9,0xa5,0x45,0xce,0xc,0x6,0x41,0xc8,0xfc, + 0x47,0xa4,0x44,0xdb,0xbd,0xb4,0x1,0x1a,0x8c,0xb2,0xf9,0x73,0xb3,0x14,0x71,0xeb, + 0x1a,0x95,0x11,0xcb,0xd7,0xf8,0xba,0xb2,0x5b,0x17,0xce,0x50,0x98,0x19,0x55,0xba, + 0x8d,0xee,0x53,0xfd,0x99,0x3c,0x2e,0xdd,0xe5,0xc6,0xfe,0x7,0xfa,0x5a,0x8c,0xa3, + 0xa9,0x5c,0x4b,0xb2,0x14,0xde,0x60,0x24,0xc5,0xbe,0x46,0x2,0x38,0xb3,0xdb,0xec, + 0xaf,0x42,0x81,0x18,0xfc,0x94,0xc2,0x7b,0xb4,0xb6,0x65,0xe7,0x46,0xf4,0x71,0x40, + 0x18,0x2d,0xd7,0x36,0xe6,0x32,0x62,0x1f,0xe4,0xec,0xdf,0x2b,0x3c,0x83,0x84,0xc4, + 0xbe,0x32,0x29,0xf3,0xf5,0x36,0x14,0x66,0x60,0x5,0xe4,0x29,0xbd,0xba,0xa,0x8b, + 0x34,0x31,0xa5,0xd0,0x67,0xa0,0x20,0x60,0x92,0x19,0xfd,0x45,0xeb,0x3c,0xb1,0x2, + 0xed,0x67,0xd9,0xf1,0xd6,0x79,0xa4,0x1a,0x97,0xf,0xab,0x51,0x6,0xcf,0xec,0xf3, + 0x8,0x5f,0x5a,0xcb,0x11,0x67,0xd9,0x9d,0x0,0xed,0xe5,0xb6,0xeb,0xa0,0x4e,0x67, + 0x68,0xe1,0xb8,0x89,0xe3,0xd0,0x8a,0x5f,0x4,0x9a,0x2,0x9b,0xc0,0xba,0xac,0xa4, + 0x89,0x55,0x31,0x84,0x44,0x3a,0x64,0xdc,0x9b,0x9c,0x6c,0x95,0x4b,0x7,0x9b,0x6f, + 0x10,0xe2,0xe0,0x7b,0x52,0x26,0x7a,0x56,0x34,0xa7,0x2f,0xe,0x57,0x49,0x2c,0xf, + 0x3e,0xa,0xe0,0x2e,0xa4,0x9c,0x41,0x2,0x96,0x31,0x2a,0x12,0xeb,0x84,0x6d,0x3c, + 0xb3,0x58,0x68,0x3b,0x3a,0xd8,0x88,0xbf,0x1b,0x22,0xd0,0xf9,0x5f,0xe1,0xe2,0x1c, + 0x29,0x53,0x4f,0x9c,0xa4,0x51,0x71,0x74,0xb2,0x1a,0x6d,0xfb,0xc4,0x50,0x8e,0x38, + 0xa7,0xaf,0x73,0x6c,0x53,0x9d,0x56,0x29,0xce,0x3b,0x6a,0xd6,0xd7,0x5e,0xf1,0xfb, + 0xbf,0xf9,0xed,0xeb,0x13,0x26,0xcc,0xb9,0x31,0x9f,0xba,0xdc,0x44,0xb,0x78,0x97, + 0x2e,0x7c,0xab,0xb0,0x48,0x81,0xf1,0x32,0x33,0x8a,0x63,0xb7,0xb9,0xff,0x73,0xb5, + 0x83,0xa6,0x75,0xb1,0xe8,0x3b,0x9a,0x70,0xce,0x3,0x3f,0x79,0xa1,0x42,0x8b,0x46, + 0x5b,0x2b,0xb8,0xe1,0x51,0xe,0xd8,0xfd,0x12,0x3e,0x58,0x9,0x5d,0xf9,0x19,0x6f, + 0x1d,0x97,0xfd,0x59,0x99,0x93,0x66,0x81,0x90,0xf0,0xd6,0xab,0x4c,0x87,0x5b,0xb1, + 0x93,0x60,0x3a,0x26,0x95,0x7e,0x2b,0x86,0xfa,0x1b,0x1d,0x12,0x7c,0xed,0x2,0xc6, + 0x67,0xcd,0x90,0xb8,0x5b,0x2,0xef,0xc5,0xa1,0x8c,0xfd,0x8a,0x73,0x4e,0x9f,0x5c, + 0x9f,0x44,0x34,0x7a,0x9a,0x19,0x48,0x85,0x6f,0x92,0x8c,0x43,0xbc,0x88,0xfb,0xfb, + 0x92,0x22,0x6b,0xc8,0x7f,0x2a,0xe9,0xa8,0x91,0x1d,0xeb,0x13,0xbe,0x99,0xde,0xab, + 0x71,0xc6,0x33,0xe3,0x0,0xf0,0xc2,0xa3,0x86,0xb5,0x2e,0x8d,0xeb,0x3d,0x9f,0x42, + 0x9e,0xa,0xb1,0x3c,0x21,0x40,0x51,0x52,0x62,0x98,0xdb,0x4d,0x49,0x4e,0x2f,0xfe, + 0xb8,0x9d,0xef,0xde,0x7e,0x93,0x61,0xb4,0xa7,0x1e,0x0,0xdb,0x8,0xeb,0x54,0x9a, + 0x7d,0x50,0x34,0xe8,0x35,0x19,0x6b,0x6b,0x5c,0x2,0x29,0xe6,0x38,0x23,0xf0,0xf, + 0xd3,0xb7,0xef,0xdb,0x33,0xf3,0xd8,0x72,0x98,0xe0,0x60,0xb1,0x92,0x75,0xa6,0xf3, + 0x53,0xe2,0x6a,0x6b,0xc1,0x51,0xa1,0xaf,0xc3,0x93,0xf7,0xe5,0x43,0xdf,0x36,0x42, + 0xda,0xe7,0x7e,0xa2,0xec,0x1e,0x1a,0x21,0xdc,0x26,0x57,0xd0,0x62,0x52,0x62,0xdb, + 0xfa,0xee,0xb0,0xfd,0x3b,0xa7,0x51,0xe,0xce,0x17,0x29,0xdc,0x84,0xe,0x86,0xf5, + 0x58,0xcb,0xe6,0x72,0x48,0xe3,0xd,0xf4,0xd,0xc,0xa4,0xf1,0xed,0x13,0x49,0x39, + 0xf5,0xba,0x9a,0x84,0x62,0x1d,0xf0,0xe3,0x4c,0xf5,0xe2,0xf4,0xaf,0xfe,0xf6,0xf, + 0x5f,0x5a,0x75,0x96,0xea,0xd4,0x4e,0x8e,0xbd,0xfd,0xe7,0x2d,0x1e,0xb0,0xc1,0xbb, + 0x38,0xcf,0x59,0xb6,0x4e,0x3a,0xd5,0xc,0x4b,0x9,0xd5,0x25,0x42,0x15,0xde,0xf4, + 0xd5,0x29,0xf,0x6a,0x57,0xf0,0xad,0xb4,0xf2,0xc3,0xa9,0xaf,0xdd,0x12,0x9b,0x31, + 0x53,0xb1,0x71,0xfd,0xf7,0xa2,0xc1,0xc8,0xc9,0x35,0xe5,0x34,0x19,0xf2,0x88,0x29, + 0x49,0x21,0x7,0x36,0x7,0xa8,0x97,0xcd,0x81,0x27,0x46,0xa5,0x69,0xa5,0x7f,0x12, + 0x1a,0xc3,0x35,0xee,0xda,0xdc,0x60,0x6b,0xd8,0xda,0xa,0xf,0xd2,0xaf,0x9,0x9d, + 0x46,0x48,0x5c,0x55,0x8b,0xc4,0xa2,0x3c,0x3b,0x2b,0xda,0xd6,0x75,0x82,0xc4,0xb2, + 0x34,0xa4,0x75,0x5,0xb,0x32,0x7c,0x74,0x6a,0x21,0x82,0xd2,0x4d,0x95,0x54,0xfe, + 0xe7,0xa2,0xc0,0x11,0x1b,0x25,0xb5,0x89,0xf7,0x8d,0xde,0x19,0x26,0x3a,0x31,0x7d, + 0x59,0x64,0x24,0x79,0xe9,0xfa,0x8e,0xdd,0x5e,0x2b,0xb4,0x4b,0x9c,0xd3,0xda,0xbc, + 0x7f,0x78,0x9a,0xb7,0x4e,0x3a,0x2a,0x8c,0x85,0x48,0xc3,0x63,0xff,0x1,0x8f,0x79, + 0xdd,0xcf,0x80,0xae,0x7f,0xbf,0x57,0xd1,0x87,0xf8,0x96,0x80,0xa8,0x51,0xf5,0xb0, + 0x8d,0x1e,0x4,0x1c,0x91,0x4b,0xd3,0x3d,0x1a,0xaa,0x19,0xdf,0xd4,0x50,0x1a,0x63, + 0xa9,0xfa,0xac,0xef,0x47,0x4,0x49,0xdf,0xce,0x4c,0x6f,0x31,0x9f,0x38,0x10,0x8a, + 0xcb,0xb,0xb8,0x11,0x53,0x64,0xad,0x66,0x2e,0x78,0x74,0xc1,0x1f,0x83,0x9f,0x72, + 0xa6,0xc3,0xa9,0xfd,0x42,0xa2,0xc8,0xb,0x91,0x54,0x9e,0xf1,0xba,0x90,0x34,0x89, + 0x9a,0x1e,0x22,0x3c,0xd7,0xd1,0xcd,0xba,0x4d,0x93,0xa4,0xdb,0xeb,0xcc,0x8d,0xae, + 0x50,0x41,0xea,0x33,0x1d,0x72,0xb3,0xb4,0x95,0xbe,0x2b,0xa7,0xfd,0xfa,0x77,0x7f, + 0xf8,0x2a,0xc0,0x83,0xc1,0xb5,0xdf,0xdb,0xc5,0x5f,0x68,0xe4,0x97,0x7a,0x9c,0x9c, + 0xcf,0x82,0x4f,0xbb,0xbe,0x59,0x8d,0xc7,0x16,0xb3,0x9d,0xfb,0xe3,0x92,0xc3,0x1e, + 0x38,0x51,0xcb,0x1b,0x14,0x38,0xfd,0x21,0x68,0xfe,0x74,0xf2,0xa,0x33,0xdd,0x91, + 0x6a,0x10,0xc2,0x4f,0x30,0x69,0xb9,0xd7,0x77,0xe6,0x2a,0x19,0xd6,0xf4,0x90,0x8, + 0x13,0x95,0xa1,0x28,0x51,0xf8,0xed,0x4c,0xd5,0xe9,0xa1,0x98,0x6e,0x42,0xe6,0x50, + 0xf8,0x8c,0x1e,0x79,0xa4,0x11,0x85,0xdb,0x27,0x24,0xbd,0xe1,0x45,0xab,0x6d,0xd0, + 0x76,0x51,0x4d,0x6c,0xc7,0xc5,0xfd,0x29,0xfc,0x82,0x5c,0xea,0x20,0xfc,0xd8,0x9, + 0xf9,0xcd,0xe1,0x77,0xb5,0xfd,0x53,0xf9,0xa8,0x36,0x76,0x69,0xc,0xf9,0xd4,0xa5, + 0x3c,0x31,0x57,0xba,0x62,0x59,0xac,0xf6,0x2b,0xaf,0x8,0x6e,0xdd,0x94,0x59,0x1, + 0x86,0x4a,0x66,0x43,0x18,0xb4,0xd0,0x95,0xf,0x4d,0x59,0xa9,0x8a,0x38,0x55,0xaa, + 0x23,0x7,0xe8,0x25,0xbe,0xa,0xe2,0xdd,0xac,0xf5,0xee,0x7b,0xec,0xb4,0xe5,0x8a, + 0x81,0x40,0x6d,0x85,0xd9,0x9,0xc5,0xd3,0xb5,0xa9,0x4e,0x6c,0xd,0xeb,0x67,0x6e, + 0xb5,0xf4,0xc9,0x8b,0x5a,0xdc,0xa,0xf5,0xef,0xe9,0xe1,0x6a,0xa3,0x51,0x3c,0x24, + 0xc9,0x53,0x89,0xe2,0x9f,0xfe,0x40,0x79,0x94,0x5d,0xfa,0xcb,0xcb,0x5d,0x51,0xa1, + 0x71,0xdd,0x29,0x6d,0x20,0x26,0x2,0x4b,0x4e,0xe1,0x30,0xca,0xfb,0x2f,0x54,0xf0, + 0x22,0x12,0xc2,0x6a,0x39,0xe9,0xed,0x33,0xb8,0xb3,0x4c,0x6a,0xd4,0x56,0xdf,0x2a, + 0xc1,0x33,0xe3,0xcb,0x32,0x9a,0x49,0xe3,0xb1,0x45,0xd2,0x8f,0xaa,0xd,0x4a,0x55, + 0x15,0x7e,0xfd,0xfb,0x7f,0xfe,0xda,0xab,0xa1,0x2c,0xa1,0x31,0x8d,0x4a,0x5a,0xea, + 0x80,0xb3,0xbf,0xa1,0x5a,0xf0,0xc3,0x4c,0xa0,0x55,0x9d,0xf6,0xe1,0x67,0x2f,0x9d, + 0x38,0xe1,0x15,0x5,0x3a,0xe6,0xc,0x31,0xce,0xe9,0x6d,0x45,0xcd,0xe9,0x62,0x11, + 0xdc,0x4c,0xb3,0xe1,0x65,0xce,0x85,0xde,0xd1,0x8,0xa1,0x3,0x58,0xdb,0xd0,0x8f, + 0xb,0x5,0x1f,0x3b,0x24,0x0,0x52,0xdf,0x38,0x6a,0x7,0xc8,0xe8,0xa8,0xc2,0xe0, + 0x46,0x88,0xd1,0xc6,0xbb,0x1b,0xa3,0xfe,0x9d,0xd9,0x75,0x78,0x5,0xff,0x38,0xe6, + 0x3e,0xfe,0x99,0xa8,0x4b,0x5e,0x89,0xb0,0xa1,0xc,0x34,0x64,0x9d,0xd5,0xa7,0xf1, + 0x52,0xbc,0xdf,0xd,0x8e,0xfb,0x38,0x59,0x9e,0x9b,0xf3,0x15,0xd5,0x69,0xeb,0x51, + 0x37,0x8a,0x54,0xd7,0x3e,0xfd,0xad,0xf7,0xac,0xeb,0x5f,0xac,0xb8,0x80,0x9c,0x9a, + 0x99,0xf,0x1b,0xf5,0xf8,0x67,0x80,0xa1,0xf6,0xe7,0xc9,0x86,0xed,0x3e,0x6c,0xe5, + 0x7e,0x9,0xe1,0xcc,0xdd,0xb2,0xe3,0x8e,0x7b,0xcd,0x59,0xf1,0x44,0xce,0x5c,0x58, + 0x7,0x75,0x82,0x66,0xdd,0x39,0x11,0x8d,0xaf,0x90,0xd0,0x4f,0x4,0xd1,0x10,0x80, + 0xe2,0x24,0x96,0xd0,0x92,0x79,0xfb,0x6,0x5d,0x78,0x34,0x3e,0xd9,0x2c,0x28,0x15, + 0xce,0x18,0xdb,0x16,0x7d,0xdf,0xfd,0x71,0x3a,0xfc,0xd9,0x74,0x19,0x9b,0x6e,0x77, + 0x98,0xe5,0xff,0x3f,0x9a,0x9f,0x20,0x3f,0x72,0x9f,0xf5,0x77,0x6c,0x25,0x55,0xa4, + 0xf1,0xce,0x15,0x4c,0x7c,0x87,0x5c,0x14,0x41,0x50,0xbd,0x2a,0x95,0xbe,0xee,0x5, + 0x1,0x87,0xf9,0x4d,0xe7,0x6b,0x20,0x14,0xa0,0x25,0x68,0x1d,0x96,0x96,0xc7,0xa6, + 0x1c,0x85,0x26,0x5c,0xc6,0xd0,0x58,0xc9,0xda,0x89,0xdc,0x71,0xfc,0xfa,0xf,0xff, + 0xf2,0xc5,0x53,0x48,0xf5,0x41,0x65,0x28,0x99,0x13,0x91,0xe6,0x33,0x2,0x59,0x6d, + 0x9,0xa,0xb7,0xad,0x60,0x8a,0xd7,0x9a,0xa4,0x31,0x95,0x4,0x86,0x2d,0x61,0x82, + 0xde,0xe7,0x2c,0xbe,0x41,0xbd,0x4d,0x78,0x0,0xe6,0x6a,0x26,0x3b,0xeb,0xc5,0x66, + 0xe2,0xa0,0x28,0x5a,0xee,0x32,0xbd,0xc2,0x17,0x41,0x8a,0xe,0x2a,0xf4,0xca,0xbe, + 0x17,0x1d,0xba,0x2e,0xc1,0xd,0x85,0x78,0x9e,0x35,0x76,0x61,0x88,0xe3,0x80,0x87, + 0x81,0xf0,0x17,0xf8,0x82,0x5c,0xe7,0x76,0x65,0x63,0x8f,0x1a,0xeb,0x3a,0x77,0xe1, + 0xd1,0x5d,0xa2,0x86,0x4a,0x52,0x23,0x36,0x55,0x46,0x68,0x23,0x49,0x90,0x2b,0x2f, + 0xe2,0xf0,0xa4,0x42,0xe7,0x35,0xf9,0x10,0xe1,0xf0,0xc6,0xb5,0x9f,0xa5,0xfa,0x57, + 0xf8,0xaa,0x2,0x1c,0x88,0x7a,0x10,0x51,0x4a,0x96,0x93,0x32,0xc3,0x57,0xf8,0x4f, + 0x2b,0xfc,0x5,0x20,0x4b,0x8a,0x58,0x5b,0xf1,0x34,0x55,0x13,0x75,0x61,0xe,0x2b, + 0x60,0x62,0x13,0xbe,0x3,0xd4,0x67,0xfa,0x34,0x5b,0x12,0xa,0x9c,0x1c,0xc4,0x2e, + 0x58,0xd5,0x64,0x2,0x8f,0xa2,0x4a,0x5c,0xe5,0xea,0x38,0x76,0x62,0xd4,0xa6,0xf3, + 0x2b,0x6e,0x2b,0xea,0xd6,0x35,0x77,0xf2,0x9e,0x2b,0x81,0xce,0xb0,0x12,0xc6,0x87, + 0x9d,0xc5,0xbe,0x15,0xee,0xbd,0x10,0xc3,0xa1,0xe7,0xee,0xe2,0x47,0xa5,0xc9,0x27, + 0x62,0xa9,0xe7,0x22,0x61,0xfd,0x23,0xc9,0x8,0x2c,0xcc,0x2b,0x98,0xc6,0x8b,0xe9, + 0xc9,0x87,0x78,0xa5,0xb1,0xac,0x1a,0xa,0x4d,0x84,0x98,0x72,0x23,0x1b,0x9d,0x9b, + 0x42,0x70,0x1d,0x5c,0xce,0x11,0x6e,0xfb,0x27,0x2d,0x8e,0xcf,0xe6,0x7e,0x6e,0x41, + 0xa9,0xc3,0xa3,0x96,0x7c,0x5d,0x3a,0x3b,0xb5,0x2,0xf8,0xcb,0xdf,0xfe,0xed,0xeb, + 0x66,0x3b,0xbb,0xc8,0x4a,0x21,0x7,0xc8,0x7a,0x80,0x7d,0xd,0xe0,0x98,0xe8,0x8f, + 0xcf,0xcf,0x51,0x8e,0xc9,0x23,0xd1,0x49,0x1e,0x38,0xd8,0xb2,0x5b,0xac,0xc9,0x6a, + 0xd4,0xeb,0x9a,0xa8,0xd2,0x23,0x4a,0x73,0x2c,0x42,0x20,0xa2,0x3c,0x67,0xa1,0xc1, + 0x46,0xbd,0xc3,0xcd,0x28,0xff,0x1b,0xb9,0x18,0x97,0xba,0x70,0xe8,0x68,0xd7,0xde, + 0xc5,0x59,0xff,0x35,0xc9,0xe5,0x37,0x4d,0x2,0xb7,0x5b,0x15,0x85,0xec,0x84,0x9d, + 0x68,0x72,0xd6,0xab,0xdb,0x8,0x64,0xcb,0x4a,0x7e,0xe0,0xa3,0x29,0xa5,0x45,0xc5, + 0xce,0x6a,0x43,0x23,0xb4,0xf,0x42,0x5a,0x2f,0xe8,0xfc,0x80,0x6,0x1,0x37,0xff, + 0xf6,0xeb,0x22,0xae,0xec,0x90,0xfc,0xa6,0x6b,0xec,0x98,0x9e,0xbb,0xac,0x51,0xd3, + 0x21,0xcc,0xe1,0x9f,0xff,0xfa,0x92,0x8,0x4f,0x73,0xdd,0x19,0xc0,0x2e,0x3,0x14, + 0xdb,0x47,0x6e,0xdb,0x11,0xf,0x23,0x4c,0xa,0xe5,0x46,0x3f,0xcf,0xdc,0x55,0x67, + 0x54,0xd2,0x1b,0x2b,0x46,0xca,0x1f,0x41,0xe6,0xbf,0xb8,0x98,0xb6,0x10,0x69,0x71, + 0x7f,0x3f,0x2a,0x41,0x56,0xa,0x10,0x4d,0x56,0x3f,0xf5,0x7f,0x91,0xc4,0xf4,0x41, + 0xa1,0x17,0xe2,0xee,0xa3,0x7c,0xaa,0x16,0xe3,0xa9,0xc3,0x5d,0x8c,0x42,0x4c,0x67, + 0xd0,0x42,0x61,0xe2,0xdb,0xcf,0x82,0xc8,0x94,0xe2,0xc5,0x17,0x63,0x30,0xcd,0x7, + 0x9a,0xd6,0xba,0xcf,0x8e,0x83,0x84,0xb3,0x7e,0xc4,0x66,0xb2,0xc1,0xd9,0xe7,0x4, + 0xf2,0xda,0xe6,0xf5,0xc6,0x68,0xb5,0xf1,0xe7,0xf7,0xbf,0x76,0x77,0xeb,0xbe,0xb6, + 0xe0,0xbf,0x7f,0x28,0x5c,0x10,0x11,0x20,0xd4,0x11,0x84,0x6a,0xdf,0x27,0x6c,0x61, + 0x6,0xcb,0xef,0x8,0x6,0x7e,0xf7,0x8f,0x7f,0xfc,0x2,0x43,0xb4,0xef,0x31,0x70, + 0x95,0xa8,0xeb,0xd2,0x7f,0x6f,0x4d,0x67,0x36,0xc7,0xa1,0x9a,0x2f,0xa3,0x43,0xed, + 0x52,0xa6,0xa6,0xcd,0x31,0x2e,0xe2,0x9e,0x38,0xc0,0xd0,0xca,0xb5,0xab,0xae,0x2a, + 0xb4,0xfc,0xa0,0x7d,0x46,0xbf,0x15,0xe,0x61,0xb7,0x98,0xe5,0x2b,0x66,0x5b,0x60, + 0xfb,0x7c,0x3,0xee,0x1c,0x40,0x47,0xdd,0xd3,0xd6,0xa8,0xca,0xe7,0x85,0x61,0xc4, + 0x78,0x43,0x85,0x89,0x5c,0xb1,0x30,0x84,0x1f,0x1,0xb4,0x6e,0xd4,0x62,0xdb,0x64, + 0x98,0x62,0x12,0x58,0x86,0x43,0x95,0xdc,0xb3,0x2b,0x90,0x0,0x6b,0xce,0x57,0x54, + 0x4e,0x51,0xd,0x6f,0x28,0x1,0xf0,0x70,0x69,0xf0,0xc9,0x1c,0x0,0xbd,0xc8,0x53, + 0x24,0xe3,0x26,0xc1,0x30,0x6c,0x1b,0x40,0x38,0x9,0x26,0x4,0xb3,0xa,0xc,0xcb, + 0x1c,0x7b,0xf8,0xc,0x70,0x18,0x58,0xcc,0x5c,0x27,0x8e,0x70,0x8f,0x24,0x23,0xe9, + 0xba,0xb6,0x60,0xa9,0xf6,0x9a,0x1b,0x27,0x26,0xce,0x27,0x72,0xf4,0xd5,0xbe,0xde, + 0x4e,0x61,0x5a,0x51,0x5c,0x58,0xa8,0x93,0x84,0x95,0x23,0x8a,0x29,0x65,0xc,0x73, + 0x92,0x4,0xff,0x43,0x8a,0xf9,0x89,0xc,0x42,0x10,0x4b,0x92,0xb1,0xa5,0x7d,0x5c, + 0xb,0x4d,0x4b,0x27,0xc8,0x59,0xcd,0x79,0xc5,0x3a,0x40,0xfe,0x88,0xa2,0x2b,0x25, + 0x42,0x4b,0x16,0x75,0xeb,0xc7,0x83,0x38,0x63,0xb0,0x5a,0x9b,0x6c,0x73,0xc2,0xd0, + 0xe1,0xa6,0x3b,0x64,0x4e,0xb2,0xb2,0x26,0xe6,0xd7,0x6b,0x4a,0x57,0x5f,0x72,0xdb, + 0xe5,0x42,0xe5,0x96,0x51,0x1e,0xe6,0x7e,0x86,0xde,0xa5,0x67,0x9,0x56,0xc,0xa, + 0x19,0x63,0x3f,0xcc,0xeb,0x4b,0xb4,0x4,0xee,0x55,0xb9,0xa,0xfa,0xf4,0xc5,0x2a, + 0xfc,0xee,0x9f,0xfe,0xfd,0x2b,0x56,0x5d,0xe2,0xd6,0x15,0xd7,0x78,0x9a,0x85,0xe1, + 0x2c,0x36,0x25,0x10,0x31,0x73,0x6f,0x4e,0x63,0x46,0x55,0x2e,0xba,0x82,0x71,0x87, + 0x69,0x5b,0x65,0x74,0x15,0x0,0x76,0x33,0x54,0x97,0xbe,0xa9,0xb8,0x59,0xe0,0xac, + 0x45,0x7b,0x9b,0x32,0xcb,0xe4,0x5c,0x75,0xc0,0xca,0x1c,0x19,0xc0,0x33,0xcf,0x13, + 0xe1,0x9d,0x54,0x16,0xf7,0x81,0xb4,0xfa,0xa1,0xd,0x9f,0xb8,0x19,0x9e,0xbe,0xf7, + 0x40,0x81,0xdb,0xc1,0xe,0x30,0x32,0x77,0xe2,0xaa,0x6d,0x97,0xb7,0x24,0x90,0x99, + 0x94,0x66,0x6d,0xda,0x6,0x9a,0x1f,0x61,0xe4,0x98,0x4,0x4f,0xcf,0xc2,0x4d,0x5c, + 0x9d,0x3e,0x6b,0x70,0xc,0xe9,0xd3,0x42,0x69,0x66,0x84,0xa5,0xeb,0x62,0x3f,0x67, + 0x94,0xca,0x1b,0x20,0xae,0xed,0x4b,0x0,0x0,0xf,0x2e,0x49,0x44,0x41,0x54,0xb5, + 0xcb,0x70,0x1c,0x90,0xa2,0x7,0xfd,0x26,0x1a,0x2f,0xe7,0x56,0xb2,0xbb,0xd9,0xb0, + 0x5c,0xe2,0xd3,0x36,0x2f,0x66,0x30,0x88,0xa1,0x91,0xb8,0xb8,0x6e,0xe8,0xd7,0xed, + 0x47,0x10,0x49,0x4e,0xe7,0xae,0x36,0xa3,0x41,0xe1,0xbd,0xaf,0xc5,0x60,0xd5,0x69, + 0x85,0x6d,0xc6,0x15,0xd1,0xd3,0x90,0x96,0xfc,0xce,0x87,0x73,0xfd,0x64,0x94,0x44, + 0xc0,0x91,0xcd,0xe3,0x89,0x23,0x17,0x12,0x66,0x4a,0x22,0xdf,0x77,0xac,0xc7,0x76, + 0xd7,0xaf,0x76,0x86,0x18,0xda,0x72,0x67,0x42,0xd7,0x82,0x63,0xa5,0xe9,0x2a,0x9b, + 0xcd,0x71,0x99,0x52,0xdd,0xc8,0x6c,0xe0,0xc3,0xdc,0xbd,0x74,0x2e,0x2a,0xbc,0xa2, + 0xde,0x71,0x3a,0x4e,0x3e,0x9e,0xad,0x59,0x24,0x6b,0xf9,0x41,0x41,0x4f,0x73,0x80, + 0x4d,0x33,0x6d,0x5c,0x6e,0x98,0xfd,0xd8,0x8b,0x98,0x55,0xf7,0x8f,0x5f,0x7f,0x1a, + 0x2a,0x2d,0x4,0xf,0x8e,0x92,0x8d,0x72,0x15,0xd4,0x64,0x63,0xc6,0x97,0x4b,0x36, + 0x1f,0x78,0x30,0xf8,0xe5,0x5f,0xff,0xf3,0xcb,0xe0,0xa6,0x87,0x26,0x35,0xae,0xeb, + 0x68,0x36,0xee,0x56,0xa9,0x2a,0xf4,0xd2,0x5d,0xcb,0x92,0xe3,0xbd,0x1d,0x4,0x79, + 0x1d,0x71,0x85,0x2a,0xf7,0xf0,0x87,0x6d,0x3b,0x83,0xa6,0x68,0x95,0xb3,0xcf,0x4d, + 0x7d,0xcc,0xe3,0x2,0xad,0xe,0x4e,0x61,0x3f,0xd4,0x4d,0xa0,0xa2,0xef,0x2c,0x77, + 0xb9,0xce,0x7d,0xf5,0xef,0x67,0xca,0xca,0xed,0x5f,0x87,0x4d,0x0,0x56,0x80,0x0, + 0x15,0x77,0x65,0x86,0xa9,0xde,0x57,0x4b,0x4,0x57,0xd6,0x12,0x2e,0x92,0xce,0x9a, + 0x87,0x7c,0xa,0xd3,0xba,0xdf,0x6e,0x5a,0x7,0x41,0x2,0xa0,0x9d,0x3f,0x6,0x46, + 0x30,0xa4,0xa5,0xbd,0x83,0xc2,0xbe,0xf,0x8c,0x9c,0x32,0x1e,0x17,0x1,0xe6,0xa3, + 0x56,0xf6,0x2e,0xc2,0xf,0x4f,0xf3,0xdd,0x85,0x89,0x67,0xbb,0x8d,0xa1,0xab,0x51, + 0x8c,0x3c,0x40,0xb2,0x13,0x4d,0x62,0xf0,0x57,0xc8,0x16,0x3d,0x43,0x77,0xbc,0xf9, + 0xb,0xa0,0x43,0xfb,0x10,0x7d,0x70,0x94,0x99,0x7b,0x5e,0x37,0xa8,0xad,0x68,0xf9, + 0xad,0xc2,0x72,0xac,0x59,0xb5,0x6d,0x79,0x2c,0x50,0x93,0x75,0xb8,0xf6,0x68,0xa5, + 0x98,0x3e,0xbd,0x68,0x70,0x53,0xcb,0xb2,0x33,0x49,0x8,0x12,0xa3,0xe2,0x31,0x98, + 0x46,0x41,0x9,0xc1,0xc8,0xc5,0xa2,0x2a,0xc2,0x71,0x25,0xcc,0xa1,0xab,0xd7,0x55, + 0x43,0x58,0xcd,0xa5,0x3d,0x29,0x8f,0x23,0xc,0xba,0xe6,0x3a,0x5c,0x5a,0xcf,0x84, + 0xc9,0xd6,0x1e,0xe7,0x69,0xf,0x23,0xa7,0x65,0xb5,0xf4,0x4,0xb0,0xf2,0x10,0x18, + 0x8d,0x10,0x95,0x1a,0x9,0x3e,0x70,0xce,0xe,0xe3,0x98,0x2d,0x7c,0x23,0x18,0xf6, + 0x90,0x3b,0x54,0x3,0x1a,0x21,0x6,0xbf,0xfc,0xf1,0x4f,0x5f,0xfb,0xd0,0x41,0x1b, + 0x3f,0x58,0xf7,0x57,0x8a,0xe9,0xb7,0x6c,0xf4,0x86,0xba,0xd1,0xf5,0x9e,0xab,0x8c, + 0xd1,0x29,0x6,0x54,0x1b,0xf8,0x30,0xbe,0x98,0x75,0x28,0x16,0xc0,0xd2,0x80,0x8f, + 0xb1,0xfa,0xe7,0xd8,0xa5,0xd5,0xe3,0x89,0xc7,0x55,0x82,0x2b,0x29,0x28,0x44,0x18, + 0x3a,0x3f,0x2b,0x6c,0x83,0xba,0x54,0x8d,0xf5,0xe,0x87,0xfc,0x6,0x38,0x2e,0xb, + 0xed,0xe8,0x1e,0xd4,0x3d,0x54,0x74,0x19,0x4e,0xf6,0x5d,0x60,0xed,0xb2,0x1a,0x39, + 0x2d,0xc8,0xb8,0xae,0xb5,0x41,0x3a,0xcb,0x66,0x1a,0x5,0x5f,0xb4,0xdd,0x76,0x6d, + 0xeb,0x54,0xac,0xd1,0x3c,0x8d,0xb3,0x8a,0xda,0x74,0x77,0xea,0xc9,0x25,0x6e,0x30, + 0x7e,0x38,0x6c,0xa1,0xcd,0x15,0x6b,0xaa,0xc3,0x91,0x43,0x3c,0xa4,0x48,0x81,0xaf, + 0x1d,0x9a,0xc6,0x66,0xd2,0xa0,0xc3,0xad,0xae,0x96,0xb5,0xd4,0x6d,0x1b,0x9,0x6b, + 0xdf,0x23,0x87,0xad,0xab,0x66,0x58,0x4d,0x83,0xd7,0xc,0x38,0x63,0xb,0x46,0x82, + 0xdf,0x8d,0x6,0x55,0xf3,0x89,0x86,0xd4,0xf0,0x29,0x79,0x9c,0xe3,0x74,0x9e,0xd5, + 0x77,0x49,0xd9,0x26,0x72,0xd4,0x7d,0x22,0xaa,0x9a,0xe7,0x42,0xa4,0x17,0xb5,0x73, + 0x3d,0xd5,0x19,0xeb,0xd8,0xdd,0xce,0xa0,0x9,0xfa,0x58,0xab,0xcb,0x9d,0x3e,0x8e, + 0xb1,0xd2,0x5,0xb3,0x57,0xb1,0xd,0x95,0xb7,0x3e,0x7,0x73,0x4c,0xa5,0x68,0x23, + 0xf9,0xe9,0xca,0x49,0xf8,0xe7,0x27,0xcc,0x31,0xac,0x26,0xf3,0x60,0x41,0x7c,0x4c, + 0xc6,0x4b,0x12,0x7e,0xd0,0xb5,0x9c,0x85,0x6f,0x7a,0x91,0x29,0x9,0xd1,0xab,0x31, + 0x6,0xc,0x3e,0x7e,0x15,0xd3,0x5f,0xce,0x49,0x3f,0x3e,0xd7,0x50,0x54,0x30,0x40, + 0xf2,0x3d,0xe7,0xff,0xc5,0x7f,0xfc,0xd7,0x97,0x26,0xee,0xb8,0x15,0x67,0xde,0xd9, + 0xfb,0xa5,0xca,0xdd,0xee,0x83,0x4b,0xa6,0x79,0x28,0x3b,0x24,0xc8,0x10,0xb4,0xaa, + 0x74,0x8f,0xb5,0xd5,0xf9,0xdd,0x80,0x60,0x20,0x65,0xbe,0xca,0x52,0xb5,0x93,0xcf, + 0x36,0x24,0x6f,0x0,0x9b,0x1a,0x8,0x13,0x1c,0xc5,0xd3,0x2c,0xb,0x71,0x1e,0x4d, + 0x7a,0x12,0x31,0x79,0xd0,0xa0,0xae,0x19,0x8b,0xde,0x4,0x6e,0x2c,0x41,0x33,0xed, + 0x71,0x16,0x55,0x3e,0x40,0x12,0x14,0xbc,0x80,0xba,0x1d,0xa3,0xb0,0x2a,0xf4,0xe1, + 0x8,0x87,0x65,0xd2,0x89,0x8b,0xec,0x54,0x60,0xd5,0xf1,0x50,0xd4,0x3d,0x31,0x72, + 0x53,0x0,0x6d,0xe4,0x93,0x52,0xc9,0x51,0x3d,0x5b,0x6c,0x64,0x43,0x7c,0x1e,0x6c, + 0x99,0x21,0xf6,0x81,0x84,0xaa,0x26,0x77,0x9a,0x9b,0xb6,0x7,0x4,0x15,0xa,0x31, + 0x34,0x29,0x6f,0x22,0x94,0x18,0xc6,0xac,0xf1,0x3b,0x22,0x38,0x1f,0x70,0x43,0xb6, + 0xce,0x45,0xd7,0x72,0xd2,0x76,0x4d,0xc,0x8e,0x69,0x1d,0xe8,0xd0,0x15,0xa5,0xf6, + 0xb9,0x82,0xfc,0x2d,0x1f,0xcc,0x8a,0x2d,0xa8,0xa7,0x9d,0xfd,0xc3,0xb,0x37,0xa6, + 0xea,0x43,0x12,0xdd,0x6,0xba,0x8,0xa2,0x6,0x5a,0x3c,0xae,0xf0,0x4,0x3f,0xf8, + 0x3d,0x5b,0x79,0xbf,0x3d,0x87,0xda,0x15,0xe9,0xb0,0xb0,0xd7,0x79,0x60,0xeb,0x1c, + 0xd5,0xba,0x50,0x8f,0x2d,0x7a,0x54,0x93,0xe2,0xf9,0xef,0x23,0x9c,0x8b,0x6d,0x3d, + 0x44,0x3,0x31,0x79,0x0,0x72,0x3a,0x6b,0x8e,0xf,0x77,0x61,0x7b,0x36,0xde,0xb9, + 0xe3,0xf5,0xa7,0x3f,0x7f,0x3d,0x42,0x5,0xf8,0x94,0xb8,0xf5,0x1,0xbd,0x32,0x2d, + 0x81,0xd7,0x9c,0xe3,0xea,0x8f,0x8a,0xe4,0xcf,0x4e,0x42,0xd1,0x7e,0xce,0xc8,0xd5, + 0x3a,0xb9,0xa4,0x3c,0xd7,0xee,0x97,0x3b,0xd9,0xd1,0x37,0xa1,0x4c,0xf6,0x44,0xdf, + 0x16,0xab,0x8d,0x38,0x48,0x71,0xee,0x18,0x66,0x10,0xa7,0x38,0x6e,0xef,0xca,0x25, + 0x6b,0x59,0x1f,0xcc,0xac,0xea,0xa9,0x8d,0xa9,0xe7,0x43,0xdc,0x8d,0x6f,0x5a,0xef, + 0x75,0x7d,0x17,0xd6,0xaa,0x8,0x56,0xc7,0xde,0x6a,0xf9,0x98,0x61,0x7b,0x8,0x42, + 0x20,0xe4,0xf0,0x69,0x4e,0x5f,0x13,0x81,0x37,0x50,0xb3,0xab,0xba,0x8a,0x8b,0x0, + 0xd,0xea,0x42,0xe3,0x48,0xa6,0x87,0x65,0xf1,0x7a,0x9e,0x28,0xd8,0xf3,0xe,0x73, + 0x44,0xf,0x8c,0x9,0xd6,0x9,0x41,0x38,0xee,0xc1,0x6c,0xe4,0x1a,0x84,0xb,0xf2, + 0x54,0x5d,0x99,0xf5,0x59,0xaa,0xea,0x3e,0x8,0xb8,0x59,0x52,0xd4,0x5d,0x99,0xf8, + 0xc,0x3b,0x54,0x1d,0x3,0xda,0xb6,0x6,0xba,0x42,0xa2,0x96,0x80,0x79,0x26,0x3c, + 0x6d,0xcc,0x1f,0xed,0x30,0x2a,0x4,0xe8,0xc7,0xe7,0x83,0xf3,0xec,0x13,0xe6,0x62, + 0x25,0x5,0x75,0x98,0x25,0x6a,0x27,0xae,0x5,0xc6,0xa6,0x40,0xa4,0xc9,0x79,0xd0, + 0xb5,0x57,0xed,0x65,0x39,0x23,0xe5,0x1b,0x4d,0x25,0xc9,0xef,0x29,0xbf,0x6e,0x85, + 0xb5,0x1e,0x7c,0x73,0x43,0xdc,0x8d,0x5a,0x72,0xf1,0x53,0xf9,0xcf,0x59,0x81,0xbf, + 0x9d,0xa1,0x7a,0xe0,0x12,0xf0,0x50,0xbc,0x6f,0x66,0x27,0x21,0x76,0xf0,0xc4,0x55, + 0x60,0x1,0x7f,0xfe,0xef,0xaf,0x99,0x23,0x21,0xb,0xf3,0xbc,0x66,0x94,0x97,0xe, + 0x3b,0x5c,0x34,0x41,0x7f,0x36,0xb6,0x7b,0x2a,0x2c,0xb,0x54,0x16,0xdd,0xa9,0xca, + 0xe3,0xa8,0xb9,0xef,0xa8,0x7,0xf4,0xa1,0xf2,0xea,0xbb,0x80,0x43,0x53,0xb2,0x41, + 0x7d,0x7d,0x6e,0xdd,0x56,0x76,0xe6,0x4f,0xfa,0x5c,0x1f,0x5a,0xf7,0x4e,0x69,0xc5, + 0xdf,0x34,0x67,0x18,0x7e,0xe2,0xc2,0x36,0xde,0xd4,0x85,0x2c,0x39,0xd,0xd8,0x17, + 0x17,0xc4,0x69,0xde,0xe1,0xe3,0xb1,0x70,0x16,0x30,0xf5,0xc4,0x86,0x7e,0x3a,0xc0, + 0xf5,0xdc,0x5e,0xac,0xc1,0xf3,0x83,0x1d,0xd6,0x63,0x50,0x97,0xc0,0xc6,0x23,0x1d, + 0xe8,0x64,0x4c,0x97,0x2f,0x23,0xf,0xbf,0x1f,0x89,0xbd,0xf6,0x0,0x97,0x56,0xe8, + 0x32,0x4d,0xf3,0xb7,0xf2,0x2e,0x2e,0x4f,0xac,0xd9,0xa7,0x4c,0xbb,0x14,0x88,0xa7, + 0x5d,0xef,0x98,0x5c,0x1f,0x92,0xf1,0x27,0xef,0xea,0xd4,0xb9,0x27,0xd1,0x9,0xa, + 0xec,0xbf,0x15,0x19,0x15,0x12,0x81,0x2b,0x4a,0xed,0xf8,0x50,0x7c,0xff,0xc1,0x78, + 0x86,0x3c,0xcd,0x9a,0xe,0xef,0xba,0x42,0x67,0xff,0x1,0x9c,0x6d,0x5,0xd1,0x7, + 0xdc,0x99,0xaa,0xcf,0xe9,0xf4,0xdb,0xea,0xd0,0x9,0x5,0xc1,0xa1,0x88,0xd9,0x7c, + 0x22,0x1e,0x13,0x7a,0xe5,0xf3,0xfa,0x54,0xe0,0x26,0xed,0x8,0x1e,0x20,0xf8,0xa3, + 0x6b,0x28,0xc3,0x7d,0xb,0xe2,0x8,0xda,0xbd,0x3f,0xe9,0x28,0x1d,0x1b,0xac,0xf, + 0xd4,0x3,0x43,0xd1,0x3,0xfc,0xcf,0xff,0x7e,0x29,0x0,0x1d,0x25,0x12,0x93,0xec, + 0x6c,0x85,0x71,0x48,0xb2,0x85,0x69,0x1f,0x66,0xd0,0x3a,0xda,0xcc,0xb1,0x7,0x42, + 0x35,0x92,0xa8,0x52,0x59,0x48,0x3c,0x17,0x97,0xe5,0x9a,0xd8,0x87,0x90,0xbe,0x3c, + 0xe6,0xa7,0xde,0xfa,0x1,0x23,0xfb,0xd9,0xbf,0x7e,0x82,0x67,0xf8,0xb0,0x3b,0xb1, + 0x75,0x24,0x1a,0x54,0x9e,0xaa,0xc8,0x78,0xf8,0xf,0x58,0x57,0xc4,0xbe,0x6b,0x3f, + 0x84,0x5b,0x60,0xb3,0xce,0xb5,0xb2,0x41,0xb6,0x75,0x5c,0x15,0x96,0xed,0x43,0x35, + 0xc5,0x90,0xc,0xec,0xe7,0x6e,0x33,0xb6,0x14,0xe4,0x97,0xee,0x68,0xeb,0xe6,0xac, + 0xaa,0x87,0xab,0xcf,0x1d,0xb,0x99,0x93,0x22,0x4e,0xea,0xc4,0xf9,0x0,0xb1,0xd6, + 0x7e,0x0,0xb7,0x39,0x6a,0xea,0xe0,0x90,0x3a,0xc6,0xd3,0x99,0xad,0x7d,0xe6,0xf9, + 0xe4,0xb3,0x52,0x29,0x89,0x1d,0xba,0xed,0xa8,0x6f,0xbc,0xcc,0x3f,0x8f,0x1d,0x50, + 0x4a,0x6e,0x95,0x3b,0xb6,0x4f,0xe1,0xe9,0x27,0x42,0x8a,0x75,0xa0,0x95,0x3b,0xca, + 0x93,0x48,0xcb,0x9,0x25,0x51,0x4,0xb5,0xe,0x5d,0xfb,0xa2,0xf6,0x59,0xdc,0x54, + 0x7f,0xf8,0xc1,0xac,0xbb,0x3e,0x78,0xe,0x1f,0x14,0xa5,0x71,0xf6,0x8a,0x3c,0xfb, + 0xde,0x60,0x6f,0x86,0xf3,0x5f,0x7c,0x7c,0x7d,0x7b,0x23,0x80,0xcf,0xb8,0x8,0x76, + 0xae,0xe,0xa3,0xa3,0x18,0xf3,0x65,0xa6,0xe,0xd4,0x2f,0x7c,0x41,0x8,0x1f,0xaf, + 0x1a,0x74,0x1f,0x53,0xd2,0xbc,0x57,0x64,0xc6,0xcb,0x7c,0xf5,0x7,0xf0,0xca,0x9d, + 0x33,0xc4,0x87,0x18,0xef,0xf9,0xef,0xab,0xa6,0xba,0x11,0xec,0x1,0x73,0xd9,0x7d, + 0x4c,0x17,0x8f,0xb,0xde,0xcc,0xa7,0xb4,0x6e,0x28,0x26,0xf7,0x4b,0xa6,0x4b,0xdd, + 0xe9,0x67,0xf2,0x83,0x99,0x94,0xea,0xb7,0x32,0x5,0x2e,0x86,0x79,0x35,0x73,0x60, + 0xa2,0xcf,0xe1,0x4f,0x63,0xfa,0xeb,0xfb,0xa5,0x2e,0x7,0x46,0x27,0x5f,0xba,0xd7, + 0xd4,0x21,0x1e,0x8a,0x89,0x75,0x15,0x49,0x2,0xd1,0xc0,0xe0,0xd5,0xff,0xb4,0xff, + 0x3d,0x79,0x47,0x83,0xd0,0xf5,0x50,0xcc,0xe8,0xf7,0x40,0x5,0x3,0xf0,0xc3,0xde, + 0xb,0xf,0xb0,0x72,0xd5,0x12,0x28,0xe5,0x22,0x46,0x97,0x9e,0xfe,0x59,0xb0,0x40, + 0x78,0xcb,0x5c,0x8f,0xa7,0x60,0xa1,0x90,0xab,0x92,0x63,0xe4,0xf9,0xdb,0x2e,0x79, + 0x4d,0x3,0xe6,0xd,0xbe,0xe6,0x42,0x50,0xad,0x0,0x55,0x69,0x2,0xe0,0xa1,0x6b, + 0x39,0xad,0xe0,0x30,0xdc,0x45,0x2c,0xdf,0x27,0x39,0x3c,0xc6,0x40,0xac,0xf2,0xa6, + 0xb5,0xfc,0x9e,0x7a,0x1b,0x92,0x67,0xd8,0x14,0xe1,0x2e,0x1f,0xb,0x6b,0xb4,0xe7, + 0xc0,0xc9,0xae,0x66,0x3a,0x87,0x3d,0xc9,0xf2,0x4c,0xd4,0x20,0x97,0x19,0xbc,0xbc, + 0xdb,0x71,0xde,0x19,0x60,0x3b,0xf8,0x73,0x7f,0x7f,0x4f,0x2b,0xf2,0x28,0xf7,0x25, + 0xc9,0x37,0x2f,0x9,0x76,0xfc,0xc5,0x87,0xcf,0x6e,0xd0,0x2e,0x77,0x43,0x8b,0x6b, + 0x13,0x4b,0xde,0xdb,0xc9,0xaa,0x42,0xb,0x68,0xc2,0x46,0x95,0x83,0xf8,0x12,0x81, + 0x1b,0xe5,0x10,0x7c,0x82,0x80,0x54,0xed,0x36,0xba,0x77,0x5e,0x78,0x7d,0xf,0xa2, + 0xee,0xb7,0x7d,0x7,0x77,0xcc,0xff,0xdd,0x13,0x10,0xc2,0x43,0x88,0x3e,0xd7,0xc, + 0x81,0x5c,0xe6,0xea,0x27,0x25,0xf,0x6e,0x7,0x40,0x2b,0x2b,0x8,0xdc,0xa5,0xff, + 0x3d,0x44,0x6b,0xd4,0xe2,0x5d,0x87,0x6,0xc9,0xbf,0xcd,0x66,0x45,0xb1,0xe2,0xfa, + 0x59,0xfd,0x77,0xe3,0x99,0x8,0x54,0x72,0x51,0xd9,0x7e,0x8f,0x42,0xa,0x90,0xdd, + 0x3f,0xb2,0xce,0x95,0x4d,0x70,0x34,0x21,0xf6,0x3f,0x4f,0xa1,0xf9,0x92,0xe1,0x7f, + 0x53,0x3e,0x4f,0x2d,0xee,0x6e,0x72,0xf1,0xb4,0xe8,0x0,0xf6,0x3f,0x2e,0x8f,0xd3, + 0x7e,0x16,0xf,0xd8,0x7f,0xef,0xbe,0xaf,0xcb,0x1a,0xde,0x3,0x10,0xfe,0xec,0x9, + 0x6e,0x7e,0x7f,0x66,0xb4,0x73,0x92,0x76,0x1c,0xe1,0xcf,0x2d,0x2d,0xf3,0xb3,0xbc, + 0x88,0xb3,0x55,0xb7,0x90,0x98,0xb1,0x24,0x64,0xfd,0x3d,0x3d,0xa0,0xdb,0xd2,0x30, + 0xe6,0x59,0x1f,0xc,0x56,0xc8,0xe7,0x93,0x62,0x48,0xe3,0x29,0x6a,0x92,0x1d,0xfa, + 0xcb,0x5b,0x73,0x15,0xc7,0xb5,0xb2,0xbb,0x97,0x2f,0xa2,0xcf,0x82,0xc7,0x5d,0x6e, + 0x5,0x8d,0x25,0x68,0x2c,0x41,0x3e,0x9d,0x6d,0xcc,0x82,0x41,0xeb,0x9,0xb0,0x8e, + 0xdc,0x20,0x96,0x27,0x35,0x9c,0xf0,0x40,0x2e,0xf3,0xb8,0x56,0xa8,0x91,0xa1,0x95, + 0x3b,0xfd,0x27,0x43,0xc1,0xa4,0xdf,0x21,0x34,0x10,0xe8,0xeb,0xc5,0xa1,0x73,0x5e, + 0x39,0x66,0xda,0x2c,0x2c,0xcf,0xdb,0x9c,0x3b,0xcb,0x3f,0x27,0x91,0x45,0xbd,0x10, + 0x9a,0x92,0x9a,0xa3,0xd2,0x59,0x4,0xe2,0x7e,0x76,0xd6,0x58,0xc0,0x75,0x3b,0xde, + 0x3f,0x67,0x2d,0x12,0xe1,0xc5,0x89,0x9e,0xfd,0x8e,0xfa,0x8c,0x42,0x48,0x59,0xca, + 0x92,0x80,0x19,0xc6,0x3d,0xe9,0xae,0x43,0xc6,0xca,0x5c,0x5e,0xc8,0x8f,0x7f,0xff, + 0x1a,0x5f,0x88,0x90,0x36,0x37,0x24,0x30,0x86,0x76,0xf8,0xa,0x78,0xfa,0xa1,0x11, + 0xce,0x5f,0x20,0x5a,0xbc,0x1f,0x36,0x3,0x2c,0x84,0x85,0x2e,0x8f,0xa5,0xe3,0x4c, + 0x10,0x95,0x56,0x38,0xe9,0x1e,0x0,0x5e,0x51,0x5e,0x55,0x29,0x25,0xd9,0x94,0x17, + 0x4,0x57,0x87,0xb7,0xec,0xa0,0xc6,0x2e,0x5c,0x2,0x3c,0x35,0x89,0x1d,0x12,0x0, + 0xa5,0xf0,0x0,0xf3,0x4c,0x14,0x33,0x5e,0xc5,0x29,0x1,0x2a,0x4,0xfc,0xfe,0x77, + 0x31,0xbb,0x34,0xea,0x19,0x41,0x80,0x4b,0x21,0x5d,0xb3,0x74,0x17,0x23,0xe9,0x23, + 0xcf,0x90,0xa3,0x65,0x6a,0x22,0xbf,0x38,0xc2,0x3d,0xb,0x4f,0x3d,0x3b,0x90,0x77, + 0xd7,0x12,0xf7,0x8,0x3e,0x98,0x9,0x92,0x29,0x20,0xd1,0xf,0xe5,0x75,0x6,0x82, + 0x53,0x83,0x92,0x8b,0x6c,0xeb,0x81,0xfe,0x9e,0xb9,0x15,0x1,0x9c,0xa8,0x45,0x3c, + 0x9f,0x94,0xe2,0x51,0x2,0x7c,0x3f,0xb7,0xef,0x67,0xf0,0x94,0x90,0xa9,0x45,0xc, + 0x43,0x87,0x1a,0xce,0x3c,0xa5,0xb0,0x19,0xc7,0x3d,0x24,0xfc,0xa8,0x25,0xdb,0x9f, + 0x7,0x5,0x46,0xe7,0xb9,0x80,0x66,0x3a,0xeb,0xf0,0xca,0x52,0x47,0x21,0xf4,0x95, + 0xb3,0x35,0xc6,0x8d,0x24,0xa1,0xf1,0xb4,0xf2,0x18,0x8a,0xa1,0x41,0x2a,0x4,0x4, + 0x25,0x40,0x5d,0x4c,0x5,0x51,0xd8,0x4e,0xe2,0x32,0xaa,0x60,0x8f,0xfb,0xc9,0x98, + 0x21,0x20,0x88,0x5b,0xdd,0xc5,0x50,0x28,0xf6,0x84,0x23,0xe8,0xec,0x44,0x98,0x98, + 0x93,0x76,0xd4,0xad,0x90,0x7c,0x85,0x87,0x86,0x6f,0x24,0xc1,0xf6,0xe,0x91,0x8a, + 0x8d,0x3a,0xcf,0xb1,0x19,0x90,0x2c,0x17,0x5c,0x91,0xcf,0x8f,0x83,0xd7,0x9,0xfc, + 0xae,0x97,0x14,0x78,0xc9,0x22,0x9b,0x12,0x3f,0x70,0x61,0xe3,0xf4,0x44,0x96,0xce, + 0x1d,0x98,0xab,0xf7,0x5e,0xc5,0x74,0xd8,0xf2,0xb4,0xe0,0x7b,0x5,0x77,0xa,0xdc, + 0x19,0x2a,0x4c,0x86,0x8e,0x9b,0x49,0xb3,0xb3,0xff,0xc,0x86,0xca,0x5c,0xe1,0x63, + 0xfd,0x8c,0xcc,0x7,0x9a,0x4b,0xe5,0xdf,0x5f,0xb0,0xcd,0x9e,0xe9,0x87,0x36,0x21, + 0x12,0x78,0xe8,0xb0,0x35,0xa0,0x20,0x74,0x50,0x68,0x9d,0xb0,0xae,0x82,0x40,0x21, + 0xd6,0x7e,0x78,0x90,0x21,0xa6,0xf8,0xdf,0xe9,0x1,0x3c,0xc2,0xda,0x9a,0xac,0xc2, + 0x77,0x4d,0x5d,0x42,0xaf,0x44,0x7,0x54,0xc6,0xcc,0x8,0xd5,0x6e,0xbb,0xd2,0xa8, + 0x2,0xa1,0xb0,0x92,0x6a,0x9a,0xd,0xfd,0xa1,0x6,0x15,0x7a,0xc1,0x60,0x10,0xba, + 0x76,0x62,0x1d,0x1e,0x95,0x51,0x4,0xfa,0xfd,0x42,0x80,0xe8,0xd2,0xbb,0x4d,0x45, + 0x87,0x74,0x2d,0xa,0x81,0xc6,0x59,0x2e,0xbc,0x28,0x4e,0x15,0x31,0xb9,0x77,0x5e, + 0x76,0x36,0x53,0x0,0x5d,0x90,0x2f,0xed,0x14,0x91,0xa0,0xd6,0x20,0x7e,0x5d,0x5b, + 0x1c,0x61,0x18,0x7b,0x84,0x77,0x4d,0xe1,0x3a,0x24,0xe4,0x1,0x82,0xb4,0xc,0x14, + 0x26,0x6c,0x7f,0xd4,0x82,0xae,0x24,0x78,0x46,0x3b,0x2e,0x84,0xc0,0xf,0x64,0xb4, + 0xcc,0xee,0x5c,0x88,0x1,0x56,0x90,0x84,0xa2,0x30,0xb9,0xa1,0x61,0x1b,0x57,0x54, + 0xd8,0x37,0x3e,0x90,0x90,0xc0,0xb5,0x8e,0x18,0xcd,0x45,0x3a,0x23,0xdc,0x20,0x77, + 0xfd,0x79,0x8a,0xd6,0x6a,0x12,0xe7,0xec,0xf0,0x49,0x7f,0xd6,0xc7,0x82,0xa1,0x3e, + 0x20,0x1f,0xf2,0x6c,0x33,0x8c,0x43,0x2c,0xd0,0x98,0xc0,0x50,0x30,0xe1,0xe9,0x59, + 0x20,0xa0,0x62,0x82,0xc,0xfd,0x78,0x6d,0x2f,0x3b,0x84,0x3,0x96,0x80,0xcc,0x4e, + 0xe0,0xf0,0xc3,0x8,0xda,0xc8,0x95,0x54,0x61,0xdf,0xa3,0x23,0x97,0x8a,0x2c,0xec, + 0x37,0x32,0xcc,0xaf,0x6d,0x7e,0xba,0x7d,0x6,0x9,0xe8,0x70,0xf5,0x22,0x9f,0x8d, + 0x84,0x4b,0xda,0x2b,0x6f,0x3c,0x90,0x38,0x28,0x89,0x8d,0x4f,0x49,0x1c,0x7,0x78, + 0x58,0x8a,0x9c,0xa8,0x62,0x85,0xdc,0x19,0x8d,0xd9,0x17,0xfd,0x67,0x26,0x68,0x3a, + 0x55,0x8d,0x88,0x64,0x85,0x79,0xe,0xc,0xaa,0xaa,0x4c,0x6,0x4b,0x45,0x47,0x87, + 0xca,0x8,0xe9,0x8,0x10,0xe0,0x66,0x48,0x50,0x91,0x33,0xb2,0xae,0xf8,0x31,0xc3, + 0x81,0xe3,0xb3,0x60,0x6,0xc,0x2e,0x9,0x66,0xdb,0xdf,0xa5,0xb8,0xe2,0x31,0x5c, + 0x40,0x2e,0x1d,0x79,0x8a,0xb,0x58,0x8a,0xe8,0x58,0x8c,0x9f,0xb8,0x1d,0x10,0x48, + 0x17,0x73,0xb4,0x56,0x32,0xfe,0xd9,0xde,0xa3,0x12,0x9,0xb9,0xc0,0xf8,0x78,0x18, + 0xff,0xe8,0x41,0x65,0x18,0x2f,0xe0,0x30,0x6a,0xd1,0x9d,0xde,0x4d,0x6,0xd6,0xba, + 0x43,0x19,0xe7,0xb1,0x17,0xfe,0x5c,0xe6,0xbc,0x98,0xef,0x16,0xdc,0x57,0x73,0x46, + 0xac,0xa8,0x4c,0xde,0x2c,0x3e,0xcb,0x51,0x44,0x98,0x9e,0x7,0xd9,0xbb,0x43,0x50, + 0x4a,0x9b,0x9,0xc0,0x1e,0x27,0xb1,0x8d,0xc,0x12,0x44,0xca,0xb9,0x95,0x51,0xc, + 0xeb,0x4e,0x7d,0xf4,0x83,0x80,0x70,0x3c,0xad,0x68,0xb1,0x22,0x4f,0xc4,0x12,0x76, + 0xe0,0xc4,0x58,0x33,0x1a,0xc6,0x22,0x58,0x8a,0xf9,0x94,0x9b,0x80,0x99,0x97,0x8, + 0x77,0xda,0x4a,0x15,0x18,0x16,0xb,0xda,0xa8,0xde,0xb9,0x91,0x35,0x19,0x72,0xf0, + 0xf7,0xcf,0xf2,0x3a,0x9f,0x5,0x86,0xb9,0x66,0xe5,0x84,0x3c,0x58,0xbf,0xc2,0x98, + 0xee,0xf,0x1c,0x52,0x91,0xe3,0x3,0xf3,0x13,0x9d,0xe3,0xb2,0xe,0x2a,0x56,0xcc, + 0xc8,0x9,0x90,0xe5,0x34,0x37,0xa6,0xa7,0x15,0x29,0xdc,0x87,0xbf,0x27,0xa8,0x53, + 0x21,0x7d,0x62,0xe9,0x76,0x2,0x39,0x49,0xa1,0xa0,0x51,0x95,0x6a,0x47,0x5a,0x73, + 0x7e,0xbc,0x46,0x6,0x2c,0x81,0x91,0x32,0x5f,0xa,0xbf,0xd7,0xa0,0x41,0x84,0x51, + 0x47,0x68,0xcb,0xa2,0x2b,0x91,0x30,0xd4,0xb1,0x14,0x56,0xe3,0x6c,0x85,0x91,0xa, + 0x25,0x79,0xf4,0x4b,0x32,0xe4,0x7,0x31,0xe7,0x68,0x1b,0x74,0x89,0xf0,0xff,0xda, + 0x95,0x9f,0x2e,0xec,0xf6,0x33,0xd,0x2,0x3e,0xcc,0xa,0xb9,0x71,0x21,0x6a,0xb9, + 0x37,0x15,0x50,0xa0,0xd,0x89,0xd1,0x42,0x87,0xf9,0xfb,0x25,0x72,0x17,0xb8,0xa3, + 0x22,0x10,0x2,0x9d,0xce,0x9d,0x21,0xe7,0x88,0x1,0x25,0x26,0x73,0xc6,0x66,0xe8, + 0x2e,0x11,0xc6,0x1,0xe9,0x3d,0xea,0xb3,0xea,0x70,0x38,0x9e,0x48,0xac,0x69,0x46, + 0x8e,0xd0,0xfd,0xf3,0x80,0xa4,0x2e,0xa2,0x23,0xf1,0x4a,0x26,0x44,0xa7,0xbc,0x5b, + 0xb6,0x6,0x21,0xc1,0xfa,0x74,0x64,0x13,0xe9,0x3e,0xa9,0x55,0x9e,0x76,0x90,0x32, + 0x83,0x86,0xc0,0xe4,0x3c,0x15,0xec,0x98,0x70,0x7e,0x6f,0x14,0x55,0xc9,0x4c,0xc7, + 0x5c,0xf1,0x33,0x21,0x40,0xfa,0x9,0x71,0xa,0xbb,0xf7,0xd1,0x4c,0x64,0x29,0xc8, + 0x4c,0xc9,0x92,0xcb,0xa8,0x6d,0x51,0x1a,0xeb,0xb1,0x14,0x81,0xd0,0x89,0x65,0x3b, + 0xc7,0x12,0x9c,0x3c,0xb,0x86,0x3c,0x29,0x71,0xe1,0xe5,0xda,0x87,0x5c,0xbf,0x5b, + 0xd4,0xdd,0xb5,0x59,0x8d,0xe,0x5a,0x90,0x1d,0x77,0xc0,0xc,0x67,0xf5,0x87,0x0, + 0x1c,0x92,0x10,0x97,0x40,0x89,0x1c,0x3c,0xa9,0xda,0xe3,0x88,0x8d,0x8b,0xe9,0xce, + 0x2f,0x63,0xaf,0x5c,0x39,0xe7,0x22,0x6a,0xb2,0xc1,0xe9,0xf3,0x37,0x86,0x82,0x4, + 0x1,0x2d,0xe0,0x3,0x24,0x5,0x61,0x80,0x77,0x98,0xca,0x3c,0x9c,0xb1,0x43,0x9a, + 0x69,0x26,0x85,0xda,0x13,0xce,0x50,0xc6,0x93,0x68,0x8d,0x85,0xf1,0xa9,0x33,0x28, + 0x86,0x95,0xa2,0x94,0xd4,0xae,0x9f,0xa9,0xcf,0x29,0x30,0xab,0x95,0x35,0xce,0x30, + 0x83,0xc7,0x36,0xeb,0x95,0x8e,0x72,0x4,0xa8,0xd0,0xaa,0xe2,0x40,0x62,0x3a,0xc1, + 0x79,0x8a,0x7e,0x41,0x90,0x9f,0x31,0x6b,0xc,0x9,0x17,0x1,0x9,0x18,0x1d,0x4b, + 0x80,0x6c,0x9,0x27,0xec,0x9c,0x56,0x30,0xa3,0x25,0xeb,0x3,0x83,0x99,0x61,0xdc, + 0x43,0xed,0x7a,0x42,0x81,0x8b,0x5,0xdf,0x25,0x3,0x1a,0xd5,0x7e,0x26,0xe1,0xc5, + 0x81,0x72,0x1e,0xc6,0xf7,0x66,0x88,0x17,0x90,0xe7,0xae,0x5c,0x8,0x64,0x8e,0x6, + 0x91,0xd1,0x9,0x22,0x8f,0xd0,0x62,0x9d,0xbd,0x70,0x4d,0x56,0x96,0x34,0x2,0x37, + 0x29,0xc1,0x66,0x9b,0x4e,0x42,0x4a,0x5e,0x58,0xe6,0xce,0x10,0x84,0xef,0xe0,0x1e, + 0x64,0xd,0x1e,0xc3,0xe8,0x33,0x49,0xa9,0x26,0x17,0x92,0x50,0xb0,0xd5,0x52,0x74, + 0x21,0x90,0x9c,0x18,0xee,0xf5,0xb8,0xb3,0xa1,0x11,0x4d,0xcf,0xf0,0x53,0xad,0xc, + 0x2b,0x6c,0x90,0x51,0xb8,0x3a,0x6d,0xfe,0xf0,0x19,0xb1,0xe9,0x9d,0x3b,0x66,0xae, + 0x78,0xb9,0xad,0x61,0xb9,0x39,0x78,0xa5,0xce,0xec,0x34,0xdb,0x48,0xd5,0x4d,0xaa, + 0xf2,0x3,0x84,0x5f,0x95,0x13,0xdb,0xc6,0x58,0x66,0xed,0x7,0x28,0x65,0xda,0xc8, + 0xa2,0xe,0x2f,0x4d,0x99,0xc4,0x5c,0x82,0xec,0xfe,0xd4,0x5b,0x22,0xb,0x5d,0x54, + 0x7f,0xe6,0x9d,0xa5,0x3b,0xa0,0x63,0x84,0x15,0x99,0x40,0x2a,0xc2,0x52,0xe0,0x55, + 0xea,0xe8,0xcb,0x57,0x26,0x6c,0x65,0x68,0xb9,0x14,0x86,0x2a,0xd0,0xe7,0xc0,0xc4, + 0x32,0x36,0x9,0x23,0xc,0x1c,0x60,0x3d,0x2e,0x45,0x45,0x9c,0xf9,0x7,0x58,0x6b, + 0x6c,0xe,0x94,0x43,0xad,0x75,0x40,0x2c,0xb1,0x75,0x6f,0xcc,0x90,0xd9,0x49,0xaa, + 0x32,0xad,0x47,0x1,0x7e,0x46,0x74,0x4d,0xd,0x1d,0xc6,0xeb,0x63,0x27,0x75,0xce, + 0xa3,0xb3,0xa5,0x4f,0x8,0x80,0x25,0x7c,0xc8,0xfc,0x6f,0x11,0xc6,0x50,0x48,0x1f, + 0x74,0x66,0x33,0x2a,0xa0,0x4a,0xc1,0xc1,0x9,0x90,0xb1,0x47,0x28,0xe8,0x14,0x42, + 0xb7,0xd9,0x36,0x1d,0x1a,0x36,0xe7,0x25,0x19,0x7d,0x69,0xd1,0x77,0x1a,0x97,0x28, + 0x9f,0x2,0x38,0x24,0x32,0xe5,0xe,0x71,0x16,0x22,0x87,0x1a,0x22,0x9f,0x8b,0x72, + 0xb4,0x29,0x71,0x1d,0xb8,0x34,0x51,0x40,0xee,0xc0,0x2b,0xdc,0x89,0x81,0x4,0x32, + 0x74,0xa3,0x98,0x5c,0x96,0xad,0x69,0xa9,0xca,0x9f,0xdf,0x6a,0x5f,0x64,0x84,0x17, + 0x1b,0x92,0xf,0x2f,0xd2,0x13,0xab,0x32,0xed,0x98,0xeb,0x6,0xc5,0xd1,0xda,0x73, + 0x89,0x43,0x71,0xb,0xa3,0x72,0x4c,0x4d,0xb3,0xed,0x8f,0xd4,0x55,0xf,0x28,0x11, + 0x43,0x3c,0x1a,0x63,0xc9,0x59,0x18,0xfd,0x1f,0x87,0xe1,0xa7,0xf7,0xe9,0x80,0xe9, + 0xfc,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/cusdrLogo2.png + 0x0,0x2,0x19,0x4c, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x1,0xf4,0x0,0x0,0x1,0x2c,0x8,0x6,0x0,0x0,0x0,0x35,0xbb,0x41,0xc8, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0, + 0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xb,0x13,0x0,0x0,0xb,0x13,0x1, + 0x0,0x9a,0x9c,0x18,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0x8,0x1d, + 0x13,0x34,0x23,0x21,0x3,0x1d,0x63,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x78, + 0xda,0x94,0xbd,0x5d,0xaf,0x6e,0x5d,0x76,0x14,0x36,0x6a,0xb1,0x85,0x72,0xc1,0x2f, + 0x89,0x88,0xb2,0x13,0x23,0x1b,0x84,0xed,0xc6,0xbe,0x23,0x88,0x3b,0x2e,0xa3,0x28, + 0x96,0x83,0x8c,0xe3,0xf0,0x61,0xc7,0x49,0x24,0x64,0x84,0xc2,0x47,0x42,0x1a,0x6c, + 0xec,0x10,0x1c,0x22,0x4,0x52,0x24,0xee,0x72,0x15,0x21,0xe4,0xbb,0xa4,0x3b,0xb4, + 0x90,0x4d,0x2,0xbd,0x7f,0xd1,0xae,0x5c,0xec,0xb5,0xe6,0xac,0xaa,0x31,0xe6,0x73, + 0x5e,0xda,0x6a,0xf7,0xfb,0x9e,0xf3,0x7c,0xac,0x67,0xad,0x39,0xe7,0x18,0xa3,0x46, + 0x8d,0x2a,0xd4,0x1f,0xfa,0xf7,0x7f,0x5c,0x55,0x55,0x44,0x15,0xaa,0x8a,0x25,0xff, + 0x61,0xad,0x3f,0x5c,0x7f,0x87,0x2a,0x70,0xff,0xb3,0xbd,0x1,0xfe,0x9e,0xf1,0x25, + 0xf7,0x1f,0x10,0xf2,0x1d,0xf9,0x5e,0xf9,0x73,0x40,0xde,0x3f,0xbc,0x56,0x3f,0x1f, + 0xf7,0x3f,0xd8,0x6f,0xe1,0xe1,0xf2,0x20,0x7f,0x7e,0xff,0x9e,0xf5,0x5d,0xf9,0x7b, + 0xab,0x8a,0x72,0x3d,0x25,0xff,0xfe,0x5c,0xef,0xcb,0x7b,0xa7,0xef,0x99,0x7e,0x77, + 0xbe,0x2f,0xff,0xf3,0xea,0xf7,0x3c,0xcf,0x3,0xfd,0xfe,0xe8,0xef,0xa9,0xfc,0x2d, + 0xfa,0x3e,0x7d,0x1b,0x87,0x7b,0x9e,0xcf,0xa6,0xe2,0xf9,0xca,0x9a,0xb0,0x7b,0x2b, + 0x9f,0x85,0xef,0xf0,0xcc,0xed,0x37,0xc6,0xf5,0x21,0xde,0xd3,0x3e,0x6b,0x78,0xae, + 0xd3,0x77,0xd9,0x3d,0xc1,0xe1,0x75,0xc3,0xfd,0xa8,0x58,0x67,0xf9,0x3d,0xf9,0xfb, + 0xd6,0xb5,0xe8,0xbd,0xe7,0xf0,0x78,0x87,0xcf,0x19,0x7f,0xe3,0xfd,0xec,0x9e,0xf, + 0x68,0x4b,0x69,0xb8,0x1f,0xdf,0xba,0xbf,0x35,0xdd,0x87,0x1a,0xf6,0x77,0xfc,0x2e, + 0xfb,0xce,0x57,0xf7,0xb4,0x6a,0xbe,0xd8,0x5c,0x87,0xb9,0xee,0xf2,0xdc,0x99,0xd6, + 0x6d,0x9e,0x3,0xf7,0xff,0x52,0xd6,0x5d,0xf1,0x70,0x6f,0xa6,0x6b,0xac,0xbe,0xcf, + 0x99,0xfb,0xfa,0x70,0xe6,0xe8,0xf5,0xd,0x47,0xe0,0xfe,0x3c,0x9e,0xbf,0x7b,0xdd, + 0xc7,0xbc,0xf6,0xe1,0xc,0xc8,0xb3,0x60,0xfd,0xbc,0xdc,0x33,0x7a,0x4d,0x98,0x7f, + 0x6b,0xae,0x6d,0x3d,0xaf,0xaa,0xfc,0x7e,0xca,0xb3,0xf9,0xfa,0xd7,0xf8,0xa1,0x79, + 0xee,0xca,0x3d,0xfc,0x7a,0x64,0x3c,0x3f,0x33,0xc,0x47,0x4,0xe,0xff,0x5b,0x2f, + 0x96,0xef,0xf8,0xe8,0xb9,0xef,0x8d,0xbe,0x99,0xba,0xdf,0x5e,0x1c,0x1b,0xcf,0x6f, + 0x1e,0x8e,0xf0,0xe3,0xad,0xad,0xf3,0xf6,0x6a,0xcb,0x2d,0x8e,0x70,0x7f,0x24,0xfd, + 0xc7,0x9f,0x3e,0x1f,0x55,0x75,0xd9,0x62,0x99,0x36,0xe1,0xba,0xe9,0xf0,0x7f,0x7, + 0xe6,0xa0,0x83,0x6f,0x1c,0x58,0xe4,0xbe,0x91,0x78,0xb5,0xc0,0x25,0x8,0x42,0xff, + 0xec,0xb9,0x56,0xdd,0xd8,0xec,0x8b,0xd2,0x9e,0x2e,0xea,0x9c,0xb4,0x4c,0xd7,0x29, + 0x9b,0xb9,0x24,0x50,0xd5,0xb3,0x29,0x39,0xdc,0x2b,0xca,0x81,0x4c,0xbf,0x87,0xa4, + 0x27,0x43,0xf6,0x14,0x38,0x7,0x26,0x7b,0x2e,0xc3,0x77,0x2,0xfb,0xf7,0x64,0xe2, + 0xd0,0x72,0x3,0x59,0x81,0x19,0x4b,0xf5,0xb3,0x29,0xbf,0x11,0xf1,0x9b,0xe2,0xf6, + 0x7c,0xfd,0x17,0xbe,0x39,0x2a,0x12,0xa2,0xb5,0x62,0x75,0x43,0xb1,0xdf,0x6b,0xfb, + 0x7e,0xfa,0x7d,0x2f,0xbd,0xf7,0xf7,0xe7,0x13,0x1e,0x5c,0xa,0x43,0x2e,0xf4,0x2a, + 0x40,0x4f,0x87,0xa9,0x5e,0xcb,0xf4,0xfc,0xee,0x3f,0xb7,0xe7,0x25,0x7f,0xa6,0x6b, + 0xfa,0x79,0x36,0xcf,0x73,0x42,0x4,0x49,0xbd,0x6f,0x79,0x28,0xaf,0x7b,0x28,0xcf, + 0xde,0xe,0x58,0xd9,0x8b,0x9c,0x12,0x18,0xb9,0x5f,0x9a,0x40,0xeb,0xb3,0x40,0xec, + 0x55,0xf0,0x74,0xdc,0xec,0xef,0xd6,0xc3,0x97,0xba,0xff,0x31,0xec,0x27,0xce,0x27, + 0x6c,0xee,0xeb,0xca,0xc0,0x25,0x67,0x2,0xe2,0xb3,0x9f,0xe0,0x93,0xc1,0x3c,0xaf, + 0x3,0x7a,0xce,0xa0,0x47,0x1,0xa0,0x9f,0x11,0x76,0x7f,0xf6,0x1e,0x40,0xae,0x41, + 0xc0,0x6f,0xab,0x5,0x51,0xfa,0x3d,0x27,0xbe,0x42,0x0,0xca,0xaf,0xb1,0x86,0x7d, + 0x74,0xff,0xe,0x70,0xba,0x57,0xe8,0xdb,0xc5,0xce,0xe7,0xfb,0x7b,0x34,0x9,0xb4, + 0x67,0xb,0x3b,0xf1,0x91,0x5,0x8c,0xbc,0xc,0x38,0xd5,0x14,0xfa,0x7e,0xec,0x63, + 0xf0,0xfe,0x66,0xbb,0xce,0x75,0xe4,0xfa,0x6f,0x25,0x7c,0xed,0x3,0xf2,0xfe,0xe7, + 0xad,0xf1,0x9e,0xfd,0x31,0x28,0xe8,0xdf,0x1,0x85,0x7b,0xdd,0xeb,0x73,0xc0,0xfd, + 0x7,0xeb,0x94,0x41,0x5e,0x5b,0x4,0x28,0xb9,0x37,0xc8,0x9b,0xfc,0x5c,0xe7,0x3e, + 0xec,0xfc,0xfb,0xec,0xf9,0xe9,0x1f,0x21,0xb6,0x33,0xf6,0xa7,0x40,0xff,0x1e,0x45, + 0x7d,0x7e,0xeb,0x77,0x96,0x5c,0x3f,0xda,0x11,0x7,0xdc,0xef,0x8b,0x25,0xf9,0xbc, + 0xee,0xf2,0x43,0x6c,0xd8,0xd8,0x96,0xd9,0x50,0xe,0xd5,0xc,0x3a,0xba,0x21,0xb8, + 0x7f,0x2d,0xa7,0x85,0x25,0x87,0xb3,0x1e,0xe0,0x80,0x1f,0x2e,0xcf,0x7b,0xc8,0x8, + 0x12,0x1a,0x68,0xe9,0x8b,0x97,0x18,0xe,0x82,0xf2,0x80,0x96,0x41,0x92,0x99,0xb1, + 0x4d,0xc5,0xc9,0x84,0x46,0x20,0xaa,0xd4,0xf2,0xec,0xb8,0xe2,0xde,0xe9,0x2,0x6b, + 0x49,0xc8,0x21,0x48,0xd9,0x7d,0xe4,0x39,0x41,0x1a,0x77,0x62,0x6,0x2f,0xf8,0xfb, + 0x5a,0x1e,0x43,0x7f,0x76,0xfa,0xdf,0x15,0x44,0xb9,0xf,0x75,0xb,0x74,0xe5,0xc1, + 0xe2,0x50,0x84,0xf8,0x1,0x7b,0x48,0x14,0x58,0xfd,0x99,0x25,0xa,0x83,0x3c,0x94, + 0x23,0x20,0x23,0x6e,0xa1,0xde,0x1b,0x66,0x22,0x26,0x1,0x38,0x2b,0xe1,0x4c,0x60, + 0x29,0xf7,0x64,0xfa,0x33,0xc6,0x3e,0x58,0xf7,0x2a,0x7e,0x4f,0xe9,0xe7,0xd2,0x7f, + 0xf3,0xa,0x10,0xfd,0x76,0xed,0xfb,0xc4,0x58,0x67,0xf5,0x15,0x80,0x80,0xe1,0xb0, + 0x91,0x24,0xa1,0xe0,0xb9,0x8,0xf4,0x50,0xcd,0x84,0xb,0xc3,0x3e,0x47,0xdc,0x1b, + 0xfd,0xdf,0x29,0xb1,0xf4,0xc4,0x6,0xa8,0x1e,0xb4,0x57,0xad,0x80,0x7d,0x30,0xaf, + 0xbd,0x8d,0x82,0x24,0x13,0xa0,0x7c,0x96,0xee,0x3f,0xbb,0x34,0xd,0xa6,0x71,0xea, + 0xb1,0xe2,0x7b,0xf5,0xb0,0x86,0x7d,0x36,0xd7,0x3f,0x1f,0x70,0x34,0xf4,0x0,0xa0, + 0x67,0x2,0xf5,0x0,0x67,0x5c,0x87,0x6,0xd3,0xc2,0x5d,0xa1,0x45,0x10,0x59,0x7b, + 0xe9,0xb2,0x24,0xed,0xeb,0xed,0x97,0xc5,0xfe,0x27,0x98,0x1,0x53,0x78,0xd9,0x1f, + 0x45,0x9,0xca,0x90,0xbf,0xdf,0xc7,0x74,0x6,0xcf,0x5a,0xff,0x8e,0x8,0xea,0x99, + 0xcb,0xc1,0x92,0x8f,0x1d,0x48,0x81,0x48,0xa6,0xa6,0x1c,0xb0,0x45,0x46,0xdc,0xd7, + 0xf5,0xf5,0x23,0x9,0xde,0xbf,0xdb,0x13,0x4c,0xca,0xd9,0xe5,0xb9,0x17,0x64,0xed, + 0xf4,0xa0,0x98,0x99,0xc,0xed,0xee,0xde,0xdf,0x7c,0x79,0xf8,0x62,0xed,0x60,0x5a, + 0x99,0x30,0xe8,0xe9,0x73,0x7,0x5d,0xe0,0xb9,0xf6,0x48,0x2c,0x9e,0xef,0xb3,0xa3, + 0x12,0x52,0xa3,0xed,0x67,0xc0,0xaf,0x4f,0x5a,0x7b,0x95,0xba,0x7e,0xe5,0xbf,0xbc, + 0xd7,0xeb,0x5b,0x83,0xf6,0xac,0x92,0x90,0x4c,0x17,0x87,0x6a,0xa0,0x55,0x56,0xa, + 0x2f,0xc5,0x29,0xdd,0xe0,0x58,0x9,0xc,0x25,0xef,0x81,0x1e,0xe2,0x53,0x10,0x92, + 0x0,0xc3,0xac,0x3e,0x27,0x98,0x31,0x70,0x8c,0x6,0x35,0xc5,0xe1,0x58,0x13,0x14, + 0x7d,0x80,0x7b,0xad,0x52,0x3e,0xc1,0xd0,0x7,0xb4,0x1,0x99,0x4,0x55,0x7c,0xd6, + 0x0,0xa3,0x9f,0xa0,0xe4,0xf1,0x8f,0xd0,0x21,0x3a,0x43,0x1a,0x70,0xa8,0x94,0xca, + 0xa1,0x3f,0xbd,0xa7,0xad,0xbd,0x11,0xc9,0xb,0xb3,0xe5,0x12,0xd5,0x25,0xa2,0x92, + 0xe7,0x80,0xc6,0x20,0xd0,0x94,0xfb,0x7e,0x7c,0xdd,0x4e,0x9c,0x93,0x14,0xc5,0xec, + 0x24,0x20,0x68,0x62,0xf5,0x75,0x50,0x33,0x4a,0x7,0x46,0x79,0xe2,0x6b,0xe8,0x81, + 0x17,0x81,0xe7,0x0,0x19,0xd0,0x90,0x96,0xa7,0x33,0x2a,0xe,0xc8,0xa7,0x7e,0x5d, + 0x27,0x2b,0xda,0x3a,0xb9,0xb9,0xed,0x7a,0xe3,0xfa,0x88,0x86,0xf2,0x2a,0x12,0x85, + 0x40,0x9f,0xc9,0xa1,0x73,0x3,0x8,0xc,0xfa,0x54,0x3e,0xfd,0xb6,0x30,0x72,0x74, + 0x4d,0x7e,0x9e,0x43,0x8d,0x51,0x11,0x42,0xe0,0xcd,0xe7,0xa8,0x85,0xec,0x5,0xc4, + 0xf6,0x86,0x7e,0x46,0x7b,0xb6,0xd7,0x7a,0x7e,0xab,0x3a,0x21,0x64,0x89,0x3c,0xc7, + 0x3e,0xe4,0xa0,0xe7,0x50,0x39,0x7d,0x3d,0x13,0xdc,0xfb,0x80,0xe5,0x49,0xb7,0x1d, + 0xea,0xe0,0xfd,0x14,0x6b,0x5,0x93,0xcc,0xf4,0xb1,0xe,0xeb,0xe7,0xb6,0x70,0xb8, + 0xf6,0xfb,0xb3,0x1,0x9,0x4f,0x12,0x58,0xee,0x7d,0xb6,0xe,0x6e,0x5f,0x41,0xf2, + 0xbf,0x2,0x59,0xdf,0xfb,0x81,0xb6,0x25,0xb1,0xc2,0x1b,0xf2,0x37,0xd1,0xef,0xd2, + 0x73,0x6d,0xb4,0x5a,0x2f,0x61,0xff,0x5a,0x55,0x30,0x25,0x26,0x30,0x7e,0xdf,0xfe, + 0xdd,0xb8,0x7f,0xa,0x6,0x98,0x1e,0xfa,0xb1,0x2b,0xa0,0x95,0xc0,0xcc,0xfb,0xb7, + 0x42,0xc2,0x7,0xd6,0x75,0x2c,0x60,0xa8,0xf8,0x75,0x5d,0x80,0xff,0x6a,0x5b,0xdf, + 0x90,0x30,0x82,0x7e,0x8c,0xf1,0xa9,0x9c,0x9f,0xfb,0xe8,0xb0,0xb,0xee,0xd,0xb0, + 0xbb,0x40,0x88,0xe3,0x10,0x9e,0xe7,0xca,0x42,0x5e,0xfb,0x16,0x91,0x52,0xe1,0x80, + 0x1b,0xc2,0x1,0x4c,0xdc,0x51,0x3e,0x9f,0xc,0xac,0x42,0xaf,0x2,0x68,0x61,0xac, + 0x57,0xe8,0x18,0x2,0x6e,0x2b,0x8,0x29,0x50,0x79,0xd,0x95,0xf4,0xd0,0x5f,0x46, + 0x54,0xf6,0x60,0xeb,0xaf,0x78,0x25,0x54,0xe7,0x1e,0x72,0xf6,0xaf,0x31,0x54,0x5f, + 0x5a,0xb9,0x0,0xbd,0x2a,0x69,0x3d,0x94,0x44,0x10,0xe2,0xb3,0x18,0x48,0x0,0x10, + 0x95,0x1d,0x7,0xb8,0x1c,0x56,0xb5,0x40,0xab,0x68,0xa2,0x37,0x79,0x40,0xcf,0xee, + 0x33,0xb1,0xd1,0xdf,0x6f,0x88,0x1,0xa4,0x8a,0x49,0x48,0x51,0x36,0x38,0x87,0x7b, + 0x1,0xf8,0xcf,0x46,0xc0,0x61,0x79,0x2b,0x30,0x5,0xd2,0xbc,0xb7,0x88,0xa,0x71, + 0xff,0x1e,0x64,0xa5,0xac,0x95,0x25,0x12,0x56,0xc7,0xb0,0x14,0xee,0x8a,0x89,0x43, + 0xfb,0x5,0x9,0x33,0x3b,0xbc,0xa5,0xaf,0xb7,0x6c,0x99,0x30,0x78,0x10,0x4c,0xa8, + 0x7a,0x1f,0x62,0x18,0x70,0x4f,0xcd,0xa4,0x75,0x1d,0x1,0x18,0xe0,0x43,0x48,0xa1, + 0xfd,0xf5,0xf7,0x40,0x56,0x9b,0x68,0xb9,0xd9,0xfe,0xee,0xe7,0xa,0x2e,0xc9,0x69, + 0xbd,0x7c,0x24,0x2,0x1d,0xba,0xaf,0x8f,0x52,0xd,0x5b,0x25,0x26,0x9,0xde,0xe, + 0xb0,0xfa,0xdb,0x64,0x8b,0x5c,0xfe,0x5b,0xbd,0x6d,0xa9,0x6b,0xe,0xf6,0x67,0x5c, + 0xbf,0x20,0x2,0x36,0xf6,0xf5,0xc1,0xa1,0x94,0xfb,0xbd,0xf0,0xf7,0xdd,0xf7,0x6b, + 0x2f,0x7f,0x2e,0x44,0xe1,0x39,0xc4,0x1,0xca,0x6b,0xbc,0xda,0x65,0x4,0xfc,0x7d, + 0x0,0xd3,0xe1,0xd5,0xe7,0xb0,0x5e,0xff,0xeb,0xeb,0x1a,0x82,0x44,0xb0,0xb2,0x2a, + 0x7f,0xee,0x11,0x1a,0xda,0x1,0xab,0x8c,0xf7,0x81,0xcc,0xfc,0xed,0xab,0x12,0x94, + 0xbb,0xa1,0xf7,0xea,0xe9,0x5d,0x13,0x52,0x85,0xc6,0x7d,0xb3,0xea,0x15,0x92,0xb8, + 0xc4,0xef,0xc2,0xe,0xa0,0x9a,0x68,0x3f,0x48,0x1,0x9f,0x7b,0xcf,0x6b,0x57,0xe9, + 0xc3,0x96,0x53,0x48,0x99,0x59,0xd5,0x3f,0xeb,0x4f,0x8e,0x7c,0xb2,0x1c,0x82,0x5e, + 0xaf,0x87,0x3c,0xcb,0xb2,0x24,0xd1,0xea,0xe0,0x1,0x98,0x51,0x70,0x17,0xa5,0x9f, + 0xab,0xf8,0x3b,0xbc,0x8b,0xa1,0x49,0x43,0xec,0xb5,0xe7,0xbd,0x9a,0x84,0xe8,0xde, + 0x2,0x3b,0x4a,0x4b,0x85,0xef,0x5b,0xbb,0xb0,0x56,0xca,0x86,0x44,0xf7,0x4,0x25, + 0xdb,0xbf,0x52,0xce,0x4c,0x79,0xbe,0x5c,0xff,0x3f,0x90,0x86,0xfb,0x1d,0x97,0x55, + 0x99,0x46,0x58,0x88,0xa,0x96,0x1d,0xd1,0x5c,0xff,0x42,0x81,0x1,0x9,0xf,0x8e, + 0x3c,0x54,0x78,0x1c,0xfa,0xc1,0xeb,0x23,0x31,0x43,0xa5,0xad,0xd9,0x73,0xf7,0xba, + 0x10,0xd0,0x77,0x42,0xee,0xad,0xf7,0xb9,0xab,0x55,0xb4,0x2a,0x17,0x91,0x63,0xa0, + 0x41,0xee,0xc0,0x1c,0xb8,0x40,0x39,0x78,0xa5,0x5f,0xb3,0xf,0x5e,0x58,0x45,0xe2, + 0xc1,0x59,0xcf,0xb9,0x1,0xc2,0xcb,0xe0,0xaa,0x8b,0x4b,0x36,0x81,0x17,0xfb,0x68, + 0x68,0x72,0xe7,0x29,0xf5,0x4c,0x90,0x52,0xe5,0xe9,0x93,0x46,0xc0,0x61,0xbb,0x4a, + 0xcb,0x3e,0x1f,0xac,0xfb,0x34,0xf2,0x13,0x2a,0xa1,0x23,0xef,0xcd,0xef,0xdf,0xa4, + 0x3d,0xae,0x80,0x5a,0x23,0x14,0xc0,0x72,0x35,0x48,0xcd,0xe3,0xaf,0xca,0xdf,0xba, + 0xb6,0x10,0xfc,0x5a,0x1d,0xf4,0xcb,0xbf,0xdf,0x15,0x5f,0x5d,0xde,0x87,0xdb,0x21, + 0x4c,0xe1,0x53,0x46,0x55,0x2b,0x15,0x47,0xc1,0x10,0x71,0x64,0xdf,0x55,0x2,0xf6, + 0x57,0xd0,0xf2,0xdf,0xc6,0xe8,0xcd,0x69,0xf0,0x64,0xd0,0x5d,0x30,0xc0,0xcd,0x18, + 0x8,0x38,0xda,0xc7,0x7b,0xe,0x30,0x92,0x12,0xb2,0xb1,0xd6,0x29,0x2c,0x1,0xa0, + 0x7c,0xb4,0x6,0x1b,0xf,0x2e,0x4c,0x80,0x2a,0x2,0x1b,0x6a,0xe8,0x1e,0xd0,0x7b, + 0xc6,0xc4,0xfe,0xef,0xb3,0xf7,0x29,0xbf,0x1d,0x79,0x64,0xc8,0x7d,0x22,0x34,0x51, + 0xc2,0x8,0xb8,0x34,0x9a,0x80,0x42,0xf0,0xc8,0x9a,0x1d,0x76,0xdc,0x71,0x25,0x76, + 0xb5,0xaa,0xd7,0xf5,0xcf,0x12,0xa0,0xb3,0xbf,0xee,0xdd,0x43,0x49,0xc,0x57,0x55, + 0xbb,0x13,0x5e,0xea,0x77,0x1b,0x88,0xa,0x43,0x6c,0x10,0xad,0x3,0x18,0xdd,0x23, + 0x12,0x56,0x39,0x53,0x0,0xb6,0x1d,0x46,0xf6,0x56,0xc5,0xa,0x3f,0xf4,0x5f,0x81, + 0x95,0x98,0x50,0x60,0x66,0x3f,0x57,0x1e,0xe4,0xad,0x15,0x6d,0x6d,0x47,0x25,0xcc, + 0x9c,0xc4,0xb1,0x84,0xe9,0xe5,0xf5,0x97,0x20,0xc4,0xfa,0x1a,0x3d,0x5b,0xac,0x5d, + 0xc1,0xf1,0xde,0x65,0xf2,0x56,0x96,0x4,0x63,0xe8,0x34,0xc9,0xde,0xbf,0xf6,0xde, + 0xf3,0xc4,0x3e,0x8,0xbf,0xc3,0xbd,0xd5,0x73,0x3,0x96,0xa8,0x46,0x82,0x83,0xaa, + 0xb7,0x8a,0xec,0xa9,0x73,0xc6,0xd0,0xfb,0xba,0xab,0x5f,0x81,0x11,0x22,0x43,0x64, + 0x2c,0xd,0x6e,0x3d,0xf6,0x4d,0x36,0x94,0xf6,0x54,0xf4,0x50,0x68,0x8c,0x1,0x8, + 0xe8,0x1,0x8a,0x7b,0xb1,0x9,0xf4,0x6f,0xd9,0x9e,0x1c,0x66,0x94,0x9e,0x26,0x23, + 0x12,0x7c,0xbd,0xf6,0xd2,0xee,0xc5,0x82,0xcb,0x56,0xc5,0xb0,0x98,0x9e,0x6c,0x7, + 0xeb,0xdc,0xbb,0x4e,0x18,0xcd,0x39,0x53,0x23,0x8c,0x35,0x31,0x9b,0xf5,0xe8,0x45, + 0x7,0xdf,0x57,0x68,0xc8,0x40,0xa5,0xdf,0x10,0x30,0xab,0xc1,0x95,0xfa,0x54,0x31, + 0xac,0x83,0x5,0x3b,0xb,0xeb,0x33,0xae,0xff,0xeb,0x6f,0xbd,0xbf,0x85,0xcb,0xa1, + 0x7c,0x85,0x93,0x8d,0x28,0x2d,0x89,0x4d,0x83,0x53,0x49,0x83,0x66,0x41,0x9f,0xbe, + 0x78,0xa0,0xd4,0x5,0x97,0x45,0x7d,0xbb,0xef,0xd5,0x5e,0x54,0x9,0xd0,0x90,0xde, + 0x67,0xa4,0xb4,0x29,0xa0,0xd5,0x14,0x76,0x86,0xe,0x96,0x41,0xcb,0xf,0x44,0x4e, + 0x62,0x20,0x19,0x79,0x6b,0x3,0x72,0x30,0x5b,0x2,0x49,0xa9,0x72,0xe8,0x70,0x21, + 0xa3,0xa9,0x8b,0x8d,0x45,0x1a,0x18,0xd6,0xe0,0xbc,0x42,0x4b,0x28,0xb4,0x4b,0xb1, + 0xf6,0x9d,0x2d,0x9e,0x80,0x16,0x83,0x5c,0xaa,0xeb,0x6,0xd1,0x9f,0x64,0xd,0x40, + 0x4d,0xae,0x49,0x8,0x14,0xce,0xcd,0x3,0x70,0x6,0x6f,0xe7,0x18,0x28,0xad,0x67, + 0xad,0xf9,0x5,0xa3,0xd2,0xde,0x56,0x70,0x88,0x7c,0x27,0x9c,0x6c,0xbc,0x57,0x3f, + 0xab,0x5,0xbc,0x95,0x36,0x18,0xd,0x83,0xd8,0xd5,0x30,0x6c,0x85,0xc5,0x77,0x36, + 0xb4,0x26,0x76,0x2c,0x22,0x10,0x82,0x16,0xe,0x3d,0x46,0xcc,0x69,0xaa,0xb6,0x9, + 0xfc,0xbb,0xf7,0xa2,0xa0,0x75,0xb3,0xfc,0x4c,0x58,0x7b,0x8,0xf5,0x85,0x28,0xe6, + 0xa4,0x92,0x77,0x3e,0xe4,0xd6,0xee,0x27,0xda,0x10,0x44,0x70,0xaf,0x71,0xfa,0x1a, + 0x6c,0x49,0x44,0xe,0x46,0x3d,0x7b,0xcc,0x2,0x13,0x5b,0x40,0x5,0xf3,0xc0,0x1a, + 0x20,0xf6,0x86,0x79,0x4b,0x45,0x6c,0x44,0xe9,0x3c,0x94,0x31,0x9c,0xcb,0x35,0x12, + 0xf5,0xa3,0x7f,0x54,0xc5,0xeb,0x38,0x5c,0x91,0xa0,0x9e,0xa1,0xb6,0x13,0x55,0x4a, + 0xd7,0x36,0xe2,0x2,0x48,0x79,0x30,0xb8,0x3,0x3a,0x6,0x36,0x22,0x39,0x4c,0x64, + 0x41,0xb7,0x50,0x64,0xa7,0xdc,0x30,0x45,0x84,0x8,0x4c,0x4,0xf3,0xfc,0xf7,0xeb, + 0x39,0x54,0x3c,0xe0,0xd9,0xd2,0xc6,0x90,0x97,0x49,0x45,0xb6,0xfa,0x5e,0x31,0xba, + 0xc1,0x9a,0x89,0x6e,0x9a,0x41,0xb2,0xe6,0xfe,0x3f,0xef,0x5,0xce,0xb5,0xe8,0x9f, + 0x2a,0x9e,0x1,0x2b,0xd6,0x14,0x16,0x25,0x28,0xdd,0xef,0x80,0xb2,0x68,0x9f,0xca, + 0x8c,0x2,0xcb,0x70,0x57,0x76,0xda,0x87,0xe4,0xbe,0xd7,0xc9,0xd5,0xdb,0x13,0x63, + 0x7b,0x95,0x41,0xc6,0xbd,0xc,0x4a,0xa6,0x1f,0x1c,0x24,0x56,0x8f,0xc,0xc1,0x5e, + 0x45,0xb4,0x5b,0xa8,0xe8,0xc3,0xfa,0x78,0xae,0xe4,0xa,0xd4,0xea,0xda,0x3b,0x33, + 0x59,0x89,0xc5,0xa3,0xdc,0x9f,0x6d,0x44,0x2e,0x39,0xf0,0x34,0xb6,0x71,0x27,0x74, + 0x23,0xf4,0xb,0x39,0xc,0x99,0xc7,0x39,0x2,0x0,0xdf,0xcf,0x74,0x77,0x50,0x20, + 0xfd,0xeb,0x24,0x7d,0x7b,0xd2,0xc8,0x3c,0x54,0xaa,0xbe,0x80,0x2f,0x4,0x27,0xa0, + 0x60,0xd0,0xdd,0x94,0xd6,0xee,0x9c,0x17,0xd2,0x67,0x67,0x1,0x97,0x40,0xaf,0x1a, + 0x88,0xd0,0x47,0x35,0xe3,0xb0,0x76,0x14,0xac,0x5d,0xb0,0xe5,0xd9,0x18,0x98,0xd4, + 0x2d,0x7,0xbf,0xd7,0x17,0x15,0x81,0x41,0xef,0x19,0xa3,0xf5,0xb1,0x25,0xc0,0xb0, + 0x4f,0x20,0x0,0xfe,0x5e,0x47,0xe8,0x86,0x56,0x1c,0x7c,0x97,0x31,0xc6,0x8b,0xa, + 0xde,0x23,0xa6,0x62,0x11,0x43,0x7f,0x13,0x36,0x66,0x28,0x21,0x1b,0x3a,0xd1,0xa, + 0xa7,0xb7,0x44,0xff,0x99,0x8a,0x0,0x4d,0x63,0x6a,0xb8,0x51,0xe,0x20,0x26,0x49, + 0xb3,0x9a,0x42,0x8c,0x3d,0xe,0xd9,0x7f,0x4e,0x8b,0xb1,0x57,0x73,0xd9,0x5a,0x84, + 0xd1,0x68,0xd0,0x2,0x7,0x30,0x40,0x13,0x35,0xd,0x23,0x5d,0x92,0x1c,0x65,0x12, + 0x38,0xa1,0x6f,0x7b,0xed,0x76,0xa,0xa,0xe2,0x1c,0x9,0x40,0xd5,0xce,0x6d,0x9c, + 0xd7,0xb5,0x71,0x68,0x78,0x1c,0xa8,0x6e,0xd,0x6c,0xb0,0xb5,0x48,0xed,0x60,0x6a, + 0xe0,0x72,0x70,0xba,0x90,0xc4,0xf1,0x32,0x2,0x39,0x84,0xb7,0xc1,0xa9,0x40,0xe3, + 0xbc,0xbf,0xf6,0x9,0x45,0x69,0xf1,0x64,0xc,0x66,0x2c,0x9,0xd6,0x5b,0xd4,0x16, + 0xbd,0x2a,0x5d,0xcc,0x3a,0x8e,0xc,0x1b,0x92,0xc1,0x7b,0x42,0x9f,0x65,0xbe,0x37, + 0x31,0xa3,0xf4,0xcb,0xd1,0xef,0xb6,0xc9,0xee,0xef,0xa1,0xcc,0x31,0xc2,0x4b,0x5a, + 0xef,0xab,0xa2,0x7c,0xe3,0x6a,0xf5,0x9c,0xed,0x5b,0xcb,0xa9,0xd1,0xfb,0x2a,0xb6, + 0x46,0x9e,0x4a,0x4c,0x9,0x2e,0x90,0xf5,0xe3,0x87,0x75,0x3,0x11,0x65,0x3e,0xb4, + 0xf5,0x64,0x94,0xb2,0xd3,0x36,0x37,0xfa,0x28,0x6a,0x3f,0x23,0x6c,0xc1,0x67,0x32, + 0xa1,0x9f,0xd1,0x27,0x90,0xa4,0xc7,0x2a,0x23,0x2f,0xce,0x77,0xdb,0xcf,0x3b,0x89, + 0x19,0x5f,0x90,0xf3,0x25,0x93,0x8d,0x6c,0x77,0x7e,0x11,0xda,0x1e,0xe2,0xf,0x37, + 0xf3,0x13,0x36,0x65,0x3,0xb,0x24,0xda,0x42,0xd8,0xf4,0xa,0x7c,0x55,0xea,0x16, + 0x5c,0x6b,0x80,0xca,0x1c,0xc2,0x72,0x20,0x2e,0xc6,0xb9,0x22,0x70,0x6b,0x75,0xc6, + 0x40,0x55,0x0,0x44,0x95,0xd6,0x5a,0xf7,0xab,0xc7,0xb5,0xa0,0x3e,0x32,0xd9,0x33, + 0x9d,0x80,0xd5,0xe8,0x8e,0x6c,0x41,0x16,0x99,0xde,0x26,0xab,0xe6,0xd2,0xa,0x6, + 0x27,0xae,0x5d,0xfb,0x7e,0xb4,0xd3,0x4e,0xda,0x4a,0x6c,0xd8,0x46,0x63,0x14,0xd0, + 0x50,0x93,0x7e,0xa5,0x95,0x7d,0xc8,0xc6,0x3f,0xd,0x56,0x7d,0x83,0x8,0xd1,0xe, + 0x56,0xe4,0x8f,0x1b,0x3e,0xbf,0x6,0x4,0x48,0x9a,0xd4,0xd5,0xe7,0xba,0xfb,0x94, + 0x4a,0x9e,0xf1,0xe0,0x9,0xb9,0xac,0x2,0xaf,0xfb,0x20,0xd6,0xc0,0x71,0x65,0xd6, + 0xea,0xfd,0xd5,0x72,0xce,0xd2,0x54,0x1,0x2a,0x57,0xa6,0xcb,0x7f,0x40,0x90,0x82, + 0x1d,0x60,0x16,0xba,0x64,0x5,0x8e,0x93,0x2d,0x47,0x62,0xb0,0x20,0x11,0x6d,0x9c, + 0xbd,0x2a,0x26,0x84,0xfc,0x41,0x39,0x3,0x9b,0xd,0xe9,0x49,0x24,0x81,0x39,0x22, + 0x8a,0x8,0xc3,0xd1,0x4f,0xa6,0xa6,0x85,0xa3,0x64,0x81,0x4f,0x4e,0x3c,0x44,0x3d, + 0xc4,0x74,0x27,0xa4,0xa4,0xee,0x89,0xfe,0x94,0x90,0xec,0x64,0x93,0x41,0xf6,0xd5, + 0x76,0x47,0xa3,0x4b,0xae,0x1,0xad,0xa9,0xca,0x97,0x8,0x5,0x4a,0xc,0xf3,0x82, + 0xf9,0x41,0x2d,0x17,0x7a,0x29,0xe7,0x1e,0xd9,0x3f,0xb3,0x50,0xf5,0xb6,0xd7,0x30, + 0x5b,0x6f,0xc6,0x82,0x41,0xed,0xa,0x95,0x88,0x90,0xc9,0x80,0xd7,0x15,0xf,0xe4, + 0xa6,0xdc,0xb7,0xc9,0xa1,0x29,0x3b,0xb4,0xb5,0x7e,0x7,0x8b,0xc6,0xba,0xc4,0xc, + 0x5f,0xcb,0x35,0x7a,0xa6,0x3e,0xb7,0x8f,0xad,0x8a,0x5c,0xe8,0x80,0xdc,0xd4,0xa7, + 0x72,0x65,0xd,0x64,0x33,0x38,0xfb,0x15,0x68,0x63,0xd0,0x1b,0xda,0x82,0x43,0x68, + 0x2,0x2d,0x7a,0xdf,0x95,0xe,0x91,0x46,0xb5,0x45,0xab,0x3e,0x3,0x6a,0x46,0xcf, + 0xdc,0x1a,0xc3,0x37,0x2,0xa7,0x1,0x60,0xca,0xb4,0x8d,0xac,0x81,0xf0,0x4e,0xab, + 0xd7,0x3c,0xc2,0x1c,0xae,0xa8,0x9a,0x93,0x80,0x94,0xa8,0x83,0xcd,0xaa,0x57,0x10, + 0x8d,0x68,0x55,0x52,0x19,0x41,0xa8,0x56,0x0,0x4b,0x6e,0xb0,0x26,0x42,0x4d,0x7b, + 0x62,0xa4,0x6c,0x77,0xa6,0xea,0x9a,0xb,0x5e,0x2d,0x2,0x27,0xe3,0xa1,0xe,0xa9, + 0xbf,0x21,0x23,0xc3,0xeb,0xc7,0x80,0xd6,0x5a,0xec,0xb,0xa6,0x2c,0xd6,0x3c,0xef, + 0x8d,0xfe,0x1d,0x5f,0x7f,0x77,0x79,0x4b,0x66,0xd2,0x31,0xba,0xff,0xf2,0x9a,0x44, + 0x3c,0x4e,0x7,0x1b,0xbf,0x82,0x53,0xab,0xfc,0xd9,0xb8,0x42,0x7e,0x64,0xb1,0x3c, + 0xf9,0x68,0x63,0x8b,0x27,0x5d,0x88,0xc8,0x2a,0x27,0x61,0x1c,0xad,0x8c,0x30,0x40, + 0x93,0xd3,0x7d,0x22,0x87,0xaf,0x1c,0xa2,0x35,0xb4,0x52,0x72,0xdc,0x80,0x49,0x12, + 0xae,0x1c,0x4d,0xe2,0x30,0xa9,0x82,0xc5,0x6,0x57,0x16,0x76,0xad,0xa0,0xbb,0x7b, + 0xf0,0x56,0x8c,0xc7,0x73,0x69,0x83,0x37,0x60,0xfc,0x3b,0x5a,0xa1,0xe4,0xed,0x41, + 0x9,0x4a,0xda,0x8a,0x88,0x11,0x30,0x94,0x9f,0x85,0x8c,0xfb,0xd8,0xa6,0x2a,0xda, + 0xf2,0xc6,0xb0,0x94,0x58,0x99,0x5a,0x67,0xab,0xa2,0x9d,0xa5,0xd1,0x66,0x92,0xa5, + 0xd8,0xb7,0x5f,0x16,0x53,0xcf,0x3c,0x3a,0x5d,0xcb,0x6c,0x5,0x48,0x45,0x5b,0x64, + 0x2a,0x83,0xe5,0xfb,0x6e,0x1f,0x4f,0xc3,0x3c,0xbf,0x8a,0xcd,0xd4,0xe6,0x8,0xa4, + 0x2e,0x52,0x7c,0x64,0xe8,0xdb,0xe4,0xba,0x82,0xd3,0xcc,0xc,0x35,0x65,0xd3,0x5d, + 0xda,0xf5,0xd6,0xd7,0x3f,0x5c,0x5f,0x17,0x77,0x15,0x78,0xad,0x7,0xe7,0x54,0x4, + 0x4,0x3f,0x7,0x6d,0x4,0x56,0x89,0x27,0x28,0x18,0xd3,0xf4,0x21,0x86,0x30,0x99, + 0xcd,0x71,0x10,0x33,0xc7,0x8d,0x57,0x25,0xa2,0xa4,0x37,0x48,0xc6,0x23,0x63,0xe, + 0x89,0xa2,0x4,0x73,0x13,0xc1,0xc,0x6b,0xd5,0x15,0x64,0x1,0xeb,0x98,0x71,0x5, + 0xa9,0x2c,0x72,0x69,0x44,0xb5,0xa7,0x5c,0x44,0xe3,0x89,0xdd,0x9c,0x3,0x22,0xd8, + 0xef,0xa5,0x50,0xa,0x8d,0x64,0xc4,0x60,0x2f,0x96,0x41,0x9c,0xc3,0x81,0x1e,0xc, + 0x65,0x9f,0x51,0xac,0xca,0x3b,0xee,0x7c,0xbb,0x10,0x57,0xc0,0xdc,0x17,0xf5,0xd9, + 0x58,0x38,0x94,0xbc,0x44,0x12,0xd8,0xb3,0xb4,0x81,0x1d,0xf,0xfd,0xa8,0x10,0x56, + 0xd8,0xec,0x57,0x44,0xa5,0x9a,0xf3,0xc4,0x68,0x90,0xf0,0xea,0x6d,0x23,0xe0,0xd4, + 0x69,0xa6,0x1a,0x18,0x49,0xfb,0x8e,0x2e,0x5d,0x4e,0xdc,0xc8,0xd7,0x1a,0xa,0x15, + 0x3d,0x44,0x56,0x17,0xe1,0x41,0x10,0x3b,0x9b,0x8,0xc,0x7a,0xdf,0x94,0x3,0x21, + 0x94,0xfd,0xde,0xb7,0xf9,0xfb,0x3,0xe1,0xd0,0x98,0xb5,0x3,0xfd,0x66,0x9c,0xbc, + 0x26,0x6b,0x18,0x3c,0x36,0xb6,0x2f,0x52,0xd5,0x4a,0x27,0x17,0x84,0xa5,0xbd,0x18, + 0xeb,0x94,0xbd,0x9a,0x82,0x51,0x31,0xbf,0xbe,0x13,0xcf,0x1a,0x7a,0x4,0xce,0x44, + 0x77,0xf2,0xe3,0xa0,0x6b,0xa1,0x67,0x4c,0x26,0xbe,0x39,0x97,0xae,0xbf,0xb,0x74, + 0x32,0x2d,0x90,0x35,0x52,0x67,0xe3,0xc9,0xc2,0x44,0xf9,0x14,0x9,0x64,0xde,0x1d, + 0xad,0x8d,0x70,0x28,0x1a,0x23,0x79,0x52,0xce,0x2,0x1a,0xff,0xc5,0x99,0xe3,0x29, + 0x7b,0xb2,0xcf,0xb7,0xc3,0x24,0x7,0x76,0x92,0x80,0x89,0xc3,0x6b,0x4b,0x18,0x73, + 0x67,0x64,0x5d,0xd5,0xd5,0xce,0x5,0x8,0xc7,0x8f,0x75,0x6d,0x76,0x3d,0xc6,0x7a, + 0xc0,0xda,0xb6,0x1c,0xaa,0x69,0xd8,0x3c,0x8,0x36,0xaa,0xc6,0x98,0x62,0x1d,0x18, + 0xf3,0x8b,0x85,0x4e,0x8f,0x17,0x26,0x1f,0x0,0xda,0xb7,0x7c,0xc9,0x70,0x8,0xa1, + 0x6e,0x38,0x4e,0x7c,0x12,0x25,0x34,0x19,0xca,0x49,0x48,0x30,0xcd,0xf,0x84,0x10, + 0xe,0x9d,0x48,0x19,0x49,0xc4,0x42,0x92,0xf1,0xf6,0x47,0x7f,0xfc,0x82,0x2,0xdd, + 0xd2,0x8c,0xec,0x5b,0x2a,0x1,0x1c,0xa3,0xcc,0x64,0x64,0xc8,0x4d,0x2,0xd2,0xc5, + 0x5d,0x28,0x44,0x8a,0xa,0xc8,0x7d,0x66,0xc,0x44,0xa6,0x9c,0xa4,0x88,0xe2,0x41, + 0xe,0xf4,0x95,0x1e,0xdf,0xd4,0xaf,0x83,0xdc,0x3,0x51,0x5c,0x1a,0xe,0xb9,0xfe, + 0x7e,0x47,0xb8,0x66,0x25,0xa6,0x49,0x2e,0x34,0xfa,0x47,0x83,0xb4,0x64,0x4e,0x1a, + 0x36,0x28,0x36,0xc9,0x45,0x89,0xe8,0x4d,0xdf,0x27,0xf0,0x20,0x53,0xaa,0xb3,0x55, + 0x22,0x7c,0xad,0x24,0x2a,0xdf,0xdd,0x6e,0x57,0x8e,0xed,0xf1,0x86,0xa0,0xb4,0xb, + 0x2b,0x3,0xd1,0x30,0xbe,0x42,0x90,0xcc,0x10,0xbf,0x83,0xfa,0xb9,0x41,0x52,0x8c, + 0x9e,0x57,0xb6,0x9,0xb4,0x1,0xd5,0x3e,0xcb,0x68,0x51,0x4e,0x9a,0xe2,0x20,0x7f, + 0xd0,0x24,0x6b,0x5f,0x11,0x20,0xa7,0x85,0xf3,0x6a,0x79,0x4a,0xc5,0x1a,0xa9,0x94, + 0x71,0x3c,0xa6,0x7f,0x4f,0x45,0x67,0xe5,0xb7,0xf3,0xb8,0x37,0x7c,0x2f,0x8d,0x5b, + 0x5c,0x5b,0x29,0xc1,0xf1,0x61,0x20,0x12,0xac,0xfa,0x4e,0x7b,0xb0,0x9f,0x37,0xcf, + 0xda,0xf8,0xe,0x5b,0xd7,0x5a,0x59,0xe,0xdd,0x4e,0x17,0xc1,0xe9,0xbd,0xdc,0x30, + 0x2e,0x6,0xe1,0xc8,0xfc,0x67,0xb6,0x3d,0x3a,0xa1,0x89,0x4e,0xc6,0x4b,0x4e,0x84, + 0x7f,0x2e,0xa2,0x62,0x8f,0x33,0x72,0xbd,0x86,0x86,0xe,0x3a,0xfd,0x0,0xab,0x3d, + 0x4a,0x42,0xb8,0x35,0x73,0x2b,0xc6,0xc9,0x94,0x8c,0x1a,0x9a,0x83,0x5c,0x3,0x82, + 0xc4,0x2a,0x82,0x40,0x15,0x8a,0xbc,0xb2,0xaf,0xc,0x84,0xa,0xed,0x8b,0x87,0x6f, + 0x40,0x8d,0x1d,0x60,0x9b,0x23,0xb7,0xb3,0x59,0xd1,0x4f,0x8d,0x29,0x86,0x2b,0x6, + 0x57,0x8d,0x3,0xb8,0x52,0x35,0x2f,0xc,0xf8,0x9,0x31,0xb5,0xcc,0x26,0xc5,0xda, + 0x69,0x75,0xbd,0x52,0xb3,0xad,0x57,0xa8,0xf2,0x8b,0x48,0x6,0xbc,0xfd,0x7,0x3f, + 0xfe,0xa6,0x56,0xee,0x69,0xb7,0x1c,0x37,0x63,0xea,0xbf,0x1f,0x36,0xec,0xab,0x20, + 0x30,0x9d,0x18,0xa7,0x83,0x3b,0x21,0xb3,0x97,0x92,0xc9,0x18,0xc6,0xe1,0x7c,0x2e, + 0x7c,0xd2,0x29,0x5e,0x7,0xfc,0x44,0x73,0x6c,0x52,0xa4,0xd3,0x63,0xed,0xac,0x5b, + 0x3b,0x6c,0x39,0x11,0x55,0xe6,0x80,0xd2,0x55,0xd,0x86,0xb9,0x7a,0x9,0xb8,0x90, + 0x76,0x82,0x77,0x8e,0xa4,0x27,0x5d,0x15,0xaf,0x1b,0x8,0x1e,0xa0,0x6f,0xea,0xef, + 0xf4,0x30,0x7b,0x90,0xd1,0x23,0xa2,0x82,0xcf,0xcb,0xc3,0x7b,0x12,0x1b,0xf1,0x20, + 0xe6,0xa3,0x5f,0xd3,0xb4,0xa3,0xea,0x16,0x9d,0x96,0x6d,0x45,0xce,0xb4,0xee,0xdd, + 0x77,0x58,0xee,0xaa,0x55,0x8d,0x43,0x3e,0x35,0xd9,0x4,0x14,0xcf,0x21,0x7c,0x56, + 0xfe,0xf,0x32,0x4c,0x6,0x94,0xe4,0xa4,0x60,0x68,0x69,0xa6,0x4,0x82,0x36,0x6b, + 0x2c,0xc7,0xde,0xb0,0x39,0xcb,0x55,0xb7,0xfc,0x7c,0xbb,0xfb,0xa2,0x2c,0x13,0x78, + 0x49,0x89,0x76,0xa3,0x2b,0x3d,0x87,0xf2,0x13,0x64,0x87,0xad,0x44,0x63,0xc1,0x2b, + 0xfb,0x99,0xdd,0x8a,0xe1,0xd1,0x7b,0xb0,0xe0,0xe9,0xf,0x74,0x4f,0xb9,0x30,0xa4, + 0x46,0xe5,0x78,0xa6,0xac,0xb7,0xb5,0xbd,0x28,0xd0,0xaf,0xee,0x37,0x6e,0xf8,0x96, + 0x1b,0x89,0xc3,0x14,0xf8,0xd6,0xe7,0xef,0x49,0x8b,0x36,0xf,0x30,0x9c,0xda,0x34, + 0x5c,0x70,0x6e,0x25,0xb1,0x8e,0x4e,0x18,0x7b,0x42,0x4,0x51,0x88,0x51,0x66,0x99, + 0xe9,0x4c,0x7c,0x6d,0x4b,0x2b,0x1c,0x8f,0x81,0x20,0x3b,0x5f,0x83,0x4f,0x3,0x9c, + 0x92,0xd3,0x97,0x25,0x56,0xec,0xd7,0x31,0xb8,0x45,0x4e,0x96,0x42,0x80,0x53,0xe1, + 0x34,0xa6,0xab,0xc3,0x6b,0x79,0x68,0x2c,0xb4,0x50,0x85,0x1e,0x7a,0x5a,0xcb,0x8b, + 0xdf,0x4a,0x5c,0x4f,0x1e,0x28,0xe8,0x8,0x13,0x63,0x7e,0x7,0x3e,0xa2,0xf1,0xe6, + 0x30,0x8,0x5b,0x6b,0x6b,0xda,0x18,0x27,0xe5,0x33,0x90,0xc2,0x4d,0x80,0x8d,0x8, + 0xcd,0xa3,0x5c,0x91,0xe2,0x2a,0xf4,0x1c,0xf2,0x3f,0xaa,0xbc,0x65,0x84,0xd,0x1d, + 0xa1,0xa3,0xf7,0x2,0x16,0x73,0xd2,0xe6,0x1c,0x55,0x96,0xb6,0xf7,0x92,0x58,0xd5, + 0xc9,0x1d,0x56,0x15,0xd,0x83,0x7d,0xc1,0xb8,0xe6,0xc,0x92,0x5,0xbb,0x96,0x6, + 0xd2,0xd7,0x28,0xc6,0x87,0xa1,0xe2,0x46,0x1b,0x75,0x53,0x82,0x45,0x9,0x61,0xe2, + 0x9,0xc0,0x5d,0xe9,0x4a,0x47,0xdc,0xe4,0xb,0xaf,0x53,0x0,0xc3,0x8d,0x3c,0x43, + 0x2,0x2,0xc6,0x25,0x3f,0x4d,0x19,0x24,0x44,0x3c,0x12,0xc2,0xa6,0x65,0x82,0x60, + 0xda,0xde,0x3d,0x62,0x65,0xfb,0xd7,0x90,0x79,0x8f,0x67,0x24,0x4b,0xc6,0x22,0x69, + 0xc5,0xfb,0x94,0x3f,0x7f,0xbd,0xf6,0x6a,0xc1,0xb3,0x8c,0x4,0xb9,0xab,0xc4,0x35, + 0xfa,0xb5,0x12,0xbf,0x1d,0x0,0x21,0xfa,0xf3,0xa8,0x1c,0xcf,0x12,0x16,0x30,0x77, + 0xe0,0x64,0x54,0x6b,0x63,0x79,0x4e,0x2f,0x2f,0xa0,0xa4,0x99,0xf5,0x76,0x6e,0xe2, + 0xe6,0x82,0x2e,0x37,0x3,0x77,0x5f,0x9,0x65,0x86,0x79,0x5f,0xcf,0x82,0x96,0xe9, + 0xdc,0x9a,0x45,0x14,0x8a,0xdf,0xb5,0x82,0x0,0x21,0x33,0xf0,0x43,0x7f,0x52,0x67, + 0xeb,0xb3,0x52,0x6d,0x0,0xb0,0x33,0xf2,0x19,0xa2,0x41,0xb4,0x2e,0x4,0x8d,0x78, + 0xb6,0x20,0x69,0x38,0xf,0xc5,0x97,0x26,0x62,0xb9,0x25,0xf9,0xf0,0x49,0x50,0x2, + 0xf5,0x50,0xc9,0x50,0x54,0xab,0xc5,0x90,0xc4,0xb9,0xa,0x7e,0x4f,0xae,0x5d,0x9c, + 0x61,0xf6,0xad,0x9a,0xf6,0xa,0xbf,0x19,0xcf,0xfe,0x5d,0xe5,0xea,0xb1,0x2d,0x1, + 0x9e,0xf,0x3f,0x2,0xf3,0xfe,0x63,0xc0,0x39,0x49,0xa,0xed,0xc5,0xba,0x4f,0x97, + 0x74,0x83,0x2f,0x1f,0xb1,0xd5,0x64,0x6b,0x6f,0xa8,0x43,0xa9,0x80,0x4d,0x32,0x76, + 0xc5,0xe1,0x41,0x81,0x14,0x6c,0x1c,0xc,0xd4,0x94,0xf1,0x96,0x17,0x85,0x44,0x48, + 0xea,0xa3,0x27,0xc8,0xd1,0x7a,0xb1,0x35,0xab,0xd3,0x24,0xaf,0xf8,0x29,0x2d,0xd7, + 0x99,0xd4,0x38,0x93,0x66,0xf,0x97,0x69,0x8e,0x62,0xf2,0xad,0x5,0xa8,0x26,0xaa, + 0x4f,0xbf,0x19,0xa6,0xec,0x7,0xa3,0xcc,0xfb,0x7b,0xbb,0x7a,0x9b,0x6d,0xc2,0x4b, + 0x63,0x37,0x86,0xaa,0x87,0x36,0x33,0xa9,0x1,0x44,0x49,0x79,0x56,0x33,0x5c,0x25, + 0x73,0x91,0xae,0x9c,0x35,0x8a,0xa8,0xa2,0x7,0xb9,0x7d,0xb,0x30,0xc0,0x89,0x30, + 0xb2,0xa0,0x2e,0x5e,0x4c,0x44,0xbf,0x3,0x68,0xa0,0xcc,0x78,0x63,0xc9,0x37,0xf7, + 0xa4,0xa,0xf7,0x20,0x8c,0xb0,0xcb,0xfe,0x7d,0xd7,0xaa,0x52,0xd0,0x31,0x47,0xc9, + 0x77,0x30,0xf2,0x8f,0x8a,0x97,0xcc,0xd5,0xb2,0xa3,0xea,0x8c,0xba,0x38,0xf7,0x90, + 0xac,0x13,0x6a,0x52,0xa7,0x1,0x20,0xba,0x2f,0xa0,0x12,0xc1,0x94,0x64,0x84,0x40, + 0x6,0x7a,0x9b,0x46,0x67,0x98,0xed,0xf3,0xe1,0xdd,0xbb,0xfd,0x98,0x18,0x73,0xf7, + 0xcf,0xc1,0x47,0xa9,0xfc,0x62,0x56,0xdc,0x88,0x33,0x8e,0x49,0x52,0x11,0x90,0x65, + 0xb0,0x51,0x9d,0xb5,0xb,0x84,0xa4,0x8d,0x54,0x75,0x77,0x20,0x7d,0x82,0x28,0x92, + 0xb7,0x12,0x7,0x96,0x56,0xad,0x36,0xa1,0x10,0xad,0x2e,0xa4,0x96,0xb8,0x8d,0x9a, + 0x89,0xbc,0x24,0xd8,0x89,0x99,0xc3,0x4c,0xf9,0xea,0xf7,0x56,0x8c,0x1c,0x21,0xd2, + 0x33,0xe3,0xc9,0x54,0x23,0x4a,0x1e,0x15,0x95,0xf5,0x3f,0x17,0x5a,0x9,0x8a,0xc6, + 0x3a,0xae,0xc1,0xd7,0x46,0x45,0x58,0xf8,0xb2,0x89,0xd1,0x44,0x22,0xd7,0x5a,0xbf, + 0x5a,0x3d,0xfa,0x70,0x29,0x16,0xd0,0x4a,0x5a,0x67,0x5a,0xe1,0x5,0x88,0x6e,0x41, + 0x7,0xff,0x1e,0x14,0xa1,0xc6,0x31,0xef,0x97,0x83,0xce,0x3c,0x9c,0xf,0x72,0xe, + 0x65,0x5b,0x12,0x81,0x8b,0x38,0x2b,0x7e,0x67,0xb4,0x68,0xb2,0xdd,0xb5,0x83,0x6, + 0x43,0x1c,0xb3,0xe0,0xb0,0xf9,0x42,0x27,0x92,0xfa,0x90,0xb0,0x90,0x13,0x10,0xd1, + 0xa4,0xae,0x87,0x5e,0xd0,0xd7,0x0,0xa8,0x24,0x26,0x31,0x11,0x61,0x9,0x97,0x9c, + 0x6d,0x29,0x47,0x3d,0x49,0x79,0x37,0x8b,0xb6,0xea,0xd7,0x8b,0x3,0x54,0x9d,0x23, + 0x81,0x1a,0x7,0xa0,0xbd,0x7e,0x1c,0x6a,0xfe,0x3a,0x70,0x8b,0xf2,0x3c,0xf,0xf2, + 0x40,0xf4,0xff,0x39,0x4c,0x11,0xbc,0x61,0x60,0x1d,0xd2,0x92,0x4,0x67,0xef,0x29, + 0x57,0x88,0xec,0xc,0xcb,0x6a,0x15,0x1c,0x66,0xd4,0xa1,0x69,0x3,0xef,0x83,0xcb, + 0x7,0xce,0xd0,0x21,0x98,0x16,0x48,0x30,0x3b,0xb6,0xae,0xca,0x64,0x68,0x92,0xb0, + 0x69,0x0,0x6e,0xe9,0x7a,0xdd,0xa3,0xca,0x76,0xd7,0x8e,0xe7,0xa9,0xe1,0x71,0x50, + 0x2b,0xb1,0x44,0x40,0x36,0x1e,0x38,0xa8,0xbe,0x49,0x65,0x54,0xb5,0x67,0x57,0xd7, + 0x31,0xd5,0xa,0xe0,0x80,0x7a,0xa5,0x61,0xe0,0x55,0x1,0x6f,0x2,0xc,0x17,0xf1, + 0x3,0x2d,0xcd,0xf6,0x43,0xb1,0xa2,0x8f,0x6e,0x7,0xc3,0x38,0x1b,0xc5,0x78,0x7e, + 0x49,0x33,0x90,0xea,0x56,0x9e,0x1b,0x95,0xdd,0x1d,0x13,0x1,0x3c,0x8,0x74,0x70, + 0x40,0x31,0x22,0x17,0xa,0x9c,0x44,0xc6,0x72,0x34,0x66,0x88,0xdc,0x67,0x8e,0xa2, + 0x98,0xd8,0x7,0xe3,0xbb,0x82,0xe4,0xd9,0x50,0x85,0xf6,0x84,0xe6,0xde,0x2e,0xe6, + 0xc6,0xb8,0xbf,0xe3,0x8a,0xe4,0xe,0xd7,0x42,0xa0,0x5c,0xa5,0x68,0x27,0xb6,0x36, + 0x90,0x73,0x3b,0x54,0xa9,0xe6,0xc0,0x5a,0xd3,0x96,0xe4,0x63,0xe8,0xcb,0x9d,0x6c, + 0x4d,0x65,0xe6,0x5e,0x53,0x6b,0xfa,0xc0,0x91,0xdf,0xd,0x86,0x89,0x4a,0x2d,0x78, + 0xbe,0x5b,0x5c,0x72,0xa8,0x92,0x44,0xc3,0x7a,0xb2,0x74,0x5e,0x9,0x36,0xf6,0xe8, + 0x6b,0x1e,0xcc,0x94,0x24,0x49,0xd0,0x24,0xe5,0xc5,0xac,0x3d,0xa8,0x7,0xb2,0xa0, + 0x8f,0x9e,0x9,0xc,0xcf,0x2d,0x78,0x43,0x50,0xe3,0x23,0x1c,0x90,0xc8,0x74,0x8f, + 0x93,0xc3,0xdc,0x5,0xb6,0xd8,0x25,0xa6,0x83,0xaf,0xb1,0x10,0x4d,0x43,0x54,0xfd, + 0x3c,0xb0,0xfb,0xda,0x8c,0xa9,0x44,0x28,0x26,0x47,0xfb,0x4e,0xcd,0xe6,0xec,0xa9, + 0x73,0xeb,0xbc,0x67,0x31,0x93,0x86,0x7a,0xad,0x20,0x50,0x2e,0x40,0x4b,0x8,0xca, + 0x88,0xc5,0x1c,0xfa,0x56,0xc8,0x39,0xa2,0x54,0x8d,0x26,0xa2,0x85,0xb7,0xdb,0x44, + 0x35,0x81,0xed,0x99,0x61,0x93,0xdd,0x17,0x22,0xc8,0xdf,0x20,0x6d,0xfa,0x29,0x3b, + 0xb3,0x1b,0xd5,0x73,0x9f,0x89,0xdd,0x46,0x48,0x31,0x99,0x40,0xbb,0xd0,0x8f,0x8c, + 0xb7,0x84,0xe1,0xf9,0x40,0xe7,0x32,0xce,0x60,0x87,0xef,0x22,0x2,0x5,0xc,0x4c, + 0x9f,0x27,0x84,0x11,0x99,0x6a,0x43,0x70,0x4f,0xff,0x8b,0xae,0x28,0xb7,0x42,0x25, + 0x10,0x10,0x29,0x77,0x65,0x9c,0x1,0x6b,0xcd,0x36,0xef,0x31,0xb2,0xd2,0xb9,0x71, + 0xba,0x42,0x1,0x74,0xa4,0xed,0x79,0xad,0x11,0x2c,0x4a,0x86,0xfa,0xa7,0x81,0xef, + 0x1a,0x7d,0xb0,0x2d,0xff,0x95,0x51,0x35,0x37,0xf4,0x68,0x9,0xf0,0x8,0x9a,0xbd, + 0x1a,0xc1,0x40,0x28,0x49,0x9d,0xea,0x8e,0x1,0xf8,0x33,0x3b,0x3e,0xe,0x63,0x25, + 0x39,0x86,0xbb,0x92,0x38,0xf4,0xcf,0xb7,0x19,0xe3,0x81,0x54,0x36,0xd5,0x44,0x93, + 0x9c,0x4a,0xca,0x2c,0x3b,0xbc,0x76,0xed,0xc3,0x9e,0x9b,0x12,0xbf,0xfa,0x81,0x3c, + 0x20,0x59,0xf4,0x8d,0x79,0x64,0x49,0x8d,0x55,0x1a,0x4c,0xff,0xc0,0x61,0xb8,0xcb, + 0x36,0x13,0x52,0xc1,0x8c,0xa,0x21,0xf,0x55,0xd8,0xc0,0x89,0x43,0xea,0x9f,0xba, + 0x16,0x6a,0xf7,0x2e,0x28,0x3d,0x88,0x12,0x11,0xa0,0x33,0xd1,0x95,0x99,0x46,0xd8, + 0x8c,0x72,0x22,0x1c,0xfe,0x5d,0x2,0x93,0x13,0x41,0x56,0x42,0x48,0xb4,0xb0,0xb3, + 0xe1,0x2c,0xf9,0x12,0xf2,0xd6,0xb8,0x56,0x79,0x10,0xd,0x19,0x0,0x5d,0x9,0xec, + 0xeb,0x49,0x8,0xcc,0xd3,0xb5,0xe2,0x27,0xc4,0x71,0x54,0x58,0x9,0x68,0x16,0x86, + 0x4e,0xf4,0x8a,0xad,0x46,0xd4,0x2f,0xef,0x61,0xd7,0x52,0xe,0xb5,0x31,0xe,0xec, + 0xe7,0x2e,0x44,0x6d,0xf1,0x76,0x5f,0xfb,0x25,0x90,0xaf,0xb6,0x14,0x5c,0x89,0xad, + 0x5d,0x27,0xb2,0x56,0xaf,0xa6,0x84,0xb9,0xf,0x31,0x57,0xa5,0x74,0x91,0x9d,0x2b, + 0x4c,0x7d,0x26,0x84,0x57,0x2,0x51,0xce,0x63,0x7,0x5a,0x97,0x84,0x43,0x56,0xca, + 0x98,0xa0,0x7,0x32,0x66,0x95,0x1e,0x4a,0x8b,0x92,0x74,0x93,0xa9,0x65,0x79,0x8, + 0xec,0x12,0x98,0xa0,0x45,0x29,0x6,0x7f,0x2b,0xf9,0x5,0xbb,0xd8,0x55,0xb2,0xdf, + 0x89,0x10,0x1,0xb,0xcb,0x29,0x60,0xb5,0xf8,0x20,0x46,0x1a,0x56,0x43,0x27,0x38, + 0x5,0xfc,0x69,0xd5,0xdd,0x5f,0xf5,0x66,0xba,0xca,0x39,0x34,0xcf,0x79,0x8c,0x2d, + 0x9d,0x6d,0x1a,0xd1,0x40,0x7a,0x71,0x65,0xaa,0x67,0x30,0x53,0x90,0xe1,0x58,0xe9, + 0x56,0xe0,0x18,0x82,0x6a,0xa,0x1c,0x62,0x2b,0x77,0x9f,0xfa,0x6c,0xf6,0xbb,0xca, + 0x8d,0x12,0x74,0xf,0xc2,0x16,0xf5,0x10,0x88,0x5a,0x5b,0xfb,0x20,0xc3,0x18,0x55, + 0xaa,0x3b,0xf0,0x74,0x82,0x83,0x1e,0xfa,0x98,0x5,0x78,0x13,0x34,0x13,0x89,0x52, + 0x1d,0xe1,0x53,0x5,0xb4,0x6b,0x5,0x17,0x98,0x8b,0x92,0x9e,0xfb,0xd2,0x8f,0x92, + 0x60,0x94,0xd0,0xf3,0x1e,0x81,0xa3,0x13,0x69,0x8c,0x5b,0x41,0xe3,0x2e,0x94,0xba, + 0x14,0x39,0x7c,0x23,0xd2,0x8d,0xf4,0xbe,0xf4,0x82,0xa7,0xe2,0x73,0x39,0xd4,0xe0, + 0xa,0x27,0xa5,0xb9,0xcf,0xb6,0x2f,0x72,0x97,0x3e,0x79,0x1f,0x12,0xce,0xcc,0xca, + 0xe9,0xc0,0xb8,0x81,0x1a,0xdc,0xc0,0x77,0x79,0xf6,0x7d,0x73,0x6,0xda,0xe1,0xa5, + 0x84,0x83,0x10,0xdf,0x93,0x8e,0xc4,0xb3,0xaf,0xf6,0x6a,0x5b,0x25,0x5f,0x41,0xff, + 0x7c,0x8a,0x76,0xe2,0x64,0xa5,0x44,0xc0,0xc9,0x37,0x5a,0x93,0xe1,0x53,0x7b,0x6e, + 0x32,0xb6,0x29,0x1c,0xb8,0x47,0xd3,0xbe,0x56,0x53,0x99,0xf2,0xea,0x66,0x44,0x5e, + 0xd6,0xdf,0x5f,0xce,0x48,0x80,0x77,0x4,0x1a,0x0,0xad,0x2d,0xaf,0xe7,0xef,0xae, + 0xce,0x54,0xd4,0x60,0x37,0x69,0xbd,0xa8,0x4b,0x97,0x31,0x9e,0xaf,0xec,0xb5,0x9, + 0x5e,0x81,0x13,0x81,0x76,0xae,0xda,0x19,0x21,0x3a,0x95,0x2d,0xd9,0xe,0xcf,0x7d, + 0x76,0xab,0x99,0xe5,0x13,0xd8,0xb2,0x5b,0x92,0xa0,0xfc,0x26,0x41,0xf6,0x22,0x46, + 0xb,0x14,0xc8,0xf5,0xea,0x1c,0xf4,0x22,0xce,0x72,0x22,0x3,0x50,0x66,0xef,0xb3, + 0x1d,0x57,0x71,0x2f,0xcb,0xf5,0xd2,0xf5,0x34,0xe7,0x44,0x32,0x45,0x9b,0x2e,0x50, + 0x65,0x3e,0xaa,0xe7,0x87,0x70,0x41,0x94,0x4,0xc,0x71,0x5e,0x53,0xb5,0x41,0x65, + 0xe3,0x33,0x12,0xc5,0x87,0xd4,0x69,0xfa,0xfe,0xc2,0x4,0xa5,0xb4,0xd1,0x72,0xa, + 0xe6,0x89,0xbd,0x46,0x85,0x11,0x45,0x52,0xa0,0x5c,0xf0,0xd,0x7d,0x86,0xdd,0xc7, + 0xd6,0xaa,0x70,0xfd,0xe1,0xff,0xf0,0xc7,0x27,0x56,0xed,0x79,0x38,0x2c,0x9c,0x68, + 0x62,0xf8,0xe6,0xbb,0xb0,0x17,0x47,0xae,0x37,0x36,0xe3,0xbb,0x13,0x22,0xf0,0x42, + 0xd2,0x52,0x45,0x48,0x64,0xb9,0x91,0x5e,0x49,0x35,0xae,0x28,0x87,0x7e,0x4c,0xd, + 0x92,0xba,0x7,0x96,0xf9,0x44,0xb5,0x6c,0xf0,0x1f,0xdb,0x9f,0x1b,0x84,0xac,0xd5, + 0x54,0x93,0xb9,0xe4,0x50,0x42,0xb3,0x4f,0x12,0x54,0x67,0xaa,0x3a,0xfe,0x39,0xcc, + 0x64,0xa4,0xbf,0x7a,0x6a,0x5a,0x32,0xb5,0xe4,0xb3,0xfa,0x60,0xb2,0x6c,0x24,0x60, + 0xe3,0x88,0x1c,0xb7,0x95,0xc4,0x51,0x6d,0xc1,0xdb,0x5b,0x38,0x8c,0x52,0x4d,0xd7, + 0x72,0xca,0x8c,0x71,0x60,0x13,0x9f,0xd8,0x45,0x29,0xa4,0x75,0xf8,0xfb,0x6f,0x11, + 0x59,0xcf,0x64,0xda,0xb0,0xe1,0x3c,0x7e,0x8e,0xec,0x80,0x64,0xe1,0x67,0xc0,0x1d, + 0xae,0x56,0x3,0x58,0x82,0x89,0x11,0xa6,0x1a,0x4c,0xc9,0xc6,0xf5,0x7d,0xc1,0xc0, + 0x8d,0xd4,0xdf,0x7e,0x59,0x58,0xe6,0x36,0x6d,0x34,0xd5,0xca,0x1f,0x55,0xeb,0x92, + 0x43,0xc0,0xe0,0x83,0x4c,0x7,0x86,0x99,0x4,0x84,0x64,0x73,0x9d,0xd8,0x28,0xf7, + 0xeb,0xe8,0x86,0x47,0xec,0xa,0xed,0xe3,0x59,0x86,0xd3,0x64,0x27,0xcd,0x16,0x74, + 0x1f,0x1b,0xaa,0x12,0x46,0x57,0x5b,0xe3,0xd0,0x9,0xcb,0x9,0x52,0xf4,0xf1,0x20, + 0x52,0x90,0xcb,0x72,0x1,0x15,0x2a,0xfa,0x84,0x3,0xf,0x6b,0x68,0x23,0x32,0xcf, + 0x93,0x10,0x7b,0x62,0x10,0x60,0x3b,0xc9,0x71,0x9e,0x22,0xc6,0x21,0xf0,0x44,0x97, + 0xa0,0x66,0xc5,0xb8,0xf3,0xcc,0xcb,0x8c,0x4f,0x2a,0x39,0x9a,0x23,0x60,0xf3,0x92, + 0xb3,0xc6,0xfa,0x16,0x51,0xbf,0xa5,0x5e,0x59,0x98,0xf1,0x5,0x96,0x5a,0xa1,0x86, + 0x57,0xc5,0xf1,0x3d,0x33,0xbd,0x4e,0xa2,0xe8,0xf5,0x87,0xdf,0x7f,0x1c,0x2e,0x28, + 0xa1,0xd2,0x34,0xc1,0xcd,0xec,0x55,0x88,0xcd,0x3a,0xc,0xc7,0x18,0x7b,0x5,0x3f, + 0x4a,0x9,0x72,0x68,0x86,0x3,0xf3,0x59,0x1d,0x2c,0xdf,0xf1,0xb5,0xaf,0xe,0xf9, + 0xd3,0xa9,0x3b,0x5,0x9c,0x64,0x1d,0x12,0x73,0x30,0x38,0x6c,0x98,0xf1,0x50,0x3f, + 0x64,0x40,0x40,0x7f,0xd,0xcc,0xc0,0x42,0x8e,0x4c,0x6e,0xd6,0xb2,0x6b,0x70,0xe3, + 0x1b,0xc1,0xe6,0xb0,0x82,0xbf,0xb5,0x68,0x59,0x47,0x31,0xb1,0xd3,0x9f,0x7d,0xd7, + 0x80,0x57,0x43,0x78,0xe0,0x8b,0x77,0x4e,0x24,0x13,0xc8,0x61,0xce,0x21,0x74,0xfa, + 0x4c,0x6d,0xf7,0x6e,0xdf,0x63,0x54,0x61,0x5a,0x64,0xe3,0x4c,0x6c,0x85,0xbc,0x2f, + 0x73,0xf7,0x3e,0xa7,0xf6,0x14,0x93,0x4d,0xc,0x45,0x58,0xa2,0x32,0x64,0x3a,0x5d, + 0x73,0x3e,0x35,0x4b,0xdb,0x53,0x65,0x86,0x31,0xa5,0x1a,0xd2,0x79,0x18,0xd3,0x27, + 0x47,0x36,0x54,0xda,0x7f,0xbb,0x55,0x4b,0xa4,0x13,0x64,0x23,0x10,0x50,0x39,0x7, + 0xe5,0x2d,0xb3,0x5d,0xbc,0x44,0x2,0x21,0x9a,0x13,0xde,0x7d,0xa7,0xc9,0x2f,0xb7, + 0xbc,0x79,0x90,0xb3,0x4f,0x83,0xc7,0xdc,0x73,0x7,0xf9,0x6f,0x41,0x98,0x32,0xaf, + 0x55,0x9d,0x84,0xc3,0x61,0x5f,0xd,0x60,0x99,0xf,0x72,0x76,0x5e,0x9,0xea,0xcc, + 0xc7,0x21,0xbe,0x1d,0x8,0x19,0xda,0xe8,0x94,0x2f,0xd2,0xb1,0xbf,0x46,0x9a,0xc, + 0x32,0x29,0x4e,0xc7,0xe6,0x14,0x30,0xc7,0x69,0xd9,0x6f,0xed,0x7a,0xd7,0x24,0xcf, + 0x55,0x3d,0x7f,0x4e,0x68,0x44,0x34,0x79,0x9,0x4e,0xe3,0x41,0x9d,0xec,0x26,0xad, + 0x2b,0x93,0x29,0x86,0x56,0xe5,0xc3,0xdc,0x67,0x9c,0xa3,0x18,0xce,0xc,0x45,0x2b, + 0x19,0xd3,0x48,0x56,0x4c,0x10,0xe3,0xad,0xb1,0x29,0x7f,0xe3,0xaa,0xa9,0xc,0xec, + 0x5c,0x6c,0x59,0x3d,0x58,0xcf,0xd8,0x1a,0x2,0xf2,0x11,0xa9,0xc2,0x93,0xc0,0x4c, + 0xab,0x6,0x51,0xbd,0x4a,0x6c,0x64,0x8a,0xa,0x3b,0xd6,0x25,0x2,0x1e,0xa2,0x15, + 0x87,0x9d,0x31,0x49,0x5b,0x85,0xbb,0x84,0xf6,0xe2,0xa7,0x37,0x8e,0x6c,0xf4,0x3, + 0xc0,0x8d,0xb0,0x62,0xe4,0x60,0x55,0xca,0xb1,0x1f,0x75,0x4c,0xa5,0x3c,0x5c,0x81, + 0x3,0x4b,0x79,0x1e,0x4c,0xde,0x56,0xa2,0x34,0x15,0xa8,0x93,0x6b,0x1b,0xb,0x43, + 0xd6,0xd7,0x96,0x4f,0x93,0x1d,0x9c,0xbc,0xd3,0x2a,0xe5,0x70,0xe3,0xa5,0x5a,0x7d, + 0x8c,0xe4,0x4d,0xba,0x5f,0x40,0xd,0xe4,0xab,0xbd,0xa4,0x28,0x52,0x8b,0x22,0x84, + 0x21,0xff,0x9c,0x63,0x5d,0xb,0x3e,0xd5,0x39,0x64,0x75,0x64,0x9b,0x64,0x80,0x97, + 0x7,0x1,0x17,0x3c,0x69,0x87,0x7,0xbb,0x37,0xc6,0xd6,0xd3,0xf6,0xcd,0xca,0x81, + 0xf1,0xac,0x33,0xd9,0x60,0xf4,0x41,0xa9,0x28,0x92,0x8e,0x76,0xf9,0x38,0xa3,0x92, + 0xae,0xd4,0xf3,0xfb,0x91,0xd7,0xda,0x52,0xa2,0x1b,0xa3,0xeb,0xb3,0xdc,0xa1,0x44, + 0x15,0xa3,0x4b,0xb9,0x6,0x50,0x18,0x82,0x4a,0xb4,0xc5,0x92,0xe3,0x31,0x0,0x49, + 0x6a,0x47,0xdb,0xe6,0x83,0xad,0x1d,0xb5,0xd9,0x7e,0x4c,0x9e,0x8b,0x42,0xa9,0x55, + 0x3d,0x40,0xd,0x1d,0x8,0xc6,0x19,0xdb,0xbb,0x75,0x2,0x95,0x22,0x49,0xcb,0x58, + 0x5c,0x9f,0x32,0xfd,0xfe,0x6a,0xec,0x7e,0x5b,0xc7,0x48,0xea,0x23,0x4f,0xf5,0xd3, + 0x90,0x10,0xc8,0x7e,0xcc,0x63,0xef,0x72,0x12,0x20,0x5a,0xef,0x18,0xd1,0xba,0xa7, + 0x29,0x94,0xad,0x33,0x3c,0x85,0x58,0x20,0x93,0xf,0x78,0xd4,0xd1,0x2,0x4d,0x58, + 0xfc,0x20,0x57,0x89,0x9b,0xb4,0x34,0x36,0xe7,0x62,0x30,0xc1,0x62,0xaf,0x36,0xd3, + 0xfa,0x13,0xf4,0x8a,0x96,0x22,0xf3,0x5d,0x75,0xf0,0x7c,0x21,0x7,0x5e,0x8e,0xac, + 0xa3,0x2a,0x9f,0x87,0xd5,0xf1,0x43,0xa2,0x9d,0xc3,0xe6,0x33,0xac,0xb6,0xd1,0x49, + 0xa4,0x67,0x27,0x7a,0xba,0x2c,0x78,0x23,0x3e,0xf4,0x98,0x16,0x3d,0x56,0xc,0xd9, + 0x60,0x63,0x1e,0x89,0xa6,0xff,0x24,0x21,0xbd,0xd,0xf1,0xd4,0x0,0x2,0x38,0xb0, + 0xfc,0x70,0xec,0x9d,0x35,0x36,0x6c,0xf6,0xe8,0x72,0x13,0x23,0x18,0xc2,0xba,0x51, + 0xc3,0x33,0xfc,0xd8,0x33,0x1c,0x7a,0xda,0xee,0x58,0x5,0x67,0xc9,0x3f,0x32,0xab, + 0x2a,0xad,0x9,0x97,0x46,0x35,0x9,0xca,0xfb,0xef,0x89,0xae,0xf1,0xc3,0x46,0x60, + 0xab,0xc1,0x6c,0xbe,0x5c,0xe6,0x51,0x7b,0x1e,0xc0,0xb1,0x16,0x35,0xdb,0x59,0x95, + 0xc8,0x94,0xfe,0x75,0xf6,0x27,0x77,0xf7,0x7,0xe2,0x43,0x8e,0x25,0x99,0x8b,0x36, + 0xeb,0xed,0xbe,0xd9,0x79,0xff,0xd4,0xc9,0xbb,0x46,0x4d,0x7c,0xb4,0xd7,0x98,0x8a, + 0x95,0xd9,0xd1,0x3f,0x19,0xb1,0x64,0xac,0x40,0x76,0x1,0xef,0xdf,0xf5,0x68,0x0, + 0x20,0xe,0xc,0xc8,0x18,0x61,0x8c,0xb6,0x11,0x41,0xce,0x7b,0x66,0x9f,0x61,0xf7, + 0xb0,0xa0,0x93,0x1b,0xb8,0x93,0x82,0x47,0x46,0xd8,0xe7,0x94,0xb,0x4e,0xae,0x72, + 0x6d,0x67,0x34,0x33,0xa0,0x22,0x96,0x44,0xe8,0xf6,0xff,0x7e,0x24,0x8f,0xd1,0x24, + 0x65,0x81,0x4d,0x36,0x24,0x74,0x44,0xf2,0xb2,0xc9,0x3,0xf3,0x92,0xd7,0x25,0x7b, + 0xb3,0xca,0x9,0x37,0x96,0x0,0x54,0xeb,0x1f,0x5d,0x69,0x56,0xfa,0x75,0x63,0x50, + 0xae,0xc1,0xf3,0xf9,0x40,0xfe,0xda,0x9e,0xe6,0x2a,0x2b,0x8b,0xe2,0x85,0x14,0x56, + 0x9e,0x5c,0x9d,0x25,0xe1,0xcc,0xe0,0x86,0xf9,0xcc,0xa8,0x3e,0x69,0xd4,0xc9,0xa5, + 0xf0,0x7d,0xdf,0x48,0x62,0x92,0x30,0xdb,0x3a,0xdc,0xfe,0x10,0x2a,0x88,0x33,0xb6, + 0x12,0x95,0xdf,0x6,0x55,0xb,0xe4,0xb6,0xbb,0xad,0x2d,0x19,0xdb,0x25,0x7d,0x19, + 0x4a,0xbc,0xfb,0x5a,0x10,0x1a,0x20,0x4a,0xb3,0xd8,0x72,0x9f,0x18,0x1c,0x75,0x38, + 0x9c,0xaf,0xaa,0x1b,0x8e,0x4d,0x6e,0x6d,0x8e,0x3f,0x30,0x59,0xe,0xb4,0xd3,0x15, + 0xdb,0xa4,0x87,0xc2,0x6,0xcf,0x83,0x77,0x55,0xbb,0x71,0x9d,0x56,0x6c,0xb9,0x4c, + 0x31,0x51,0xb3,0xfd,0x66,0x12,0xa0,0x33,0x4,0x51,0xf9,0x2b,0x97,0xff,0x26,0x31, + 0xcd,0xf2,0x9b,0x70,0x2e,0x0,0xdb,0x4d,0xa7,0x4f,0x4,0xb4,0x5d,0xb2,0xf6,0xef, + 0x35,0xc0,0x35,0x91,0x91,0x4d,0xa4,0x47,0xd4,0xe0,0xfb,0x5e,0x7,0x99,0xec,0xbc, + 0x37,0xb4,0x98,0x36,0xed,0xae,0x37,0xb5,0xa2,0xa7,0x9c,0xcc,0x68,0x4e,0xd9,0x9e, + 0x3e,0x3c,0x50,0xaf,0x4a,0x88,0x76,0x7f,0xaa,0x38,0xd8,0xad,0x94,0x4c,0x86,0xa0, + 0x8c,0x8d,0x10,0x6,0xdb,0x25,0x44,0xe3,0x3d,0x64,0xac,0xca,0x6c,0x50,0x59,0x37, + 0x38,0xd,0x4a,0x6e,0x10,0xb2,0xd8,0x73,0xed,0x50,0x42,0x84,0x3c,0x24,0x83,0x19, + 0x2b,0x46,0x31,0xb2,0xfa,0x42,0x90,0x28,0x4a,0x3d,0xc8,0x85,0xf4,0x86,0xac,0xc, + 0x11,0x24,0xa5,0x4d,0xaa,0xd0,0x3,0xca,0x78,0x1,0x5,0x77,0x8a,0xd3,0xdf,0xcb, + 0x20,0x3e,0xa9,0xc7,0x7,0x31,0x33,0xd3,0x87,0xd6,0x37,0xd4,0x6a,0x36,0x5a,0x1, + 0x6a,0x6,0x31,0x8e,0xb0,0xd4,0x25,0x46,0x36,0x87,0xd1,0x94,0xc4,0xe,0x16,0xb9, + 0x6,0x96,0xf0,0x2f,0x74,0xe2,0x71,0xb5,0x12,0x27,0xab,0x3e,0x42,0xda,0x21,0xbb, + 0xec,0x1c,0xf9,0xf3,0x71,0xdb,0xf1,0x9e,0x8c,0xe6,0x58,0xd3,0x86,0x80,0x1,0xce, + 0x55,0x44,0x52,0x49,0x2d,0xeb,0x11,0x56,0x76,0xe0,0xc3,0xb8,0x34,0x59,0xa1,0x8f, + 0x57,0x3d,0xbc,0x90,0xea,0x3a,0xec,0xbe,0x7f,0x14,0x1,0xe1,0xd8,0xe3,0xce,0x8a, + 0x71,0x97,0xc7,0x42,0x5e,0xd5,0xf1,0x36,0x15,0x8b,0x9,0xd7,0x33,0xd7,0xde,0xe6, + 0x82,0x0,0x30,0xa0,0x75,0x4b,0x53,0xfb,0x81,0xe2,0x6d,0x74,0x8e,0x67,0x74,0x8e, + 0x7d,0xbe,0x69,0xb0,0x4a,0x6f,0xbc,0x1a,0xab,0x22,0x39,0xd8,0x89,0x3e,0x8,0xcf, + 0x30,0xb6,0x59,0x13,0x19,0xab,0xa1,0x6c,0x41,0x57,0xa9,0x61,0x21,0x75,0x78,0xa2, + 0xa3,0x9c,0xc0,0x81,0x27,0x37,0x28,0xd3,0x64,0xa0,0x98,0xec,0x3b,0x87,0xae,0xe8, + 0x84,0xab,0xab,0x73,0xa2,0xa1,0x92,0xa,0x71,0xc0,0xc7,0x1f,0xc3,0xff,0xd4,0x91, + 0x46,0x4e,0x53,0x4,0xd5,0xdf,0x33,0x55,0x84,0x74,0xdf,0x81,0xe6,0x26,0xfb,0x8a, + 0x6b,0x13,0xcf,0x3a,0xdb,0x4c,0xad,0xa5,0x8a,0x43,0x47,0x5a,0x99,0xf9,0x2b,0x47, + 0x78,0x50,0xc3,0x9,0x81,0x81,0x7f,0x26,0x61,0xce,0x87,0xe7,0xe6,0x41,0xf7,0x4a, + 0xa1,0xb8,0x5d,0xf6,0x16,0x5b,0xd3,0xcc,0xae,0x34,0xbe,0x62,0x55,0xe1,0xf,0xfd, + 0x7b,0xef,0x3f,0x5e,0x87,0x33,0x1d,0xbe,0xd9,0xf1,0xf5,0x5,0x5b,0x20,0x86,0xfe, + 0x4d,0xe0,0x8d,0x1d,0x4d,0xdf,0xed,0xa8,0x18,0x69,0x79,0x25,0xd1,0x7d,0xe8,0x43, + 0xb5,0xf9,0xc5,0x57,0x1c,0xab,0x98,0x1d,0x33,0xc2,0x4f,0xf0,0xc6,0x12,0x35,0x3a, + 0xc9,0xc1,0x9b,0x2e,0xf2,0x40,0xc4,0x98,0x5b,0xe4,0xdd,0x4d,0x7e,0xfe,0xd1,0x7c, + 0x41,0xa4,0x98,0xb8,0xaf,0xbd,0x47,0x8c,0x80,0xd8,0x27,0xe1,0x48,0xd5,0x98,0x46, + 0x18,0x6,0xbb,0x62,0x31,0x7,0xe2,0x87,0x83,0xf7,0x4d,0xbf,0x5b,0x68,0xda,0x49, + 0xc5,0x4a,0x5,0x1e,0x75,0x14,0xaa,0x14,0x30,0x9,0x2,0x5f,0x3b,0xbf,0x4e,0x8d, + 0xd3,0xe7,0x17,0x24,0xeb,0xbe,0x82,0x83,0x31,0x8a,0xe1,0xe7,0xe7,0x4d,0x7a,0xa9, + 0xa8,0x97,0xb2,0xc9,0x6b,0xbd,0x6a,0x70,0xa3,0x9,0xfd,0xe0,0xbb,0x90,0x18,0x86, + 0x9e,0xdb,0x51,0x65,0xb8,0x62,0x74,0xf3,0x5b,0x2,0xd1,0xa7,0xd6,0xd0,0x91,0xe1, + 0x3a,0xf4,0x56,0x5e,0xe8,0xf7,0x1f,0xbf,0xfb,0xf8,0xfd,0xdf,0xba,0xa1,0x3c,0xd2, + 0x62,0xda,0x4d,0x4b,0x82,0x43,0xd,0xd8,0x7f,0x13,0xfc,0x80,0xb4,0x63,0x6,0x42, + 0xa0,0xed,0x34,0x7e,0x83,0xd5,0x31,0x6b,0x47,0xf2,0xa8,0xd2,0xed,0x4,0xb0,0x4e, + 0x3,0x4b,0xf6,0xc7,0xc4,0xbb,0x38,0xdf,0xf0,0x7e,0xaa,0xcc,0x85,0x50,0x97,0x9b, + 0x9d,0x64,0xb0,0xb3,0x3d,0x3d,0x8d,0x70,0x29,0xec,0x2f,0x30,0x3f,0xd3,0xf0,0xa3, + 0xd4,0x59,0x96,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x20,0xdb,0xa1,0x3,0x49, + 0xf8,0x95,0x6c,0x73,0x93,0x6c,0x1e,0x7c,0x4,0xe,0x4f,0x4,0x43,0x5f,0x3e,0x11, + 0x20,0x72,0x38,0x15,0xd0,0x65,0x94,0x5f,0x5a,0x31,0xc,0xca,0xae,0xae,0x17,0xd4, + 0x7d,0x31,0x10,0xc6,0xe6,0x15,0x84,0xc7,0x2a,0x84,0xe3,0x24,0x6f,0xfc,0xee,0x51, + 0xb2,0xb2,0x8c,0xf7,0x49,0x93,0xae,0x7d,0xc3,0x9,0x43,0x90,0xdc,0x38,0xca,0xa1, + 0x31,0x13,0x61,0xc0,0xa4,0xd,0x0,0x77,0x5,0x12,0x58,0x68,0x55,0x6a,0xc0,0xb8, + 0x5b,0xa1,0x5f,0x3c,0xf4,0xc1,0xd6,0x3f,0x5f,0xf2,0xf9,0x17,0xda,0x34,0x4e,0xba, + 0x2a,0x3d,0x1a,0x19,0x70,0x50,0xcc,0xc5,0x24,0xa,0x93,0x71,0xce,0x77,0xd8,0xe8, + 0xe9,0x76,0xa4,0xd7,0x23,0x16,0x8c,0xea,0x80,0x86,0x84,0xbe,0x37,0xc9,0x88,0xe2, + 0xd8,0x3,0x74,0x6b,0x52,0xa8,0x7f,0xfd,0x91,0xb4,0x92,0xfa,0x14,0x68,0xb5,0xa6, + 0x8e,0x4f,0x50,0x6e,0xb6,0x3b,0xbf,0xa1,0x19,0x8d,0x5,0x6a,0xbe,0x3d,0x8a,0x50, + 0x1d,0x8a,0x5e,0x4e,0x5c,0xda,0x97,0x63,0x4b,0xc2,0xba,0x76,0x4b,0x58,0x6c,0x22, + 0x60,0xaf,0xb8,0xdf,0x86,0x7e,0xd6,0xc,0x41,0xb6,0xef,0x83,0xc3,0x86,0x66,0x11, + 0x85,0x57,0x4c,0xbd,0x6d,0xc4,0x6c,0xf5,0x34,0xe1,0x4a,0x6c,0x18,0xe1,0x90,0xe8, + 0x23,0x1d,0x10,0x5c,0x43,0xdb,0x14,0xd6,0xbb,0x36,0x2c,0xc7,0x58,0xe7,0x49,0xa4, + 0xc3,0x80,0x67,0xf7,0x7c,0x4b,0xf6,0x89,0x43,0xd6,0xed,0xb6,0xb5,0x72,0xb0,0xda, + 0xeb,0xed,0x75,0xe3,0x16,0x1f,0x2a,0xce,0xdc,0x4b,0xad,0xdf,0xe9,0x37,0x27,0xb, + 0x62,0x6f,0x89,0x64,0xc0,0x4a,0x88,0x5c,0xa5,0x85,0xe7,0xc4,0x82,0x35,0xaf,0x2f, + 0x59,0xe9,0x51,0xc9,0xa3,0x8d,0xd4,0xf9,0xfd,0x42,0xe8,0xa9,0xef,0x91,0x2a,0x74, + 0x89,0x9b,0x2a,0xbb,0xbe,0xc9,0xe3,0xcc,0x85,0x7c,0x32,0x98,0x23,0xd6,0x38,0x9b, + 0xa4,0xb4,0x8c,0xd,0xc2,0x7f,0x9b,0x8e,0x70,0x91,0xc2,0xc7,0x50,0x5f,0xd3,0xe7, + 0xf3,0x4c,0x2a,0xd9,0xe7,0xd1,0xa1,0x2d,0xa2,0x4a,0x9e,0x84,0x57,0xaf,0x40,0x2c, + 0x23,0x2b,0x5c,0x5d,0x1a,0xf8,0xb9,0xc0,0xb4,0xc7,0xf0,0x56,0x5c,0x79,0xeb,0xa, + 0x2e,0x45,0xd0,0x92,0x9b,0xb5,0xec,0x94,0x44,0x2a,0xed,0x4b,0x3a,0x9a,0x9e,0x2d, + 0x9f,0x3c,0x4e,0x98,0x2,0x48,0x36,0x6a,0x9,0xb1,0x1f,0xd6,0xbc,0x74,0x22,0x6a, + 0xbb,0xd3,0xdb,0x5b,0x49,0x46,0xd5,0x21,0x46,0x6e,0x22,0x10,0xaa,0x3a,0xc5,0xa5, + 0xf,0xcc,0xb2,0x41,0x33,0x25,0x82,0x1d,0x91,0xae,0xd8,0xf8,0x2d,0xdb,0x28,0x4c, + 0x72,0x22,0xb3,0xda,0x84,0x7b,0x69,0xc6,0xdb,0x23,0x5b,0x65,0x87,0x97,0xed,0x73, + 0x1f,0xa2,0x51,0x3b,0xe7,0x23,0x5c,0xd3,0x85,0x18,0x9e,0x59,0x6e,0xe6,0x56,0x42, + 0xf8,0xd2,0xb5,0xa4,0x58,0x4,0x53,0x84,0x61,0x5d,0x70,0x3f,0xe9,0x60,0x1a,0xed, + 0xcd,0xd1,0xa5,0xe0,0x3a,0x4e,0x35,0x70,0x1e,0xba,0x64,0xe1,0x55,0xa3,0xed,0x96, + 0xf5,0x21,0x79,0x1e,0x39,0x2e,0x47,0x5e,0xa,0xe2,0xca,0xad,0xf6,0x99,0xeb,0xe1, + 0x5f,0x8e,0x50,0xe4,0xdc,0x4f,0x60,0xde,0x36,0x76,0x85,0x1a,0x44,0x2c,0x42,0x93, + 0x9f,0x23,0xb9,0x63,0xc4,0x8,0xc,0x6b,0x8,0xbd,0xeb,0x4a,0xc7,0xb5,0xc8,0xe8, + 0x2b,0xb8,0x23,0xf4,0xc8,0x37,0x20,0x79,0x83,0x6f,0xf6,0xa8,0x27,0xed,0x75,0x99, + 0x7d,0x16,0x3,0xde,0x84,0x92,0x5,0xa7,0x51,0xb4,0xfa,0x92,0x51,0x95,0xcc,0x3e, + 0xd7,0x82,0x53,0x15,0x11,0x88,0x35,0x97,0x2e,0xfc,0x26,0x9,0x63,0xb0,0x7c,0x8b, + 0x5f,0x64,0x63,0x57,0xa3,0x98,0xb9,0x8c,0x9f,0xa1,0x57,0x4a,0xc3,0x3c,0xf0,0x38, + 0x78,0x42,0x74,0x11,0x16,0xe,0xba,0xe2,0x8a,0xb2,0xc6,0xb5,0x37,0x6f,0xc,0x43, + 0x5e,0x60,0xcf,0x57,0x6b,0xe7,0x4a,0x3,0x1b,0x21,0x6f,0x32,0x2f,0x9c,0x3,0xc4, + 0x4e,0xd,0x70,0xe2,0xc7,0xad,0x5a,0x10,0xc6,0xb9,0xc9,0x59,0xb0,0x34,0x5f,0x46, + 0x97,0x66,0x58,0x7f,0x1e,0xc9,0x7e,0xb9,0x7c,0xf7,0x49,0xa9,0x6e,0x4f,0x68,0xd4, + 0x6a,0x81,0x11,0x1c,0xc0,0x15,0x2c,0x2e,0x81,0xb,0x58,0x25,0xd4,0xce,0x86,0xff, + 0x3b,0xf9,0xfa,0x91,0xd6,0xdd,0xad,0x23,0xd2,0x35,0x1a,0xc,0x57,0x8c,0xc1,0x74, + 0x4d,0x5e,0x74,0x9c,0x1,0x70,0x59,0x63,0xca,0x74,0x50,0xce,0x75,0xf7,0xb1,0x4a, + 0x97,0x4d,0xae,0xaa,0x10,0x3a,0x9b,0x11,0x25,0xe,0x84,0x48,0x8f,0x2d,0x34,0x68, + 0xde,0x9e,0x8c,0x78,0x2e,0x40,0xfd,0xd2,0x55,0xc6,0xdb,0xea,0xf7,0x5a,0x7b,0xfd, + 0xed,0xe9,0x55,0x37,0x46,0x70,0x39,0x44,0x9,0xc3,0xd2,0xb1,0x32,0x86,0x3d,0x3a, + 0x80,0x6c,0x93,0xb4,0x11,0x6b,0x34,0x62,0x42,0x9,0xeb,0x10,0x26,0x19,0x58,0x62, + 0x34,0x91,0x6c,0x6a,0x44,0xbf,0x5,0x15,0x92,0xaa,0xa2,0x4b,0x8b,0x20,0x2e,0xec, + 0x16,0x14,0x1c,0x1e,0x44,0xb2,0x57,0x6b,0x86,0xea,0x92,0x81,0xd8,0xce,0x64,0xed, + 0x25,0x4d,0x26,0x36,0x53,0x34,0x3c,0x64,0xda,0xa7,0x1,0xfe,0x5c,0x48,0x18,0x23, + 0xf1,0xd9,0x76,0xac,0x54,0x70,0xc5,0x2d,0x46,0x37,0x93,0x1d,0x75,0xf6,0x85,0x1d, + 0xf4,0xc3,0xe5,0xa9,0x87,0x3f,0x5d,0xd3,0xc6,0xcf,0x24,0x81,0x35,0xdb,0x99,0x9a, + 0x46,0x36,0xd4,0x54,0x64,0x30,0x29,0x5a,0xc1,0x87,0xc7,0xa6,0x3e,0xaa,0x4f,0x15, + 0xf0,0x80,0x3,0x37,0x11,0x14,0x56,0x68,0x63,0x3b,0x23,0x1d,0xa1,0x40,0x97,0x2c, + 0x2a,0x5a,0xa4,0xd4,0x1e,0xba,0x5c,0xfb,0xe2,0xe,0xa0,0xbb,0xc6,0xad,0xb8,0x90, + 0x6a,0x7f,0x10,0x3f,0x8b,0x3c,0xec,0xbd,0x3d,0x69,0x22,0x32,0x5a,0x12,0x4,0xcc, + 0xa8,0xbf,0x92,0xda,0xe3,0xd0,0x40,0xa,0x91,0x60,0x95,0x60,0xa2,0x86,0x35,0x9d, + 0xf7,0x52,0x96,0xd0,0x3c,0x6a,0x80,0x34,0xd1,0x91,0x79,0x32,0x60,0x39,0x20,0x6a, + 0x97,0x3,0xd2,0xa0,0x61,0x19,0x27,0x5,0x70,0x8b,0xdb,0xae,0x47,0xbe,0xdd,0xd5, + 0x76,0xcf,0xd4,0x5d,0xda,0x74,0xaa,0x63,0xb,0x91,0x68,0xc0,0xd0,0xd6,0x2f,0x2c, + 0x1,0xe6,0x12,0x50,0x29,0x33,0x48,0x42,0x1b,0x7c,0x66,0xb4,0xbf,0xd8,0x64,0x5, + 0x91,0x22,0x46,0xd1,0x4e,0xd0,0xeb,0x31,0xb2,0xe1,0xc3,0x7d,0x40,0x35,0x6e,0x93, + 0x8b,0xb4,0xf7,0x3d,0x3f,0xe2,0x7a,0xe8,0xa5,0x55,0x47,0x0,0xb3,0x5f,0x1c,0xed, + 0xbb,0x76,0x56,0xc8,0x6b,0xe0,0xa2,0x65,0xca,0x58,0xdf,0xe7,0x36,0x43,0x77,0x61, + 0x40,0x9e,0x9c,0xc6,0x63,0x7a,0x29,0x2a,0xef,0xbb,0x44,0xc9,0x96,0x40,0x57,0x15, + 0xa6,0x79,0x5,0x38,0x5f,0xaa,0x77,0x97,0x60,0x53,0x23,0xd9,0x20,0xc1,0xd8,0x26, + 0xe,0xd,0x7c,0x4d,0x16,0xb2,0xd8,0xca,0xcf,0x56,0xc3,0xb1,0x48,0x96,0x2f,0x24, + 0x66,0x1d,0x55,0x85,0x31,0x24,0xd,0x17,0xc0,0xc8,0x56,0xb7,0xf7,0xf2,0xaa,0x67, + 0x30,0x5,0x47,0xf6,0xfa,0x75,0x28,0x22,0xd1,0x20,0xc8,0xb,0xc1,0x98,0x68,0x23, + 0xe2,0xf9,0x1e,0x34,0xd8,0xf,0x6,0x89,0x5,0xb3,0xdd,0x18,0xb3,0xd1,0x69,0x1, + 0x6c,0x81,0xda,0x9f,0x4f,0xa6,0x34,0x26,0x9d,0x88,0xf8,0x11,0x6c,0x2c,0x5e,0x73, + 0xef,0xa9,0x1,0x46,0x5c,0x2c,0xe9,0x9,0x6f,0x75,0x6,0xf1,0xbe,0xe,0x3a,0x53, + 0xba,0x42,0xd,0x4f,0x58,0xf0,0x75,0xc1,0x82,0x39,0xe4,0x10,0x80,0xf5,0x34,0xf0, + 0x1a,0x1e,0x1e,0x60,0x56,0x5a,0x55,0xcb,0x1d,0xc0,0xb4,0xd7,0xaf,0x53,0x7,0x83, + 0x64,0x24,0xf3,0xa9,0xc8,0x4,0x7,0x6,0x8,0xb2,0x21,0xb1,0xba,0x31,0x11,0xd3, + 0x7,0xf0,0x43,0x4,0x37,0xeb,0xdc,0xdd,0x99,0xb4,0xc5,0x73,0xf5,0xc3,0x8d,0x7d, + 0x52,0x5,0x75,0x20,0x42,0xc9,0x88,0x16,0xee,0xcf,0x7b,0x5a,0x2c,0xd,0x8f,0xd2, + 0xe9,0x8,0x81,0xd7,0x86,0x9,0x1b,0x5b,0x82,0x2e,0x80,0x22,0x7,0xe6,0x48,0xc0, + 0x82,0x1d,0xcc,0x5b,0xd4,0x31,0xb4,0xd6,0xa3,0xf0,0xd4,0xa0,0x69,0x2c,0xdc,0x85, + 0x2d,0xb2,0xb6,0x68,0xd8,0xd6,0xbc,0x7f,0xe0,0x4a,0x45,0xfe,0x98,0x89,0x2d,0xf6, + 0xbe,0xc1,0x40,0xe9,0x8b,0x1,0xbf,0xfd,0xdc,0xf0,0x30,0xd6,0x7d,0x4f,0x70,0x75, + 0x4a,0x20,0x55,0xe9,0xe0,0xd9,0x51,0x43,0x3b,0x44,0xdb,0x4f,0xc6,0x2c,0xf7,0xb6, + 0x20,0x93,0x1d,0x6e,0xa4,0xd5,0x4d,0xee,0x61,0x1d,0xce,0xcc,0x80,0x23,0xf6,0xfd, + 0xaf,0xc6,0x58,0x99,0x5c,0xdb,0xf2,0x4,0x58,0x70,0x3a,0x22,0x18,0x23,0xa6,0x7a, + 0xd0,0x21,0xf0,0xa6,0xe9,0xf,0x34,0xa2,0x3c,0xaa,0xb7,0xa8,0x46,0x47,0x39,0x48, + 0xf2,0x85,0x98,0xa6,0x0,0x5a,0x97,0x45,0x91,0x15,0x54,0xc2,0xe4,0xd1,0x2e,0x4a, + 0x8e,0x53,0xc6,0xa9,0xe9,0x78,0xe7,0x25,0x7f,0x75,0xd9,0xfa,0x63,0xb9,0x76,0x7e, + 0xf7,0xad,0x87,0xf5,0x9c,0x31,0x1a,0x6,0xa1,0x51,0x63,0xa1,0xf1,0x32,0x20,0x79, + 0xf3,0x52,0x11,0xc5,0x38,0xa4,0xdf,0x33,0x23,0x6e,0x41,0xf6,0xda,0x5d,0xd1,0xbf, + 0xb9,0x2b,0x9a,0x7,0x5c,0x26,0x23,0x76,0x82,0x1b,0x87,0xc9,0x62,0x2e,0xd8,0xa9, + 0x57,0x71,0xee,0x1b,0x4d,0x39,0xc8,0x52,0xa1,0xaa,0x57,0x51,0xfb,0x20,0xef,0xb2, + 0x88,0xa3,0x1e,0xb1,0xf5,0xc8,0xca,0x60,0xf2,0x5d,0xfc,0xa9,0x82,0xd5,0x26,0x99, + 0x31,0xb4,0xad,0x19,0xfd,0xdc,0x49,0x3d,0x88,0xd1,0x5a,0xa0,0x64,0xfe,0xb,0xe, + 0x33,0x34,0xa2,0xc3,0x98,0x54,0x56,0x7a,0x34,0x81,0x80,0x2e,0x13,0xcb,0xc9,0x25, + 0x48,0xe6,0x4e,0x19,0xae,0x78,0x8e,0xbe,0x75,0xd9,0x5e,0xb4,0xf9,0xcb,0x69,0xbc, + 0x82,0xc3,0xd3,0x57,0xa5,0xbe,0xeb,0x76,0x30,0xb,0xf8,0x75,0x70,0x7e,0x2b,0xb5, + 0x77,0x45,0x54,0x64,0x61,0x7c,0xfc,0x8,0x61,0xa4,0xc0,0x3,0x11,0x55,0x73,0x38, + 0xcb,0xa5,0x81,0xc2,0x32,0x29,0x69,0x7,0xf,0xad,0x62,0xc4,0x0,0x83,0x63,0xc0, + 0xdf,0x81,0x9a,0x9,0x43,0x56,0xd5,0xb0,0xa1,0x2a,0x6c,0x24,0xa8,0x92,0x6a,0xe9, + 0x49,0x26,0x28,0x52,0x99,0x4e,0x38,0x4b,0x7,0xb2,0xb9,0x6d,0xe6,0x22,0x2e,0x50, + 0xb2,0xa0,0x24,0x58,0xbd,0x87,0xdc,0x13,0x4e,0x93,0x32,0x86,0xeb,0xba,0x77,0x80, + 0x51,0xd1,0x83,0x3e,0xb3,0xbd,0x26,0xf0,0x38,0xbf,0x77,0x35,0xd4,0xae,0xcd,0xae, + 0x77,0x59,0xe4,0x70,0xae,0x43,0xd5,0xd1,0x51,0xc0,0x8c,0x7f,0x2a,0x5c,0xc3,0x1c, + 0x39,0x42,0x92,0x26,0x5f,0x99,0xd7,0x78,0xe7,0xa3,0xf9,0x70,0xa3,0xc9,0x27,0x6f, + 0xfb,0x5f,0x97,0x5e,0xae,0x3d,0x99,0x82,0xd4,0xe5,0xf0,0x8a,0x1d,0x8c,0x59,0x6a, + 0x70,0x44,0xf0,0xc0,0xf2,0x56,0x23,0x18,0x88,0xbd,0x1b,0xd0,0x6c,0xc0,0x54,0xd5, + 0xfb,0xd4,0xbf,0x63,0x12,0xe5,0x62,0xcd,0x35,0x69,0x20,0x88,0xdc,0x63,0x7d,0x24, + 0x43,0x31,0x39,0x6f,0xa0,0x73,0x8a,0x50,0x2a,0xb5,0x1c,0x28,0x8e,0xc5,0xec,0x2d, + 0x43,0xdb,0x12,0x15,0x4a,0xa6,0x9a,0xba,0xc0,0xbd,0x11,0x31,0x73,0x43,0x38,0x81, + 0xa8,0xe8,0x3d,0xa1,0x71,0x54,0xe1,0x90,0x7d,0xaf,0x4,0x58,0x60,0x77,0xb5,0xaf, + 0x9e,0xc6,0xee,0x72,0xaf,0xca,0xfe,0xbd,0xdd,0xd6,0x3a,0xf7,0x79,0xf,0xee,0xc3, + 0x64,0x23,0xdd,0xe1,0x92,0x4d,0x3f,0x97,0x44,0x83,0x1a,0x21,0x4d,0x1d,0x37,0x17, + 0x71,0xd8,0x9a,0x1a,0x80,0x2c,0x80,0xfb,0x5c,0x60,0x85,0xb0,0x7,0xe4,0x50,0x25, + 0x11,0x5,0x11,0xcc,0x75,0xad,0x52,0x6a,0x12,0xba,0xd8,0x25,0x70,0x72,0x2f,0xc, + 0x22,0x11,0xee,0x34,0xa2,0x29,0xe9,0xfb,0x44,0x3,0xd1,0x82,0xab,0xfb,0x92,0x3b, + 0xd1,0x41,0x75,0x96,0xc5,0xa8,0x60,0xb2,0x14,0xe7,0x3c,0x9e,0x7f,0x54,0x91,0x95, + 0x79,0x54,0x36,0x49,0x2a,0x76,0x48,0xac,0xfa,0x38,0x65,0xf6,0x77,0xcb,0xd4,0x8b, + 0xe4,0xf0,0x45,0xd5,0x34,0xb4,0xe5,0x3d,0x2c,0x9f,0xfb,0x46,0xf4,0x72,0x1f,0xd1, + 0x17,0xa,0x49,0x2e,0x8d,0x63,0x50,0x65,0x33,0xc3,0xfe,0x3b,0x7a,0x55,0x83,0xb1, + 0x87,0x75,0xa0,0x75,0x43,0x94,0xd1,0x62,0x8f,0x62,0xa,0x3d,0x70,0x21,0xc,0x67, + 0xcc,0xb2,0xd,0x98,0x69,0x58,0x4c,0xf9,0x64,0xd,0x5a,0xa6,0xe,0x5,0x4f,0xb0, + 0x9a,0xb6,0xf5,0xe0,0x9c,0xd6,0x41,0xcf,0x43,0xe8,0x4d,0xa5,0x38,0x84,0x52,0xee, + 0x5a,0xfb,0x97,0xa1,0x4f,0xd9,0x87,0x35,0xf8,0x7a,0xc1,0xbf,0x12,0xc8,0x9e,0x84, + 0x8c,0x11,0x80,0x6,0x76,0xaf,0xda,0xa5,0x52,0x38,0x23,0x30,0xf3,0xa5,0x48,0xee, + 0x64,0x9f,0x75,0x16,0x3e,0xa6,0x1f,0xe4,0xf7,0x47,0xad,0x73,0xad,0xd2,0x4e,0xe5, + 0xc7,0xe8,0x5e,0x22,0xe0,0xeb,0x30,0xc4,0x21,0x5c,0x99,0xcf,0x2,0x1f,0xd3,0xc9, + 0x90,0xad,0xf,0x8b,0xd1,0x14,0xa,0x3d,0xc2,0x4c,0x1c,0x80,0x2c,0xc8,0x6,0xee, + 0x47,0x9f,0xd7,0x7c,0xf1,0x1d,0xc8,0xad,0x2,0x63,0xb8,0xb7,0x28,0xa8,0x7e,0xa, + 0x55,0xd,0x3a,0x9e,0xc5,0xbf,0x6a,0x58,0xad,0x9d,0xc0,0x7a,0x55,0xce,0x11,0x45, + 0x10,0x56,0x5b,0x60,0xf4,0x56,0x6f,0xba,0x8c,0x56,0xd5,0x10,0x90,0x3b,0x18,0xbb, + 0xf2,0xd3,0xab,0xa2,0x16,0xbe,0x36,0x47,0xe6,0xd4,0xe5,0xcc,0x13,0xc7,0x59,0x88, + 0xae,0x73,0xc0,0x3c,0xdb,0xd3,0xa6,0x5b,0xdb,0xde,0x1b,0x19,0xbb,0x18,0x8c,0x3f, + 0x3b,0x1c,0xaa,0x6,0xf1,0x7c,0xb9,0x18,0x43,0x5f,0xd1,0x67,0x44,0x93,0xb9,0xb8, + 0x34,0xa,0x7c,0xe9,0xd6,0x30,0xcf,0xcc,0x1,0x4e,0xd7,0x1e,0xe1,0x12,0xb7,0x28, + 0xc9,0x6a,0x45,0x60,0x62,0x43,0x40,0x9b,0x74,0x2,0xec,0xf1,0xa1,0xa6,0x7e,0x25, + 0xfd,0x1d,0x56,0xef,0xdd,0x2b,0x24,0x4a,0x74,0xa3,0xa,0x20,0x14,0xc6,0x42,0xb8, + 0xa5,0xab,0xb8,0xd5,0xf2,0xc1,0x7e,0x20,0xe8,0x4e,0x8e,0xa,0x8,0xba,0xe4,0x3e, + 0xa8,0x20,0xce,0xc4,0xf2,0xbd,0x1e,0x42,0x8d,0xb3,0xfb,0x61,0x4c,0xe0,0xd0,0x1d, + 0x46,0x76,0xf5,0x26,0x92,0x39,0xda,0x6f,0xf1,0x1e,0xde,0xfd,0xdf,0xab,0x27,0xa7, + 0x14,0xe8,0x13,0x61,0x8,0x64,0xae,0x74,0x3,0x21,0x91,0x91,0xad,0x42,0x1b,0x2, + 0x40,0xeb,0xbf,0x73,0xa0,0x53,0x3,0x8d,0xcb,0xd5,0xb3,0x6d,0xe2,0x28,0x68,0x94, + 0x4c,0xeb,0xe9,0x39,0x9b,0x1d,0xe9,0x90,0x61,0x37,0x7f,0x96,0x90,0x9b,0xf7,0x91, + 0x18,0x78,0x7f,0xda,0xa8,0xa0,0xcf,0x73,0xd5,0xf1,0x34,0xb8,0x43,0x93,0xc0,0xc6, + 0xb4,0xfd,0x53,0xc1,0xd8,0x17,0x68,0x56,0xa6,0x59,0xda,0x50,0x7e,0x8,0x62,0x40, + 0x26,0x2f,0xcc,0xde,0x36,0xba,0x2e,0x30,0x17,0x36,0xa9,0x96,0x5a,0x1b,0xe,0xf6, + 0x9b,0x57,0xf2,0xf,0x2f,0x2,0xba,0x8a,0x58,0x67,0xa9,0xbb,0x88,0xd4,0xd4,0x1b, + 0xd2,0x5d,0x93,0xcc,0x6f,0xc,0xf,0x2b,0xc8,0x9a,0x38,0x8c,0xd5,0x69,0x2,0x30, + 0xb5,0x36,0xe2,0x35,0x40,0x2,0xdc,0x69,0xf1,0xfb,0xba,0xb5,0x85,0x69,0x6c,0x60, + 0xf0,0xf3,0xc6,0x39,0x6e,0xce,0x95,0xe7,0x90,0x2,0x66,0xbb,0x87,0x59,0x74,0xe5, + 0xf7,0x5d,0x5d,0xa4,0xe8,0xe8,0x1,0xfe,0xa2,0x89,0x38,0xb5,0x40,0xb8,0x12,0x45, + 0xd7,0xe9,0x80,0x68,0xa6,0xf9,0x94,0xd2,0x10,0x20,0xa5,0x3d,0x84,0x6c,0x1f,0xb7, + 0xbe,0x96,0xa0,0xab,0x8f,0x0,0x14,0x74,0xd9,0x72,0xf1,0x4d,0x72,0xb9,0x3d,0xe4, + 0xe7,0x75,0x36,0x22,0xc7,0xfe,0xe4,0xc,0x13,0x11,0x34,0xac,0xf6,0x5f,0xcc,0x28, + 0xe8,0xc4,0x4,0x9d,0x98,0xfb,0x66,0x8f,0x80,0xce,0x6a,0x35,0xf2,0x7e,0x18,0x42, + 0x59,0x5,0xac,0xb,0x12,0x1c,0x2,0x35,0x65,0x53,0x8b,0x36,0x36,0x30,0x77,0x1c, + 0x31,0xe8,0x26,0x34,0xa9,0xc3,0x4e,0x50,0x41,0x63,0xba,0xbb,0x9d,0x69,0x83,0x95, + 0x53,0xd4,0x46,0x5,0x76,0x22,0xe8,0xa3,0xbf,0xca,0x49,0x77,0xa5,0x8c,0xca,0xee, + 0x66,0x95,0x9e,0xd9,0xca,0x62,0x67,0x16,0x29,0x4d,0xda,0xf,0x9d,0xa5,0x1f,0xac, + 0xf6,0x56,0xb,0xb2,0xef,0xb3,0x74,0x2b,0xda,0x9f,0x89,0xce,0xf8,0xe4,0x59,0x40, + 0xa1,0x9,0x6d,0x3c,0x50,0x17,0xbb,0x82,0xd7,0x1e,0x57,0x9,0x1,0x96,0xa8,0x4e, + 0x9c,0x68,0x3f,0xa9,0xe1,0x55,0x38,0x55,0xa1,0xc1,0xe2,0x8a,0xb0,0x54,0x3a,0xa9, + 0x4d,0x2d,0x3,0xa9,0x68,0xa8,0x53,0x9,0x3,0xf3,0x75,0x32,0xc0,0xe9,0x9a,0xd7, + 0x52,0x4a,0x47,0x83,0xaf,0x8d,0x3f,0x27,0x43,0x57,0x20,0xc5,0xd1,0x72,0x94,0x5a, + 0x75,0xa4,0x7c,0x52,0x6e,0xa3,0x3e,0x85,0xd2,0x3,0xc6,0xcc,0x99,0x99,0x44,0x50, + 0xba,0x41,0xcb,0x61,0x9e,0xce,0x48,0xaa,0x6c,0x4c,0x14,0xed,0xd3,0x33,0x78,0xf6, + 0x3,0x74,0x30,0x6,0x17,0xe,0x1e,0xd0,0xf3,0x75,0xd6,0x8b,0x64,0x2c,0x3,0xf1, + 0x65,0x62,0x28,0xe0,0xd9,0x74,0x47,0x7,0x2b,0x16,0xf2,0x46,0x91,0x25,0xae,0xc1, + 0xe2,0x13,0x2e,0x22,0xb0,0x48,0x54,0xba,0xa6,0xad,0x7a,0x84,0xb5,0xa4,0xa6,0x21, + 0xe6,0x2c,0xfa,0x7d,0xca,0x13,0x4d,0x2,0xdb,0x74,0x45,0xa2,0x67,0xb7,0x65,0x1c, + 0x7c,0xa8,0xda,0x2,0x5c,0xb8,0xf3,0x36,0x4,0xe4,0x41,0x2f,0xb0,0x1d,0x38,0x4d, + 0x4f,0xfe,0xfe,0x67,0x6d,0x1,0xa2,0x14,0x55,0xf5,0xf,0x7f,0xd8,0xef,0x4b,0x6f, + 0x9e,0x3,0xa2,0xb4,0xfe,0xfe,0xae,0x52,0x5d,0xbb,0xc9,0x3c,0x14,0xf4,0x70,0x52, + 0x62,0xa8,0xb5,0x58,0x9,0x71,0x38,0x53,0xc2,0x1b,0xe3,0x5c,0x1b,0xa,0x3a,0xfd, + 0x73,0xe2,0x80,0xc0,0xfb,0xe7,0x7a,0x1,0xc2,0x66,0x6d,0x44,0x37,0xcd,0xf6,0x82, + 0xf3,0xd1,0xb6,0x50,0xd7,0xb5,0x52,0x52,0x5c,0xd5,0xad,0x52,0x15,0xfa,0xc2,0x41, + 0x60,0x0,0x5e,0xcd,0x23,0xbb,0x5d,0x1c,0x6,0x62,0x8a,0x9b,0xd3,0xcf,0x23,0xc0, + 0xe3,0x26,0x2a,0x9d,0x99,0x74,0x98,0xd9,0xa5,0x85,0x60,0x90,0xd2,0xd7,0x1f,0x5d, + 0x8d,0xaf,0xa0,0x15,0x11,0xea,0x12,0x45,0xc0,0xab,0x59,0x95,0x96,0x42,0x9d,0x2b, + 0xa9,0xb8,0x76,0xc6,0xa5,0x6c,0x66,0xb8,0x4,0xa3,0x67,0x5d,0xe5,0x33,0xdf,0xa8, + 0x3e,0xb3,0x2f,0x7d,0x35,0x4e,0x52,0x82,0xb5,0x25,0x48,0x7d,0xbe,0x96,0xa,0x52, + 0x74,0x32,0x56,0xd,0x15,0x8b,0x54,0x4b,0xc8,0x67,0x9a,0xfc,0x7,0x6d,0xc2,0xc7, + 0xf8,0x4c,0xa9,0x3c,0x65,0x55,0x23,0xe2,0x3d,0x8,0x84,0xcd,0x3c,0x3f,0xec,0x52, + 0x4d,0xfb,0x6d,0x4e,0x18,0xae,0x5c,0xa6,0xd8,0xc0,0x1a,0x80,0x3d,0x94,0xbf,0x98, + 0xca,0x44,0xa3,0xa8,0xec,0x2c,0xbb,0x91,0x96,0x2a,0xc5,0x5,0xca,0x65,0xa3,0xaa, + 0xed,0x9,0x17,0x66,0x18,0x4a,0x70,0x1c,0x74,0xc5,0x2b,0x3,0xe7,0x4d,0x9a,0x9c, + 0x5a,0x6e,0x83,0xf6,0x29,0x32,0xca,0x34,0xa2,0x56,0xbc,0xe6,0xaa,0x79,0x30,0x1, + 0xaf,0xaa,0xa8,0x5c,0x3e,0xf1,0x99,0x8d,0xdc,0x19,0x72,0xab,0xcd,0x6,0x19,0x21, + 0x18,0x75,0xbd,0xe8,0x31,0x66,0xbb,0x62,0x92,0x55,0x75,0x72,0x67,0x12,0xbb,0x5c, + 0xcf,0x62,0xef,0x68,0x60,0x60,0x4f,0xc7,0x8f,0x4d,0x2d,0x8,0x34,0xa4,0x43,0xb8, + 0x29,0x8a,0x72,0x0,0x36,0x14,0xe0,0x5a,0xdc,0xca,0x9,0xba,0x83,0x8d,0x4d,0xc4, + 0x28,0xb9,0x6d,0x4a,0xd8,0x76,0xd5,0x46,0x95,0x66,0x8d,0x41,0x67,0xf5,0xd,0x58, + 0x64,0xb3,0x69,0x34,0xb4,0x2a,0xf4,0x20,0x3a,0xa1,0xb5,0x6a,0xa3,0x9b,0x59,0x3d, + 0x2a,0xd9,0x4f,0x13,0x95,0xad,0xbf,0x10,0xf3,0xf2,0x4f,0x80,0x74,0xef,0x53,0x27, + 0xec,0xa9,0x76,0xc5,0xe8,0x99,0xba,0x91,0x5e,0x83,0xf2,0x95,0x24,0x8b,0x89,0xc7, + 0x32,0x9f,0xb7,0x9,0xd7,0x4f,0x2c,0xf6,0x87,0xbc,0x9d,0xe8,0x31,0x47,0x4,0x26, + 0x92,0xae,0xab,0xf3,0xf2,0xba,0x36,0x6,0x5a,0x42,0x86,0xba,0x22,0x60,0xb,0x89, + 0xf,0x8,0x66,0x3,0x16,0x2e,0x31,0xed,0x70,0x63,0x4,0x27,0xa3,0x70,0x2d,0xb7, + 0x65,0x9d,0x8c,0x36,0xbb,0xd9,0xd8,0xea,0xc2,0xec,0x43,0xe8,0x5b,0x3b,0x33,0x19, + 0x43,0x40,0xf0,0xbe,0x8c,0x6e,0xea,0x5c,0x80,0xd0,0x9,0xff,0x95,0x45,0x73,0x7, + 0xb,0x4a,0x25,0x1d,0xec,0xdb,0x49,0x92,0x11,0x76,0xdd,0xb0,0x1,0xff,0xb5,0xa8, + 0x25,0x4d,0xee,0x8c,0x70,0x57,0x2a,0xdb,0x37,0x62,0x98,0xa7,0xb6,0x73,0xc7,0x3, + 0x76,0xb2,0xfb,0x75,0x66,0xfd,0x89,0xf8,0x57,0x1d,0x60,0x46,0xfb,0x3e,0xbe,0x24, + 0x6d,0xb4,0xea,0xd8,0x18,0x9d,0x1c,0xa6,0x1d,0x38,0xcc,0x7c,0x1f,0x86,0xd6,0x47, + 0x71,0xe6,0x99,0x61,0x8c,0x26,0xb6,0x81,0xce,0xb2,0x6f,0x6c,0x56,0xd5,0xef,0xff, + 0xe,0x90,0x1e,0x6,0x1,0x2a,0x85,0xbe,0xf4,0x79,0x5c,0xd5,0xd7,0xe9,0x8,0x5f, + 0xea,0xa9,0x70,0x5,0x7b,0x39,0x75,0xe3,0x3b,0xed,0x4c,0xfc,0x91,0x64,0x8c,0x67, + 0xd0,0x45,0x27,0x6c,0x42,0x40,0xff,0x17,0xa9,0xe7,0xa0,0x24,0x4e,0x26,0x84,0x8b, + 0xd6,0x1e,0x80,0x32,0xb5,0x31,0x91,0xcc,0x42,0x1c,0xc7,0x6c,0x52,0xfd,0x35,0x2c, + 0x95,0x2f,0x86,0xf5,0xc6,0x37,0xf4,0x9e,0xe4,0x4f,0xf1,0x7e,0x6,0xec,0xcf,0x64, + 0x42,0xbb,0x9b,0x7f,0x98,0xb1,0x94,0x13,0xa6,0x60,0x1d,0x29,0x38,0xdf,0xe7,0x91, + 0xa1,0x6d,0xda,0xfb,0xfd,0x1c,0xf3,0xc6,0x1e,0xed,0x90,0x70,0xf6,0xfe,0x16,0x7f, + 0xb2,0xc4,0x86,0xf0,0xe5,0x8b,0xd4,0x5d,0x97,0x16,0x89,0xb2,0x98,0x31,0xeb,0xef, + 0x3b,0x47,0x5,0x7d,0x19,0x6a,0xeb,0x11,0xa1,0x37,0xa0,0xc2,0x2d,0x6e,0xef,0x11, + 0x41,0xe,0x86,0xc6,0x56,0x22,0x21,0xd8,0x81,0x26,0x7,0x98,0x52,0x82,0x7d,0x4d, + 0x79,0xc0,0x27,0x5c,0x30,0xea,0xeb,0x8b,0x88,0x4e,0x16,0x45,0x15,0x9e,0x9,0x5, + 0x87,0xd2,0x9b,0x94,0x96,0x1a,0x6e,0x25,0xd1,0xd3,0x93,0x54,0x46,0xb0,0x4d,0xc9, + 0x59,0x20,0xef,0x35,0x1c,0xd5,0xc8,0xb3,0x83,0xdd,0x2f,0xa2,0x72,0x5a,0x22,0x8f, + 0x6b,0xd4,0x80,0xc2,0xf5,0xce,0x3f,0xe0,0x54,0xdc,0xcb,0x52,0x55,0xab,0x32,0x6, + 0x61,0xe2,0xa5,0xce,0xa6,0x6c,0xca,0xb0,0x94,0xcc,0x1e,0x96,0x69,0xa7,0xe2,0x8, + 0xd3,0x5,0x26,0xd5,0x99,0x8,0x2,0x89,0xb4,0x6b,0x23,0xe6,0xa6,0xd0,0x64,0x84, + 0x2,0xfa,0x8,0x1a,0x26,0x22,0x48,0x45,0x4f,0xfb,0x24,0x48,0x93,0x7,0xdc,0x81, + 0x54,0x71,0xe1,0x98,0x34,0x8d,0xd,0x9e,0x88,0x77,0xaf,0x5c,0xa3,0x7c,0xd6,0xf3, + 0x1c,0x46,0xcb,0xec,0x6a,0x7c,0xc1,0x22,0x36,0xee,0x54,0xc5,0x6f,0x7d,0xe4,0xa0, + 0x56,0x3d,0x23,0x5c,0x18,0xc4,0x97,0x3,0x76,0x1f,0x62,0xaf,0x23,0xfc,0xa,0x21, + 0x1,0xf1,0xeb,0x52,0x61,0xed,0xd0,0xae,0x29,0x9f,0x4e,0xf0,0x71,0xc3,0x61,0xde, + 0xb,0xa2,0xe2,0x54,0xae,0x9f,0xce,0x27,0xf9,0xa3,0xce,0x86,0x32,0x44,0x73,0xd5, + 0xd4,0x48,0x93,0xb8,0x74,0x88,0x2b,0x9b,0x7f,0xd5,0xfb,0x3e,0x2b,0x18,0xa2,0xf5, + 0x4f,0x76,0xb,0x8,0x56,0xd0,0x41,0x2b,0x9c,0xc5,0x66,0xdf,0x89,0x34,0x6d,0xec, + 0x8e,0x86,0xb2,0xa1,0x14,0x2,0x45,0x67,0x4f,0x33,0x93,0x6e,0x4f,0xb0,0x58,0x79, + 0x9f,0x7d,0x96,0x16,0x31,0x17,0x5d,0x8d,0x98,0xd8,0xcd,0x34,0x28,0xc4,0xae,0x69, + 0x8,0xf3,0x6b,0x3e,0x17,0x3d,0x19,0x37,0xb4,0x33,0xfb,0xa9,0xd1,0x3b,0xbd,0x74, + 0x6d,0x5e,0x5a,0xbb,0xf,0xf9,0x99,0x2b,0x36,0xaa,0x39,0x8d,0x9d,0xdb,0x17,0xbc, + 0xea,0x7,0x5e,0xa0,0x21,0x88,0xeb,0x9d,0xa8,0x0,0x38,0x51,0xc4,0x5c,0xe9,0x2d, + 0xf6,0x15,0x1b,0x32,0xd1,0x5b,0x13,0x6a,0x9b,0x4a,0xf3,0x6b,0xe0,0x42,0xfc,0x94, + 0x4f,0xe5,0xc5,0x1d,0x8c,0x15,0x3e,0x4f,0x39,0xc0,0x9e,0x1b,0x80,0x81,0xaf,0x20, + 0x5,0x17,0xf5,0x9,0xd0,0xd4,0x25,0x3d,0x64,0x61,0xbb,0xb3,0x81,0xb,0xe9,0xb3, + 0x33,0x48,0xd4,0xde,0xca,0x46,0xaf,0x3,0xe9,0x8b,0x42,0xd3,0xd4,0xe5,0xb0,0x35, + 0x21,0xd4,0x70,0xa9,0xdf,0x44,0x93,0xa2,0x8b,0x6a,0x21,0x46,0xcc,0x9a,0x24,0xdc, + 0x9e,0x68,0xc8,0x71,0xea,0x1c,0xcd,0x46,0x20,0x30,0x88,0x64,0xf1,0x39,0x2f,0xdf, + 0xb2,0x3f,0xfa,0x9a,0x8,0x54,0xe7,0x53,0x39,0x9,0x37,0xd6,0xb,0x81,0x9b,0x39, + 0x54,0xb5,0x66,0x7f,0x23,0x46,0x5d,0x71,0x39,0x26,0xa,0x76,0xdd,0x3d,0x9a,0xfb, + 0x45,0x57,0xcd,0x5e,0xc9,0x2a,0x4c,0x52,0x69,0xe,0xd3,0xcd,0x41,0x95,0x1a,0x4e, + 0x72,0x86,0x45,0x49,0xf7,0xa1,0x4d,0x7f,0xea,0xd4,0x5,0xef,0x66,0xd9,0xfe,0x7d, + 0xd,0xd5,0xde,0xf,0x98,0xab,0x4f,0xa4,0xfd,0xfd,0x9a,0x3c,0x5b,0xcd,0xf,0x7b, + 0xb,0x9c,0xf4,0x99,0xf8,0x4d,0x2c,0xe2,0xce,0x92,0x9b,0xa,0x59,0xc9,0x78,0x19, + 0xb6,0xc,0xeb,0xe3,0x17,0x1e,0xfe,0xd6,0xcf,0xa6,0x24,0xd1,0x24,0xc3,0xba,0xb2, + 0x99,0x78,0x65,0x23,0x4,0xfb,0x8d,0x39,0xbc,0x9f,0xd5,0x7a,0x29,0xd1,0x6c,0x62, + 0x2b,0xc9,0x7a,0x88,0x63,0x26,0xa6,0xc5,0xb4,0x7f,0x45,0x1d,0x5d,0x8c,0x4,0x24, + 0x8d,0x94,0x56,0xae,0x9c,0x4c,0xd9,0x75,0x8,0x74,0x9b,0x50,0x93,0xc9,0x2c,0x76, + 0x67,0xb8,0x0,0xc6,0x19,0xf0,0x5a,0x83,0x9b,0x57,0x24,0xea,0xde,0x89,0x9d,0x4, + 0x98,0xdf,0x3f,0x29,0x1f,0x66,0x52,0x85,0xa3,0xa2,0x2c,0xc2,0x37,0x20,0x9,0x88, + 0xae,0xa2,0xc5,0xf0,0x41,0xb9,0xab,0xe0,0x2b,0x19,0xd2,0x61,0x0,0xa2,0x53,0x26, + 0x31,0xfb,0xce,0xf2,0x39,0x6d,0x2a,0x61,0x77,0x99,0x2f,0xa9,0x8f,0x3c,0xc7,0xbe, + 0xbf,0xb5,0x6d,0x6a,0x96,0x84,0x5f,0x23,0x79,0xac,0x2e,0x47,0xbf,0x2c,0x74,0xc5, + 0x8b,0xe2,0xe1,0x87,0x8,0xdb,0xf8,0xb6,0xe,0x14,0xb4,0x2d,0x6b,0xe8,0xda,0xe3, + 0x67,0x93,0xc1,0x8b,0x72,0x83,0x98,0x43,0x93,0x6c,0xbc,0x1a,0xa5,0x8c,0x6c,0x7b, + 0x60,0x69,0x1,0x3e,0x7f,0xc6,0x90,0xbe,0x4d,0x25,0x42,0x19,0x9d,0x4d,0xd6,0x26, + 0x4,0xd6,0x62,0xb6,0xe,0x4b,0x2d,0x79,0x85,0x6a,0x3b,0x14,0x2b,0x86,0x2a,0xb1, + 0x46,0xa4,0x8d,0xec,0xf9,0x8,0x12,0x5a,0x63,0x1d,0xb4,0xb8,0xd2,0x56,0x36,0xc1, + 0xde,0x6b,0xf0,0xa7,0xf0,0x55,0x8e,0x53,0x1c,0xc4,0xb7,0xfe,0xec,0x5,0xc9,0x63, + 0xa4,0xce,0xf3,0xc5,0x87,0xea,0x5e,0x9a,0x8d,0xb,0xae,0x38,0x73,0xde,0xfa,0xbc, + 0x5a,0xdc,0x5b,0x76,0x77,0x5f,0x54,0x48,0xdc,0xe8,0x3,0xd6,0x99,0x72,0xf8,0xa6, + 0xd2,0xa1,0x2d,0xca,0x7b,0x37,0x3f,0x23,0xa4,0x12,0x9f,0x1e,0x50,0x6d,0x96,0xe1, + 0xe3,0x94,0xb6,0x5c,0x70,0x44,0x55,0x6a,0xc1,0x14,0x4c,0xd7,0x9d,0x98,0x7c,0x87, + 0xab,0x50,0x31,0xc5,0x40,0xdb,0xb0,0x77,0x99,0x1,0x8,0x59,0x27,0x9,0x65,0x21, + 0x87,0x84,0x16,0x34,0x3c,0x85,0xe8,0x49,0x84,0x4b,0x70,0xea,0xc,0x36,0x2,0x5b, + 0x9b,0x85,0x91,0xc4,0x1d,0xf,0x33,0x39,0xc8,0xf4,0x89,0x31,0x39,0xa4,0xbb,0xf, + 0x3c,0xb2,0x57,0xe5,0x71,0x32,0x36,0xd,0xca,0x11,0xe2,0x64,0xca,0xaa,0x4f,0x71, + 0xaf,0xac,0x92,0x77,0x9c,0x41,0xcb,0x7d,0x50,0xfa,0x1c,0xc8,0xb4,0x35,0x57,0xf2, + 0xb0,0x60,0x3d,0xe,0x1e,0xc5,0x34,0x9d,0x69,0xe7,0x8f,0xc,0xc4,0x33,0x44,0x32, + 0xc6,0xc1,0xd3,0x9d,0x7e,0xb4,0x30,0x64,0x8a,0x91,0xc2,0x6,0x72,0xe8,0x33,0x69, + 0x98,0xa0,0x23,0x61,0x7a,0x7f,0x75,0x8e,0x78,0x52,0xd9,0x48,0x37,0x32,0xe3,0x8e, + 0xb8,0x2e,0xb9,0xd0,0x83,0xc,0xda,0xb5,0x0,0x91,0xec,0x1f,0xd0,0x7b,0xb3,0xba, + 0x4d,0x94,0xd5,0xce,0x24,0xca,0xd2,0x8,0x59,0xa5,0xfe,0xd7,0xc1,0xda,0x85,0x28, + 0xe9,0xed,0x9c,0x38,0x13,0xbb,0x1a,0x3c,0x74,0x20,0xea,0x96,0x33,0x49,0x8d,0xa1, + 0x78,0x3a,0x11,0x32,0x4b,0xc9,0x7b,0xc4,0x5c,0xcb,0x68,0x50,0x1b,0x80,0x36,0x43, + 0x1f,0xe8,0x6b,0x84,0xc1,0x63,0x4,0x7a,0x60,0x62,0x1b,0xb3,0x1c,0xa2,0x1c,0x93, + 0xc7,0xe9,0x81,0x7e,0xb8,0x68,0x4f,0xe,0x87,0x5e,0x73,0xe7,0x33,0x44,0x55,0x9e, + 0x2d,0x80,0x81,0x81,0x8f,0x30,0x98,0xc1,0x40,0x8,0x9d,0x48,0xab,0xc0,0x29,0x6a, + 0x72,0x8e,0x8f,0x46,0xc,0x8c,0x44,0x4b,0xcb,0xa8,0xbb,0x58,0x13,0x45,0x80,0x7e, + 0x9e,0xaa,0x6a,0xea,0xc5,0xc1,0x8c,0xc,0x87,0xf8,0x1d,0x49,0xd7,0x35,0xb8,0xc6, + 0x84,0x79,0x54,0x73,0x15,0x33,0x44,0x5c,0x4d,0x6d,0x9c,0xab,0x95,0xaf,0x7b,0x92, + 0x3e,0xbc,0xfd,0x91,0x9f,0xfc,0xb1,0x79,0x71,0x71,0xf,0xe8,0xe7,0x34,0x46,0xca, + 0xf6,0x69,0x76,0x49,0x1d,0x82,0x36,0xa8,0x8c,0x6d,0xf4,0x8d,0xe4,0x38,0xf,0xf8, + 0x40,0x2f,0xc4,0xb7,0xf3,0x1b,0xa6,0x96,0xeb,0x50,0x14,0xf3,0xcc,0x13,0xad,0x74, + 0x8,0xac,0x1a,0x88,0x40,0x87,0xef,0xe7,0x37,0x78,0xb4,0xe3,0x6b,0x52,0x84,0xe6, + 0xf8,0x19,0xe1,0xa6,0x93,0x7c,0xe0,0x41,0x8d,0xf6,0x6c,0xaa,0x35,0x89,0x9d,0xa6, + 0x5e,0x45,0x77,0x5c,0xdb,0x81,0x9,0x71,0xd8,0x37,0x5d,0x99,0x55,0xc1,0x27,0xc7, + 0x5,0xd3,0x26,0x3c,0xfc,0x36,0x62,0x23,0x6,0x68,0xdf,0xb9,0xf5,0x9e,0xdd,0x8f, + 0x5,0x26,0x35,0x6a,0x36,0xa3,0x84,0xaf,0x12,0x4d,0x6,0xa8,0x2,0x2b,0x65,0x9a, + 0xdc,0x7a,0xd,0xfa,0x63,0xda,0xf4,0x81,0x7a,0x17,0x28,0x93,0x36,0xe5,0x70,0xc9, + 0x50,0x6c,0x73,0x3b,0x40,0xe6,0xbe,0xb0,0x75,0xb9,0x17,0x31,0x13,0xa6,0x8c,0xb4, + 0xd0,0xd4,0x1,0x54,0x9e,0xb4,0x2d,0x10,0xd5,0xc4,0xe6,0x42,0x98,0x92,0xc7,0x77, + 0xda,0x3b,0x2f,0x17,0xee,0xd1,0x9d,0xcd,0xf3,0xc,0x7c,0xc7,0xfd,0xf3,0xdd,0x5e, + 0xf4,0xfa,0xfb,0x8e,0x2e,0x6c,0x47,0xe,0xfb,0x21,0x78,0x1c,0xff,0x73,0xfa,0x8c, + 0x93,0x4c,0xf2,0x49,0x3a,0x39,0x9,0x9e,0xfc,0x77,0xb8,0x1e,0x7c,0xe3,0xf5,0xc3, + 0xdf,0xdb,0x40,0x35,0xfc,0x30,0xe4,0xec,0x38,0xa8,0x76,0xc6,0xde,0x4a,0x62,0x30, + 0xf2,0xe3,0x4,0x55,0x6e,0x4,0x43,0x32,0x76,0x5a,0x58,0x22,0xb6,0x1,0x32,0x90, + 0x4c,0x61,0xe4,0xeb,0x74,0xc8,0x74,0xaa,0xc4,0xa5,0x34,0x99,0x7e,0xcd,0xae,0x72, + 0xe6,0x3b,0x1d,0xd1,0x98,0x2,0x4d,0x91,0x33,0xa4,0xea,0xb6,0x29,0xcb,0x45,0xd1, + 0x39,0x16,0xeb,0x1c,0x4,0xbd,0xe,0x6e,0xa9,0xf9,0x44,0xe3,0xef,0x2e,0xd4,0xac, + 0x4e,0x83,0x2e,0xdf,0x1c,0x2d,0x9e,0x1,0xea,0x23,0x86,0xca,0x6f,0x16,0x34,0xf8, + 0xfa,0xbf,0xcb,0x88,0x26,0x29,0x93,0x38,0x70,0x75,0xa3,0x6,0xbb,0xfa,0x98,0x69, + 0xcc,0x6d,0x2b,0xbc,0xc3,0xe6,0xbd,0x5d,0xf3,0x3c,0x72,0x72,0x62,0xa2,0x3f,0x37, + 0x12,0xd5,0x94,0xd8,0x54,0x2e,0xc9,0x57,0x2f,0xbe,0x8b,0x6d,0x1,0x6a,0x8f,0x33, + 0xb2,0xf4,0x81,0xc5,0x6f,0x95,0x6d,0x38,0xd9,0x29,0xa4,0xe6,0x4,0xbb,0x80,0xfd, + 0x80,0xb6,0x7,0xb5,0x87,0xc3,0xec,0x43,0x9b,0x14,0x2e,0x83,0x5a,0x12,0xec,0x56, + 0xa4,0xc6,0x74,0xef,0x23,0xad,0x67,0x44,0xb8,0x9c,0xa1,0x48,0x5f,0xda,0xa8,0x61, + 0xac,0x29,0xe8,0xbc,0xfd,0x3,0x4f,0x62,0x13,0x9d,0x76,0xaf,0x16,0xf2,0x7b,0x95, + 0x1d,0x1c,0xb2,0x97,0xe8,0xe4,0x38,0xd5,0x99,0x26,0xf5,0xfa,0xa2,0xa2,0xc9,0xe9, + 0x6,0x4,0xfb,0x5d,0xa1,0x7d,0xc,0x5,0xd2,0x4a,0x32,0x2f,0xb9,0x45,0x31,0x21, + 0x30,0xf4,0xdb,0x90,0xf7,0x73,0xc4,0x2a,0xaf,0x20,0xe,0xa2,0xb7,0x59,0x51,0x8d, + 0xbb,0x80,0x63,0x9b,0x2d,0x2b,0x54,0x74,0x92,0xa7,0xbd,0x4,0x3,0x12,0xd3,0xdb, + 0x76,0x5e,0x21,0xa2,0x66,0x1d,0xdf,0xc3,0x35,0xa4,0x3d,0x57,0x63,0x1a,0x71,0x73, + 0x9,0x6,0x57,0x34,0x67,0xf1,0x77,0xc4,0x27,0xef,0xef,0x49,0x6b,0xa0,0xff,0x46, + 0xfa,0x59,0x86,0x1e,0xa8,0x3a,0xf1,0x70,0xb0,0xdc,0x33,0xa2,0xf1,0xfe,0x3d,0x90, + 0x7d,0xe3,0xad,0x5e,0xa,0xf7,0x29,0xd9,0xcd,0xf,0xf9,0x90,0x47,0x3d,0xf4,0x42, + 0xc,0xed,0xc2,0x11,0x44,0x9b,0xcd,0xe,0xb6,0x96,0x9d,0xe3,0x56,0x10,0xa2,0x69, + 0x70,0x81,0x5e,0xd5,0x17,0x53,0x12,0x15,0xbd,0x58,0x50,0x52,0x76,0xf9,0x96,0x56, + 0x6e,0x86,0x49,0x1c,0xb4,0xa0,0x5,0xdb,0x67,0xd9,0xde,0xa6,0xa2,0x4f,0xf7,0x64, + 0xd3,0x3e,0xec,0xd1,0xc6,0xd6,0x79,0x40,0x2b,0x1a,0x3f,0x82,0x35,0x8a,0x4e,0x6d, + 0x69,0xe8,0x9c,0x26,0xc1,0x20,0x12,0x85,0xa6,0x2b,0xf2,0xa6,0x4c,0xe5,0xee,0x58, + 0x39,0xbb,0xe4,0xee,0xec,0xc9,0x15,0xd4,0x9e,0x31,0xa3,0x45,0x68,0xca,0x54,0x47, + 0xaa,0xf3,0x55,0x5,0xb1,0x1,0x4c,0x92,0x15,0xc1,0x5c,0x72,0xcc,0x2c,0xe6,0xb6, + 0x7,0x5,0x67,0x7b,0x56,0x5a,0xd2,0x27,0x6e,0x3c,0xa5,0x42,0xfc,0xcf,0x73,0xa1, + 0x90,0x13,0x22,0xe1,0x97,0x72,0x16,0x81,0xaf,0x6e,0xc7,0xa8,0xf4,0x4c,0x81,0x18, + 0x23,0x18,0x84,0xe1,0xc3,0xfc,0x15,0x33,0xd3,0xcd,0xec,0xa0,0x82,0x3,0x20,0xea, + 0x69,0xcf,0xe8,0x47,0x6,0xe3,0x11,0x32,0xb4,0xb4,0xd4,0xf,0x4c,0xd5,0xe,0x1e, + 0x8a,0x0,0xc,0x59,0x60,0x4d,0xb3,0xe6,0xa3,0x9e,0x7f,0xef,0x67,0xd,0x83,0x4, + 0x75,0x30,0x7,0x1f,0xfb,0x53,0x78,0xd1,0x7f,0xca,0xe0,0x8f,0xa6,0x10,0x56,0x2f, + 0xc8,0x98,0x53,0x35,0x35,0x59,0xe6,0x42,0x44,0x4e,0xaa,0x66,0x9f,0xd1,0x43,0xe5, + 0x34,0x95,0xa7,0x69,0x9c,0xa1,0x9a,0x9d,0x2f,0xca,0x4d,0xd5,0x3a,0x3b,0xfd,0x20, + 0xa0,0xbb,0xaf,0x1d,0xd,0x3a,0x2,0xdd,0x80,0xba,0x86,0x85,0xe3,0x95,0x56,0x13, + 0x23,0xf6,0x18,0x92,0xbd,0xda,0x1e,0xa0,0x19,0x5d,0x78,0x42,0xf8,0xf4,0xc5,0xbb, + 0xc,0x0,0x4,0x3d,0xc2,0x88,0x38,0x28,0xda,0xc0,0x41,0x92,0xf3,0x71,0xd7,0x32, + 0xa7,0x35,0x78,0x8b,0x62,0x79,0x75,0x8f,0xfb,0x46,0xa,0x83,0x4c,0xee,0xca,0xdb, + 0xd,0x93,0x2a,0x6b,0xd1,0xc7,0x76,0x73,0xef,0x12,0x6e,0x16,0x85,0x9c,0x1c,0x60, + 0x10,0x55,0xf3,0x9a,0x88,0x7e,0xfb,0xb,0xdd,0x14,0xb3,0xca,0xd4,0x8,0x4d,0x1a, + 0x1a,0xe9,0xb1,0x1e,0x23,0x86,0x36,0xc8,0x74,0x59,0x4b,0x2b,0x47,0x89,0x75,0x0, + 0x81,0x8,0x85,0x40,0xad,0xea,0xe1,0x3a,0xe9,0x44,0x75,0xa5,0xbf,0x5c,0xed,0x40, + 0x1b,0xad,0x56,0xf9,0xe5,0x96,0x7c,0x44,0x79,0xa4,0xa3,0xc5,0x86,0xd6,0xd,0xc6, + 0x34,0x5f,0x31,0x81,0x8b,0x57,0xb1,0xfd,0xc8,0xd1,0xbc,0x37,0xdc,0x1c,0x93,0xc1, + 0x3b,0x99,0x12,0x25,0x8d,0x7a,0xa3,0x9c,0x97,0x35,0xc6,0xa8,0x16,0xda,0x45,0xf1, + 0x3a,0xd8,0x48,0xc6,0xdb,0xfe,0x7c,0xed,0x39,0x8a,0x20,0xc,0x27,0xd2,0x83,0xc3, + 0x36,0x8b,0x8,0x33,0x10,0x1f,0x12,0x4b,0x74,0x12,0x6,0x6,0x9d,0x7,0x34,0x19, + 0xd2,0x74,0x84,0x6a,0xd9,0x51,0x8b,0xb,0x5b,0x72,0xb0,0xb9,0x7f,0x8f,0x8e,0x95, + 0x31,0xa0,0x4f,0xcc,0x59,0x56,0xc8,0x2c,0x22,0xfa,0x79,0x1a,0x74,0xbd,0xce,0xe7, + 0x76,0x80,0x83,0x7b,0x87,0x7,0x2d,0xb6,0xf5,0x92,0x4e,0x8a,0x55,0x38,0xf4,0xbf, + 0xce,0xa,0x68,0x3b,0x29,0xfa,0x5f,0x3e,0x7e,0xfc,0x5e,0x55,0xf5,0x5f,0xbd,0xff, + 0x47,0x1f,0x4d,0x99,0xc5,0x3e,0xd6,0x93,0x19,0x25,0xdc,0xa5,0xe3,0x54,0xf7,0xb0, + 0x3e,0x34,0x4d,0xb0,0x7b,0xb2,0xa3,0x43,0x9c,0x75,0xb0,0x6b,0x12,0xd2,0xbf,0xbf, + 0x87,0xad,0xb5,0x50,0x13,0x2,0x93,0xb,0x6c,0xad,0x43,0xc9,0xbe,0x99,0xbd,0xec, + 0xcd,0xe7,0x0,0xbb,0x84,0xed,0x80,0xe3,0xdb,0x21,0xd9,0x9b,0xba,0x98,0x7a,0x56, + 0x65,0x26,0x35,0xc4,0x40,0x70,0x7c,0x7a,0x63,0x62,0x33,0xb9,0xd,0xea,0x2d,0xc1, + 0x64,0x30,0x8c,0x55,0x1f,0x41,0xc9,0x78,0xac,0xee,0x51,0x0,0x60,0x18,0xaf,0x81, + 0x3b,0xbc,0xd2,0x95,0xdf,0x2b,0xe,0xed,0x42,0x97,0x8f,0x2d,0xb8,0xe5,0x30,0x83, + 0x6b,0xb0,0x89,0xab,0x8e,0x7e,0x4e,0x6a,0x7f,0xe0,0x5c,0x35,0xa7,0xc3,0x30,0x23, + 0x87,0x86,0x28,0x74,0x21,0x8e,0x59,0x6f,0xdd,0x28,0xf,0x24,0x1d,0xf5,0x2a,0x4, + 0x73,0x4a,0x7c,0x10,0x20,0x79,0xb,0xad,0xa7,0x45,0x4c,0x62,0x30,0x7b,0x4f,0x51, + 0xe0,0x6b,0x4,0xdf,0x4b,0x7f,0xe1,0x76,0x96,0x53,0x4d,0xfe,0x89,0x6b,0xb1,0xcf, + 0x6d,0x9a,0xa8,0x57,0xd0,0x6e,0xa5,0x50,0x23,0x52,0xb5,0x3f,0x49,0x61,0xce,0x0, + 0xb1,0xf6,0xec,0x77,0x68,0xa,0x58,0xbc,0x58,0xe7,0x8b,0x48,0xea,0x4e,0xc9,0x2a, + 0xd2,0xcf,0x90,0xdd,0xac,0x44,0xb4,0xae,0xcd,0x6a,0xb7,0x2a,0xc8,0xa7,0x7a,0x6e, + 0xfb,0xa8,0xe3,0xc3,0xbe,0xb7,0x36,0xb7,0xdc,0x5b,0x3c,0xe3,0x95,0x89,0xc7,0x87, + 0xbc,0x6d,0xdb,0xf,0x55,0xcd,0xb3,0x3c,0x63,0xb9,0x91,0x91,0xe7,0xb2,0x39,0x42, + 0x5c,0xba,0x2a,0x68,0x6f,0x60,0x13,0x76,0xd7,0x3c,0x7,0x87,0xa,0xc6,0xb5,0xa1, + 0x2f,0x93,0x43,0xad,0x9a,0xc7,0xa1,0xc6,0xe9,0xe2,0x23,0x29,0x63,0x86,0xa3,0x51, + 0xc3,0xdc,0x25,0x30,0xaf,0xa0,0xc9,0x3b,0x4,0xfb,0x6a,0x50,0x83,0xfc,0xe2,0xf5, + 0xaa,0x2b,0x16,0xc1,0xf5,0x1a,0xf1,0xc8,0xe,0xd7,0x4,0x37,0xb1,0x7,0x57,0xc6, + 0xcc,0xa7,0x40,0x26,0xd7,0xf4,0x23,0x86,0x6b,0x43,0x32,0x5d,0x87,0x9b,0xd8,0x5c, + 0xf0,0xd8,0x20,0x3c,0x7e,0x56,0xf1,0x33,0x20,0xd0,0x50,0xaf,0x43,0x4,0x25,0xe6, + 0x22,0xcd,0x2d,0x64,0x70,0x1f,0x4,0x15,0xd4,0x86,0x2e,0x5d,0x10,0x6,0xcd,0xc, + 0x54,0xaa,0xa7,0x10,0x8,0xc2,0x3c,0x72,0xc6,0xb0,0x4d,0xa1,0xea,0x89,0xb4,0x16, + 0x8f,0x4c,0x5a,0xb0,0x43,0xb8,0x88,0x29,0x48,0xb3,0x7b,0x44,0x28,0x9e,0x99,0x4c, + 0xf5,0x86,0xfc,0xd1,0x4,0x58,0xd0,0xc9,0x46,0x32,0x1b,0xcc,0x9a,0x49,0x56,0x14, + 0xf7,0x30,0x99,0x8b,0x72,0x66,0x3b,0xf0,0xba,0xa3,0x23,0x37,0x82,0xd3,0x3e,0xe0, + 0x25,0x4,0x51,0x78,0x95,0x18,0x4b,0x8a,0x2a,0x66,0xa4,0x64,0xb6,0xac,0xa4,0x26, + 0xbe,0x16,0xaa,0x89,0x4d,0x35,0x3,0x3b,0xf4,0xa4,0xc4,0x44,0x6a,0xd0,0xdb,0x71, + 0x9a,0xf0,0xa7,0x2,0x97,0x6,0x67,0x44,0xb2,0xdd,0xf0,0x23,0x64,0x95,0xc5,0x32, + 0xa6,0x42,0x24,0x5,0x56,0xf5,0x2d,0x43,0x9f,0x5d,0x41,0xc1,0x66,0xb0,0x11,0x12, + 0xce,0x41,0x86,0x2b,0x1d,0x97,0xb,0x18,0xdf,0xe,0x78,0x85,0xbe,0x35,0x61,0xa8, + 0x36,0xed,0xd0,0x35,0xfb,0xfb,0xa8,0xa1,0xc,0xfa,0x87,0xc,0x36,0xc6,0xd0,0x4e, + 0x34,0xff,0xc6,0x6a,0xfd,0xc4,0x25,0xa1,0x8a,0x58,0x7b,0xbd,0xde,0xac,0x4a,0x7, + 0xc0,0x7e,0x8e,0x10,0x68,0xa9,0x44,0x3b,0x29,0x8,0x9f,0x5,0x4f,0xa7,0x3d,0x3a, + 0x7c,0x60,0xa6,0x53,0x43,0x78,0xda,0xef,0x71,0x4d,0x8,0x9f,0x80,0xe8,0x9,0x8, + 0xb4,0x1d,0x48,0xdf,0x3b,0x48,0x90,0x5c,0x84,0x64,0x2c,0xdf,0xa9,0x41,0x98,0x46, + 0xe,0x0,0xca,0x28,0xdc,0x83,0xde,0x30,0xde,0xf7,0xe6,0x2,0x11,0xcd,0xb1,0xba, + 0x72,0xee,0x47,0xc5,0x1d,0x92,0x59,0x34,0x53,0x44,0xd2,0x7f,0x7b,0x8,0x8,0x47, + 0x96,0x5f,0x75,0xb5,0xfa,0x93,0xb,0x49,0xe2,0x4a,0x32,0x5e,0x12,0xba,0xa0,0xdd, + 0xcd,0x28,0xf,0x9,0x85,0x85,0x52,0x60,0x7c,0xcd,0x17,0x33,0xc4,0x29,0xf2,0x27, + 0xf7,0xcf,0x67,0x73,0x1e,0xb,0xf1,0x90,0xc8,0x14,0xcb,0x8c,0x67,0xaa,0xe9,0x5e, + 0x6e,0x2,0x19,0x1a,0xfd,0x85,0x71,0xbd,0x9a,0xb2,0x32,0x31,0x4d,0xe3,0x17,0xa2, + 0x58,0x9d,0x45,0xd7,0x90,0xd9,0x15,0x93,0xdd,0x3c,0x84,0x40,0xe3,0x13,0x34,0x91, + 0x86,0xc,0x38,0xba,0xe7,0xb2,0xd7,0x66,0xda,0xf8,0x6e,0xee,0xa2,0x56,0x8d,0xbb, + 0x95,0xc2,0x5d,0x3d,0x61,0x20,0xc9,0xb0,0x46,0x7d,0x7d,0x84,0x1f,0x7b,0x4d,0x8f, + 0x5e,0x4d,0x43,0x9a,0x90,0x4a,0xef,0x98,0x52,0xd0,0x0,0xef,0x23,0x8b,0xb1,0x91, + 0xad,0xbb,0x74,0xde,0x71,0x61,0xe5,0x12,0xfd,0xfb,0x6,0xcc,0x37,0x76,0x3d,0xad, + 0x7a,0xf5,0x9e,0x64,0x69,0x23,0x4f,0x50,0x9,0x17,0xa0,0x5c,0x86,0x47,0xe2,0xd2, + 0x66,0x86,0x25,0x26,0x58,0x59,0xcb,0x7b,0xda,0x24,0x36,0xf,0xc4,0xc2,0x5,0x63, + 0x1a,0x2f,0xc1,0xa1,0x73,0x87,0xb7,0x65,0xc2,0xa4,0x30,0x54,0xef,0xb0,0xfd,0x6b, + 0x9c,0x19,0x91,0xb,0x65,0x8,0xa6,0xe4,0x71,0x63,0x15,0x97,0x76,0xa4,0x64,0x5f, + 0xb0,0x7c,0x12,0xa4,0x4a,0xef,0xa1,0x67,0x31,0xa6,0x4,0x4c,0x7f,0xe6,0x45,0x41, + 0xda,0x12,0xc5,0x41,0x87,0xe5,0x3d,0xe9,0xbb,0x36,0xe9,0x92,0xd5,0xc,0x7c,0x72, + 0x3c,0xcf,0x34,0x3,0x48,0x47,0xda,0x72,0x7a,0x74,0xc9,0x80,0xb,0x44,0xcf,0xe8, + 0xc9,0x8e,0xa2,0x5f,0x3,0x67,0x22,0x64,0x53,0x61,0x8a,0x9a,0xe5,0x2,0x41,0x30, + 0x6c,0x36,0x5a,0x83,0xc,0xc4,0x94,0xbd,0x7f,0x37,0x6,0xc7,0x74,0x86,0xcc,0x40, + 0x4e,0x49,0x4,0x5d,0x2a,0xd7,0x90,0x8,0xb0,0x17,0x3a,0x7a,0x60,0x61,0xd2,0xd5, + 0xaf,0x3a,0x51,0xbb,0x51,0xc3,0x35,0x62,0x50,0xd1,0x6f,0x3a,0x6d,0x83,0xfc,0xb3, + 0x2c,0xbc,0xab,0x11,0x4a,0x0,0x83,0x83,0x5e,0x42,0xa8,0xd0,0xaa,0x51,0xc4,0x2a, + 0x9a,0xb4,0x68,0x88,0xa0,0xa0,0x42,0x97,0x5d,0xb9,0x14,0x88,0xdf,0x39,0xc8,0x42, + 0x4e,0xde,0xb7,0x51,0x35,0x6d,0xa2,0x5f,0x66,0xbd,0x5d,0x2a,0x34,0xb5,0x75,0xa8, + 0xe2,0xc,0x89,0xe,0x84,0xd9,0x47,0x85,0x3a,0x93,0x41,0xc5,0x61,0x90,0xd1,0xe4, + 0xb4,0x7,0xf,0xc,0x8e,0x3e,0xcb,0x82,0x36,0xe4,0x35,0x2d,0x8f,0xe7,0xc8,0x72, + 0x57,0xa0,0x82,0xb,0x2e,0xdc,0x15,0xfa,0x5f,0xfe,0x63,0xff,0xf1,0xc7,0x6f,0xff, + 0xeb,0x7f,0xfb,0x9e,0x84,0x47,0xa,0x44,0xea,0x15,0xc6,0x86,0x3f,0xdc,0x94,0x44, + 0xc5,0x18,0x44,0x1a,0x32,0x68,0x5b,0xcd,0x8f,0xbd,0xca,0x8e,0x5d,0x8c,0x26,0x27, + 0x38,0x26,0x8,0x7e,0x78,0xbb,0x34,0xa8,0xc2,0xab,0x34,0xf4,0x8,0x26,0xb,0x8a, + 0x16,0xc0,0x5d,0x56,0x33,0x47,0xee,0xea,0xda,0x88,0x0,0x9a,0x2f,0x75,0x8a,0x42, + 0xdc,0xf5,0xcc,0x75,0xf2,0xae,0x2f,0xeb,0xdd,0x99,0xae,0xb7,0x5e,0xf,0x5c,0x0, + 0xc8,0xfe,0xac,0x10,0x52,0xa8,0x7d,0x2c,0xd1,0xaa,0x83,0x7b,0xbf,0x6a,0x45,0x41, + 0x6e,0xd3,0x24,0x1b,0x7,0x7c,0x84,0x9c,0x4a,0xcd,0x94,0x5c,0xfe,0xd8,0x94,0x1a, + 0xa5,0x37,0x6b,0xbe,0x2b,0xf4,0x6b,0x57,0x94,0xc3,0xb4,0xc,0xa4,0xaf,0xac,0x2e, + 0x87,0x1b,0x31,0xba,0xbc,0x62,0x52,0xf1,0x90,0xb0,0xac,0x6f,0x6e,0xc2,0x3c,0xdd, + 0xf7,0x48,0x84,0xa8,0x55,0x15,0xbc,0x17,0xad,0xa8,0x4,0x30,0x90,0xe3,0x62,0xbc, + 0x4c,0xd4,0x25,0x19,0xe8,0x23,0x88,0xde,0x32,0x4c,0xd,0xf,0xd6,0x8b,0x43,0x22, + 0x41,0xb7,0x10,0x50,0x29,0x36,0x34,0x69,0x9f,0xd5,0x1c,0x4,0x1b,0xdd,0xbf,0x9d, + 0xc6,0xe5,0x41,0x37,0xd1,0x41,0xca,0xe9,0xa1,0xdd,0x5c,0x26,0xfa,0x15,0x25,0x2b, + 0xe,0xa8,0x27,0xea,0x5,0xff,0x64,0x52,0x9a,0x4,0x5e,0x20,0x9b,0xac,0xa6,0xaf, + 0x7d,0x75,0x7a,0xf8,0xb4,0x47,0x31,0xaa,0x36,0x60,0xc6,0xc2,0xb2,0xae,0x1b,0x25, + 0xa2,0xa7,0x36,0xc4,0x84,0xaf,0x61,0x1c,0x95,0x9d,0xdd,0x75,0x7a,0xc5,0x72,0x21, + 0x95,0xbf,0x18,0xd2,0x8f,0xaa,0x28,0x6,0x34,0x27,0x2c,0xaa,0xe4,0x5f,0xa8,0xee, + 0x2c,0x85,0x2d,0x33,0xee,0x80,0xc9,0x23,0x7d,0x65,0x95,0x97,0x25,0x12,0xab,0x47, + 0xa5,0x4e,0x38,0xc3,0xcc,0xf2,0x94,0x11,0x11,0xe1,0x2,0x4,0xf4,0xcc,0xcd,0xe, + 0x9b,0xde,0x6e,0xc0,0x88,0x7e,0xfb,0x75,0xb4,0x9,0x47,0x53,0x38,0x43,0xe7,0xcb, + 0x9b,0xcc,0x6d,0x8d,0x90,0x3b,0x6,0x7e,0xac,0xb9,0xcf,0x81,0x36,0x27,0x4c,0x13, + 0xda,0x48,0x5d,0x5f,0x4c,0x86,0x9d,0xeb,0x80,0xa3,0x54,0x3b,0xbf,0xfd,0xfb,0xff, + 0xf6,0x7d,0x3b,0x0,0x51,0x34,0xf0,0xd1,0x48,0x5e,0x8d,0xf9,0x2f,0x9e,0xf3,0x98, + 0x34,0xc0,0x55,0xad,0x49,0x36,0x97,0xba,0xde,0x2d,0xe2,0xa2,0x4,0x32,0xe,0x6d, + 0x10,0x17,0xdc,0x40,0x53,0xd2,0x1a,0x10,0xf9,0xad,0x50,0x85,0x6c,0x25,0xc4,0x81, + 0x2b,0xec,0x60,0x25,0x48,0x33,0x38,0x23,0x4b,0x59,0xd,0x1,0xbf,0x85,0x6b,0xe4, + 0xa3,0x65,0xcd,0x81,0x21,0x6e,0xd5,0xb9,0x7c,0x7,0xa2,0xda,0x68,0xc5,0xba,0x29, + 0x47,0x5d,0x3,0x34,0x0,0x33,0x2b,0xa3,0x6,0x19,0x74,0x1b,0x43,0xad,0x1c,0x9b, + 0xf0,0x92,0x92,0xae,0x54,0x57,0xdb,0x18,0xc5,0xa1,0xeb,0x3f,0x39,0x82,0x2d,0x5b, + 0x63,0x4d,0xde,0xfc,0x9e,0x20,0xd8,0xf6,0x14,0xd8,0x72,0xcb,0xc5,0xb2,0x79,0x5, + 0xa0,0x3a,0x94,0xef,0xf2,0xbc,0x15,0xf2,0xc5,0x2f,0xa4,0x84,0x87,0xd6,0x1,0x6, + 0x42,0x24,0xb,0x7,0x96,0xa3,0xfc,0xb2,0x5c,0x9b,0x96,0xa4,0x33,0xb2,0x5c,0xb6, + 0xf5,0x51,0xaf,0x94,0x3,0x9f,0xf9,0xe6,0x49,0x71,0x53,0xaf,0x5,0xa7,0xca,0x41, + 0xde,0x73,0xe1,0x0,0x9e,0x63,0x68,0xbf,0x1e,0x90,0xc8,0x64,0x62,0xa3,0x3f,0xf, + 0x14,0x46,0x7,0x45,0x23,0xb1,0xe2,0x94,0xed,0x62,0x6e,0xdf,0xe6,0x7b,0xb3,0x35, + 0x5c,0x27,0x7f,0x85,0xe1,0xfc,0x9d,0x6e,0x65,0x53,0x3b,0x45,0x1f,0xb4,0x80,0xb7, + 0x24,0x14,0xe5,0xb1,0xb5,0x66,0x62,0x66,0x61,0xf3,0x5,0x51,0xd1,0x93,0x16,0x5, + 0x42,0x39,0x33,0x27,0x30,0xfc,0x7d,0xfb,0x7a,0x2f,0xa,0x4b,0x14,0x42,0xd2,0xc9, + 0x83,0x85,0xe5,0x36,0xa2,0x4f,0xef,0x48,0x69,0xf3,0x1b,0xda,0x91,0x59,0x5b,0xeb, + 0x7f,0x42,0xec,0x10,0x61,0x7,0xd,0xac,0x77,0x15,0xb4,0x8b,0xab,0x3b,0x9,0x65, + 0x60,0xc7,0x18,0xe4,0x69,0x36,0x9b,0x55,0x88,0x8c,0x56,0x49,0x10,0x69,0x51,0xb9, + 0x33,0xd6,0x7d,0xe3,0xb8,0xe,0x48,0xb4,0x3e,0x28,0x62,0x5d,0xa8,0x78,0x7e,0x2a, + 0x55,0x39,0xe1,0x8f,0x56,0xb9,0x73,0x41,0x9f,0x29,0x13,0xba,0x48,0x1c,0xa0,0x49, + 0xe1,0x9a,0xf6,0x79,0x64,0xb6,0xb4,0x31,0xbe,0xbb,0x12,0xfc,0xfc,0xfa,0xb7,0x5f, + 0xfd,0xa9,0x9f,0xf8,0xf8,0xfb,0xbf,0xff,0x6f,0xde,0xff,0xca,0x9f,0xf8,0x89,0x8f, + 0xbf,0xff,0xaf,0xfe,0xcd,0x3b,0x52,0x53,0x5e,0x51,0x3b,0x15,0x78,0x99,0xb8,0xd, + 0x8,0x32,0x5a,0x8c,0x6c,0x35,0xdb,0x59,0x25,0x5b,0x11,0x12,0xe0,0x2f,0x9f,0xb0, + 0x49,0xd9,0xc4,0x81,0xa9,0x6e,0x7e,0xc7,0x39,0x4e,0xf9,0x20,0x35,0xea,0x7,0x8f, + 0xcb,0xd,0x29,0x56,0x8b,0x3f,0xc6,0x50,0x34,0xb0,0x54,0x4c,0x3e,0xb5,0x3,0xbb, + 0x6c,0x13,0x63,0x3c,0x43,0xd1,0x74,0xbf,0xdd,0xee,0x77,0x40,0xa3,0x98,0x9,0x9, + 0x6c,0x36,0x57,0xd7,0x1e,0xc9,0x18,0x6a,0x13,0xb6,0xb4,0x29,0x97,0xc,0xe3,0x73, + 0x1a,0x20,0x71,0xe6,0xac,0xe0,0xd8,0x7f,0x3e,0x90,0x31,0x17,0x44,0xcf,0x20,0x48, + 0x4d,0x6f,0xee,0xa3,0x38,0x5e,0xe5,0xd0,0xd1,0x31,0x60,0xf0,0x84,0x98,0x2a,0xc9, + 0x57,0x55,0x4e,0x24,0x5c,0x38,0x78,0x48,0x80,0x87,0xa2,0xca,0xcf,0x49,0x4c,0x3c, + 0xaf,0x61,0xd4,0xb4,0xd9,0xd8,0x56,0x8e,0xc6,0x1d,0x94,0xab,0x70,0x9e,0x2a,0xd1, + 0xbf,0xcb,0x61,0x9,0xa4,0x44,0x76,0xf8,0x6c,0x38,0xea,0xda,0x7f,0x27,0xd1,0xf9, + 0x1f,0xa3,0xdb,0xd8,0x64,0x3b,0x3a,0xd,0x55,0x6b,0x71,0x37,0x31,0xb0,0x34,0x28, + 0xa6,0x77,0x83,0xc5,0x8f,0x18,0x5,0x5c,0xd2,0xdd,0xec,0x6b,0x8,0x21,0xf4,0x63, + 0x50,0x12,0x7c,0x9,0x3c,0x33,0x6b,0x6d,0x72,0x65,0xf3,0x57,0x9a,0xcc,0x79,0xc4, + 0xc6,0x7e,0x10,0xc8,0xa4,0x85,0x59,0xd0,0xaa,0xf3,0xa8,0x78,0x8e,0xac,0x67,0xb9, + 0x25,0x71,0xa9,0x6,0x56,0xcc,0xe2,0xad,0xea,0xfa,0xa,0x96,0x30,0x77,0x9d,0x91, + 0x48,0xd6,0xc8,0x28,0xb3,0x6d,0xa2,0xfe,0x46,0x26,0x5f,0x15,0x7d,0x16,0xdc,0x46, + 0xc7,0x24,0xeb,0x60,0x48,0x70,0xea,0x3,0x4d,0x12,0x49,0x23,0x56,0x14,0xec,0x81, + 0xeb,0x4f,0xe8,0xa3,0x36,0x27,0xf,0x9c,0x4c,0x10,0x9c,0xf0,0xe0,0x84,0x4b,0x98, + 0x2e,0x37,0x1b,0xca,0xed,0x55,0xd,0x2b,0x17,0x21,0x96,0xb9,0x41,0xe1,0xba,0x4d, + 0x1a,0x10,0xac,0x6a,0xb7,0x3c,0xd,0x27,0xea,0xbe,0x49,0x73,0x3d,0x9,0x11,0x43, + 0x7b,0xe8,0xbf,0xfa,0xc7,0x7f,0xe2,0x43,0xd5,0xbd,0xda,0x7b,0xb1,0x1d,0xa1,0x88, + 0x20,0xfc,0x1,0x83,0x63,0xd1,0xb6,0x94,0xd4,0xc3,0x6c,0x5,0x18,0x6,0x7a,0xa2, + 0x7d,0x62,0xd4,0x50,0x69,0xe1,0x58,0x19,0x70,0x72,0x77,0x4b,0x8,0x3c,0xdc,0x9b, + 0x7a,0x85,0x56,0xbd,0x2c,0xaf,0x98,0x59,0x1e,0x85,0xe8,0x39,0x10,0x8e,0xd8,0xe1, + 0xc5,0x48,0x15,0xad,0xb5,0x54,0x3,0x77,0xb2,0x50,0xb3,0x81,0xfa,0x8c,0xfc,0xd8, + 0x5a,0xbd,0xfa,0xf4,0x78,0x27,0x98,0x55,0x35,0x59,0xb2,0x1a,0xee,0x5b,0x1d,0xaa, + 0x24,0xc,0xa0,0x24,0x6a,0xca,0xc0,0x7c,0xa6,0x3d,0xd0,0x8c,0x1e,0x4f,0x22,0x40, + 0xc,0x55,0x33,0xa4,0x37,0xc4,0xd1,0xbf,0x61,0xba,0x74,0x44,0x8b,0x0,0xad,0xc2, + 0x6a,0xba,0xdc,0xa7,0x2a,0x59,0x91,0x4,0x8a,0x5b,0x9f,0xf4,0xa1,0xd3,0xcf,0x7d, + 0x22,0xad,0xed,0x44,0xcd,0x7f,0x83,0x31,0xf4,0x35,0x21,0xb6,0x9e,0xff,0x46,0xc3, + 0x9a,0xd9,0x95,0xa2,0x40,0x91,0x3c,0x51,0xa,0xa9,0x49,0x49,0x68,0xb5,0x63,0x6, + 0x3f,0x87,0xc9,0x52,0x89,0xed,0x7c,0x43,0xb4,0x1f,0x21,0x9f,0x5b,0xc3,0x2c,0xfc, + 0x3d,0xd,0x74,0x17,0x7d,0x8c,0x24,0x9,0x47,0x25,0x23,0xbf,0xbf,0x7d,0xde,0xa5, + 0x62,0xe8,0xae,0x2a,0xed,0x86,0xd1,0xb4,0x1a,0xd0,0xd7,0xa0,0x9c,0x6f,0xbf,0xf9, + 0xa3,0xff,0xef,0xfd,0x37,0x7f,0xf4,0xff,0xbe,0x77,0x16,0xfd,0x44,0x7e,0x8e,0x69, + 0x17,0xc,0xb8,0x3c,0x30,0xb6,0xc4,0xac,0xac,0xbd,0x2a,0xc,0x63,0xbe,0xd0,0x70, + 0x8b,0xa8,0x57,0xb7,0xdc,0x7a,0xc3,0x4c,0x61,0xf3,0xa,0xa5,0xd0,0x58,0xda,0x14, + 0x92,0xc2,0xa6,0xe1,0xcb,0xf0,0x10,0xd9,0xe5,0x1,0x4d,0x34,0x23,0x3c,0x82,0xf5, + 0xcf,0xc2,0xa1,0xcc,0xc7,0x35,0x14,0x96,0x63,0x9b,0x55,0x1c,0x9c,0xec,0x6d,0xce, + 0x1b,0xe6,0xa1,0x37,0xc0,0x47,0xac,0x6f,0x78,0xb9,0x96,0x90,0x3,0xe5,0x50,0x7, + 0xcb,0x47,0x3f,0xd2,0x80,0x3c,0x6d,0x45,0xa5,0x6a,0x57,0xe1,0x62,0xd3,0x82,0x9c, + 0x24,0x26,0x59,0x2e,0x27,0x1b,0xd5,0x3f,0x92,0x33,0xe0,0x29,0x14,0xae,0xaf,0x1e, + 0x7a,0x56,0x92,0xfc,0xec,0xbd,0xa5,0xcc,0x24,0x70,0xd4,0xf9,0x82,0x8b,0xde,0x60, + 0x83,0x4b,0xbc,0xaa,0x8d,0x70,0x18,0xec,0xd,0xf7,0x8e,0x6f,0xe5,0x60,0x53,0xee, + 0x1c,0xb4,0xa5,0x5f,0x14,0x89,0x51,0x2a,0x38,0x86,0x31,0xf,0xc5,0x37,0x8d,0xfc, + 0x24,0x17,0x15,0x7a,0x1f,0x9f,0x4a,0x8c,0xa,0x42,0xdb,0x63,0xe1,0x4b,0xa6,0x9e, + 0x82,0xd4,0xce,0xa9,0x51,0xcf,0x94,0xdd,0xeb,0xae,0xe4,0x93,0x44,0x20,0xd5,0xb, + 0x5a,0xd0,0x37,0xeb,0xad,0x3e,0x6c,0x79,0x3a,0x9a,0x55,0x3a,0x7,0x6c,0xe3,0x7c, + 0x41,0x96,0xb5,0xb1,0xb0,0x9c,0x3a,0x85,0x79,0x67,0x97,0xce,0x29,0x7,0xea,0xd3, + 0xc6,0xfc,0x9e,0xf1,0x3f,0x6c,0x72,0xa3,0xcb,0x89,0x47,0x1,0x41,0xb9,0x83,0x92, + 0x30,0xd0,0xa4,0x9e,0x73,0x13,0xd3,0xbc,0x1a,0x36,0x13,0x2e,0xef,0x60,0x5b,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x3e,0x55,0x2a,0x61,0x92,0x11,0x6d,0x4,0xea, + 0xb9,0x9f,0xe6,0xa1,0xcd,0x86,0x64,0x90,0xb4,0x0,0x65,0xc6,0x3a,0xc6,0x58,0xaf, + 0xc6,0xf,0x51,0xf2,0xdd,0x20,0x39,0xe1,0x2d,0x8f,0x98,0x1e,0x48,0x16,0x1d,0xe, + 0xf3,0xcd,0x34,0xb4,0x28,0x3,0x1,0x84,0x18,0x59,0xcd,0xde,0x8d,0x39,0x17,0x1f, + 0xee,0x77,0x56,0x98,0xd5,0xa4,0x44,0x79,0xdb,0x56,0xd3,0xa7,0xb5,0x5d,0x79,0xfb, + 0x92,0x89,0x2,0xe1,0x44,0x5c,0xfb,0x6c,0xef,0xa,0x92,0x7b,0x54,0x18,0xba,0xe6, + 0x75,0x32,0x88,0x6c,0x6e,0x75,0x19,0x85,0x17,0x32,0xfd,0x59,0x5e,0x51,0x31,0xd6, + 0xbb,0x11,0xe7,0x20,0x92,0xb3,0xaa,0xf4,0x28,0xa3,0x87,0x74,0x39,0xba,0xbd,0xfd, + 0x28,0xc4,0x4d,0x91,0x4f,0xb7,0x51,0xd6,0xed,0x33,0xe0,0x6b,0x2,0x62,0x70,0x7, + 0x18,0x19,0xb,0x52,0x89,0x51,0x60,0x69,0x96,0x1b,0xd9,0xf7,0x2b,0xa,0x45,0x2f, + 0x9c,0xc6,0xb1,0x2,0x7,0x98,0xd4,0x4b,0x70,0xa2,0x42,0x4d,0x44,0xa,0x1c,0x8, + 0x6,0xa7,0xfe,0xc9,0x89,0xe8,0x10,0x96,0x8e,0x2d,0xc3,0x1f,0x88,0x13,0xa3,0xd3, + 0x1a,0x6,0x41,0x14,0x77,0x28,0x32,0x45,0xaa,0xab,0x43,0xbd,0x47,0x56,0x44,0x83, + 0xbc,0xe,0x54,0xeb,0xaa,0x81,0xd0,0x27,0x87,0x6d,0x54,0x41,0xe4,0xe1,0xbb,0x5a, + 0x9f,0xeb,0x9a,0x7b,0x8f,0x6c,0xb1,0x21,0x46,0xcf,0x6a,0xa8,0x24,0xae,0x60,0xda, + 0x8f,0x4d,0x78,0x27,0xfe,0xd1,0x7b,0xe6,0x13,0x4,0x8a,0x56,0xcd,0x96,0xbb,0x8a, + 0x69,0x5f,0x78,0xfa,0xee,0x80,0x40,0x75,0xc,0xc5,0x12,0x33,0x8a,0x54,0xad,0x90, + 0xcb,0x64,0x9e,0x6d,0x13,0xbc,0x18,0xe,0x52,0xf0,0xb1,0xa3,0xd9,0xc6,0x55,0xcd, + 0x6e,0x82,0xf1,0xce,0xec,0xf3,0x62,0xc1,0xaa,0x5e,0x9c,0xdd,0x2d,0x1c,0xe,0x4, + 0x1d,0x30,0x3e,0x43,0xa1,0x71,0x36,0x98,0x7a,0xcf,0xc4,0x23,0xec,0x38,0xbd,0xba, + 0x70,0xe3,0x46,0xd8,0xa1,0xe,0x23,0x7b,0xf6,0x9e,0xa9,0xda,0x7e,0xa2,0xb5,0xf4, + 0xd9,0x89,0x96,0x46,0x50,0xe3,0xe0,0xb4,0x26,0xaa,0x78,0x25,0xd3,0x1f,0x57,0xef, + 0x67,0xba,0x12,0x5f,0x67,0x1d,0x73,0x3a,0x1,0xa0,0x95,0x53,0x10,0xe9,0xac,0x1a, + 0xf4,0x60,0xed,0xbd,0xd7,0x59,0x3f,0xc2,0x99,0xfa,0x15,0xc6,0x92,0xc1,0xd6,0x6f, + 0x2e,0x71,0xee,0x92,0xcd,0xe4,0x83,0xc4,0x5a,0xa6,0xa2,0x64,0xe3,0xe4,0x8e,0x2b, + 0xac,0x41,0x3c,0xdf,0x41,0x4d,0x68,0x67,0x1b,0x5d,0x23,0x39,0x63,0x7,0x3a,0x1b, + 0xf7,0x32,0x22,0xb1,0x8c,0x67,0x4d,0x7d,0xef,0x35,0x6,0x5b,0x81,0x18,0x96,0xfb, + 0x2d,0xac,0x3d,0x41,0x11,0xf8,0x61,0x90,0x1,0x1d,0x79,0xb4,0xd8,0x75,0x8b,0x84, + 0xb9,0xd6,0xcd,0x83,0x16,0xc1,0x92,0x51,0xc6,0xe8,0xac,0x9f,0x7d,0xd8,0x62,0x69, + 0x8a,0x58,0x30,0xd,0x79,0x1b,0xc3,0xce,0xe1,0x76,0x2b,0x3a,0xa3,0x2d,0x57,0xcf, + 0xd8,0x1a,0x6b,0x8,0x8a,0x59,0xe4,0x88,0x53,0x4f,0xf3,0xbe,0xfc,0x72,0xd1,0x65, + 0xe4,0x9d,0x9d,0x89,0x37,0xfc,0x3b,0x30,0x16,0x85,0x47,0x2b,0x52,0xf5,0x8c,0xe6, + 0x94,0xb1,0xd7,0xec,0xcb,0xbe,0x76,0xda,0x55,0x2a,0xf4,0xd2,0xc4,0x42,0xc2,0x19, + 0xad,0x30,0xa8,0x2e,0x65,0x11,0x79,0x12,0x55,0x57,0x21,0x82,0x14,0x1,0x88,0xd1, + 0x27,0x2b,0x8,0x93,0x1,0xcb,0x74,0x90,0x60,0x13,0xf4,0xa0,0x8d,0xd4,0x49,0x5, + 0x45,0x9d,0x4f,0xe5,0x62,0xb9,0xbb,0x93,0x1a,0x5a,0x16,0x3a,0xb,0x79,0xdc,0xd0, + 0x5d,0x85,0x1f,0x3a,0x75,0xfe,0x37,0xe6,0x7c,0x65,0x12,0x87,0x91,0xcc,0x70,0x1a, + 0x39,0x14,0x3d,0x67,0x17,0x1a,0xe1,0x46,0x81,0x88,0x30,0x6d,0xa1,0x5,0xb9,0x76, + 0xa8,0x86,0x67,0x1a,0x2b,0xc9,0xa1,0x5a,0x9,0x8a,0x4d,0xc9,0xfa,0x8e,0xe,0xe2, + 0xb9,0x38,0x88,0xf4,0xee,0x9a,0xa,0x5b,0x27,0x11,0xba,0x9b,0x76,0x26,0xb9,0xc3, + 0x7c,0x9,0xd0,0xd,0x92,0x4e,0xaa,0x77,0xe8,0xcc,0x21,0x41,0x6b,0x6d,0x4c,0xa9, + 0x7,0x56,0x6d,0xf3,0x98,0xa5,0x45,0x5b,0xa7,0xb3,0x20,0x6,0x9a,0x3c,0x6,0x6b, + 0x16,0xce,0x40,0x73,0x91,0x13,0xbe,0x83,0x28,0x51,0x3a,0x28,0xd5,0x4d,0x67,0xdc, + 0x23,0xa,0x65,0xaa,0x62,0x5a,0x11,0x9a,0x8b,0xd8,0x17,0xdf,0xa0,0x4b,0xa4,0x6c, + 0xe3,0x9c,0xd5,0x56,0x64,0x8e,0x47,0xd1,0x46,0x49,0xd7,0x3c,0xf0,0x1a,0xed,0xdc, + 0x1a,0xe3,0x4b,0xf0,0x85,0x15,0xd6,0xab,0xdc,0xd5,0xbd,0x7c,0x7e,0xf7,0x4f,0xd8, + 0xeb,0x7d,0x35,0x1b,0xa9,0xcf,0x83,0x36,0xee,0xd7,0xc4,0xba,0xd4,0x3c,0x27,0x41, + 0xbe,0xd2,0x56,0x75,0xe,0x8b,0x71,0x3f,0x31,0x66,0x30,0x76,0x32,0x6c,0xb5,0x29, + 0x62,0x17,0x5f,0xb1,0x16,0x2d,0xd9,0x85,0x99,0xaa,0x8b,0x56,0x1a,0x1e,0x72,0x7, + 0xc2,0x55,0x99,0xaa,0x1e,0x82,0x55,0xb7,0xbd,0x8,0xa1,0x4c,0x5c,0x28,0x6f,0x9, + 0x83,0xa3,0x61,0x6a,0x1a,0x18,0xa9,0xf3,0xb3,0x8e,0x45,0xd3,0xe0,0xa1,0x37,0x10, + 0x65,0x31,0xb5,0xd3,0xcb,0x8e,0xfa,0xa6,0x42,0x89,0xaa,0xcb,0xfd,0x1e,0xb2,0x2f, + 0x8f,0x42,0x33,0xb7,0xb9,0x6,0x69,0x9f,0xde,0x5b,0x8a,0x4c,0xa2,0x33,0x15,0x85, + 0xdd,0x3d,0x31,0x35,0x5b,0xcb,0xee,0x40,0xfb,0xaf,0x63,0x91,0xde,0x24,0xaa,0xa0, + 0x2a,0x1e,0xa,0x1,0x89,0xa6,0xfc,0xd8,0x4b,0x10,0xb6,0x8,0xc,0xdb,0xda,0x9e, + 0xd5,0xa0,0x54,0xc2,0xdc,0x9a,0xe4,0xd6,0x97,0x2d,0x81,0x7f,0x90,0x69,0x99,0x88, + 0x98,0x4,0x8d,0xd2,0xad,0x3e,0x21,0xc4,0x25,0x2c,0x28,0x96,0xe8,0xee,0xe5,0x5e, + 0xa0,0xfb,0x7c,0x2d,0x75,0xf6,0xbe,0x5c,0x6f,0x9e,0xd0,0xa9,0x1c,0x84,0x9a,0xde, + 0x43,0x9a,0xa3,0xa9,0x0,0x6e,0x5b,0xd0,0xe4,0x29,0xc,0x3d,0xf3,0x56,0xa9,0xb9, + 0x97,0xdc,0x34,0xf3,0x5d,0x82,0x4c,0x60,0x79,0x77,0x47,0xe5,0x75,0x75,0xf4,0xa4, + 0x79,0x8,0x20,0x60,0xb6,0xab,0xc3,0xc2,0x7a,0xed,0x3c,0xa1,0x28,0x98,0xaa,0xc4, + 0x94,0xff,0x71,0x55,0x32,0xd7,0xb3,0x77,0x6,0x6b,0x61,0x4f,0x7f,0x30,0x5b,0xcb, + 0xca,0x3,0xb1,0x56,0xf3,0xfd,0xfa,0x1b,0x1,0x59,0x28,0x2,0xf6,0x75,0x67,0xb5, + 0xc7,0x8,0xc6,0xd6,0x65,0x2a,0x17,0x42,0x51,0x1c,0xb7,0xad,0x46,0xe9,0xd,0x33, + 0x7b,0xbb,0xad,0xf5,0xd6,0x47,0xf4,0x8c,0xe0,0x39,0xea,0x79,0x23,0xd8,0xd7,0xca, + 0x8a,0x46,0x64,0xb3,0x10,0xb6,0x3f,0x7c,0x9f,0x8b,0xf8,0x8d,0xc5,0x4,0x61,0x58, + 0x3f,0x63,0xb4,0x18,0xb4,0xe0,0x97,0xfc,0x6b,0xec,0x2b,0x42,0x2c,0x2a,0x49,0x4f, + 0xa2,0x4c,0xf7,0xa0,0xcf,0x31,0xaf,0xdd,0x3b,0xcc,0x44,0x43,0x84,0x5b,0xb4,0x4f, + 0x31,0x55,0x62,0xd0,0x16,0x89,0xf0,0x5d,0x5c,0xfb,0x3,0x3e,0x8d,0x21,0x95,0xf2, + 0x0,0x29,0x78,0xd5,0x59,0x83,0x97,0xf7,0x40,0xbe,0x63,0x55,0xe3,0x41,0x0,0x75, + 0x14,0xff,0xd2,0x18,0xd0,0x49,0x62,0x3,0xd9,0x2f,0x39,0x2d,0xed,0xd8,0xef,0xdc, + 0x8e,0x2f,0xe,0x2b,0xd6,0x1e,0xc1,0xcb,0xe0,0x31,0x73,0x16,0x6b,0xbe,0xa2,0x3a, + 0xd1,0x24,0xd3,0x3d,0x70,0x72,0xd3,0xb6,0xdf,0xfc,0x8a,0x68,0x39,0x21,0xc8,0x39, + 0x81,0x31,0x81,0xc6,0xac,0x98,0xf0,0x38,0x78,0x35,0xc8,0x6d,0x78,0xd3,0xbe,0xc0, + 0xc6,0xf8,0x4b,0x5c,0xac,0xe0,0x7d,0x19,0x73,0xbc,0xf1,0xea,0x5a,0x33,0xcc,0xc6, + 0xe4,0x92,0x8a,0x74,0x67,0xfd,0xb4,0x43,0xd7,0xe,0x62,0xb1,0x46,0xdd,0x45,0x9b, + 0xbe,0x9e,0x16,0x5c,0x19,0xbd,0xc,0x6,0x92,0x10,0xc4,0xe1,0x26,0x38,0x82,0x71, + 0xa1,0xba,0x9f,0xb0,0x4b,0x40,0x96,0xbb,0x5f,0x5d,0xfe,0x81,0x3a,0xc7,0xdd,0x24, + 0x52,0x87,0x76,0x6d,0xf6,0x64,0x18,0xfa,0xcf,0x59,0xd1,0x30,0xc9,0x4f,0xd0,0xbc, + 0x9a,0x23,0x58,0xb0,0x9c,0x69,0x3f,0x3d,0xab,0x27,0x77,0xd5,0x9e,0x2c,0xd9,0xaf, + 0x97,0xec,0xfe,0x93,0x56,0xb,0x93,0xec,0xa7,0x9,0x1d,0xd8,0x7a,0x28,0x9f,0xb5, + 0x5e,0x9f,0x7f,0x99,0xf6,0x96,0xe9,0x70,0x21,0x7e,0x8d,0xf8,0xbd,0x6f,0x6b,0x5e, + 0xbd,0xe6,0x9c,0x92,0xa8,0x32,0x1,0x94,0x85,0x26,0xf4,0xfb,0x5d,0x22,0xaa,0xc2, + 0xe5,0xd,0xaf,0xba,0x14,0xca,0x86,0xa7,0x99,0xdf,0xe8,0xeb,0x50,0x3d,0x29,0x58, + 0x2e,0x86,0x41,0x90,0x82,0x59,0xfb,0xd2,0x5f,0xd7,0xec,0x72,0x45,0x86,0xf7,0x66, + 0xdf,0x82,0xbd,0xa5,0xc4,0x84,0xe7,0xe,0x20,0x2e,0xa3,0xc2,0x59,0x5a,0xd5,0x6, + 0xd4,0x28,0x9b,0xde,0xef,0x29,0x6,0x32,0xac,0x5,0x58,0x3a,0x7f,0x9,0x8c,0xd9, + 0xe6,0x9a,0xcb,0x94,0x1c,0xa0,0xb0,0xea,0x3a,0xd4,0xff,0x1c,0xf3,0x68,0x4c,0xad, + 0x76,0xbf,0xf3,0xba,0x1b,0x1,0x18,0x7,0x74,0xb2,0xf0,0x8d,0xb1,0xad,0x93,0x69, + 0x8c,0x26,0xbd,0x4f,0xa2,0x70,0x19,0x6a,0xf4,0x75,0xc9,0x57,0xe7,0xff,0x44,0x4b, + 0xc,0x13,0x11,0xc1,0x7e,0x1f,0x7,0x72,0x48,0x85,0x1f,0x7b,0xd,0x4,0xce,0xd6, + 0x2c,0xad,0xa3,0x3d,0xe3,0x2,0x1d,0x7,0xe7,0xb8,0xd6,0x24,0x57,0x2e,0x8,0x9a, + 0xec,0x6a,0x83,0xc,0x28,0xec,0x93,0xe9,0xfd,0x4b,0xdc,0x9,0x33,0x19,0xc6,0x44, + 0x6f,0xa2,0x47,0xcd,0xcd,0xad,0xd8,0x49,0x9d,0xaa,0x19,0x9d,0xf8,0x77,0x30,0x7e, + 0x51,0x23,0xbb,0x85,0x25,0xe9,0x8a,0x95,0x64,0x8b,0x13,0x3b,0x39,0x7b,0xe2,0x5a, + 0x4a,0x4a,0x63,0x44,0xc7,0xa9,0xfb,0x6,0x94,0x49,0xb3,0x9d,0xa0,0x2f,0x25,0x43, + 0xd4,0xa3,0xe5,0xde,0x9d,0xba,0x42,0x6b,0xa1,0x29,0xfc,0x22,0x82,0xe5,0x2a,0x74, + 0xaf,0xe7,0x50,0x42,0x64,0x7c,0xd9,0x37,0x62,0x48,0xc,0xe,0xdf,0x85,0xd0,0x7d, + 0x4e,0xd3,0x2,0xe,0x1,0x4b,0xf5,0xc6,0x1d,0xc7,0x6e,0xac,0x8b,0x54,0xd8,0x52, + 0x7b,0x52,0x68,0xf0,0x5a,0x5a,0xdd,0x65,0xa4,0x3d,0x36,0x76,0xf0,0x10,0x48,0xd, + 0x4a,0xee,0x4a,0x7c,0x4f,0xcf,0x9,0x74,0xc,0xbf,0xaf,0xb1,0xc9,0x12,0x14,0x36, + 0xd,0xa2,0x35,0x9b,0x2e,0x2e,0xa3,0xc7,0xdd,0x89,0xda,0x26,0x2,0x6d,0xb3,0x1a, + 0xdd,0x6c,0x34,0x62,0x22,0x4d,0xeb,0xff,0x49,0xf4,0x1e,0x92,0xc6,0x13,0x68,0x97, + 0xbe,0x30,0x5,0x3a,0x6a,0x68,0xb,0xcd,0x98,0x86,0x41,0x26,0xd9,0x89,0xd0,0x86, + 0x9b,0xba,0xd3,0xd5,0xde,0x5e,0x14,0x74,0x6,0x6a,0xb0,0xc3,0xf0,0x92,0xc6,0xe0, + 0x43,0x1c,0x8a,0x79,0x86,0xa8,0xb0,0x4f,0x37,0x6f,0x98,0x11,0xcb,0x16,0x78,0xdd, + 0x6b,0xd3,0xf3,0xde,0xd5,0x18,0x81,0x46,0xe,0xc5,0xc1,0x70,0x6,0x3,0x92,0xc4, + 0x51,0x84,0x3,0x67,0x4a,0x48,0xdc,0xa7,0xb9,0x47,0x1c,0xd6,0xab,0x90,0xf5,0x3e, + 0xb1,0x72,0x83,0xf0,0xe6,0x24,0x50,0xe,0xac,0xd2,0x53,0x35,0x77,0xe0,0xcc,0x34, + 0x73,0x22,0xca,0xdc,0x2e,0xc7,0x19,0x66,0xf,0x56,0xf7,0xbf,0x5e,0xd8,0xd6,0x9a, + 0x72,0xe8,0xa1,0x9d,0x2e,0xaa,0xb2,0xc5,0x81,0xfc,0x3a,0xb5,0x4d,0xd8,0x3,0x5b, + 0xd,0x41,0xcb,0xfa,0x74,0xbd,0xdd,0x66,0x4f,0x85,0x9c,0x7,0xbf,0xd0,0x94,0xe4, + 0x2d,0x9,0x1b,0x18,0x70,0x23,0xb7,0x68,0x43,0x88,0xd2,0xbe,0xa2,0xf3,0x1e,0xb6, + 0x40,0x1d,0x85,0x27,0x11,0x4,0x2d,0xd1,0xa8,0x6f,0x6d,0x2a,0x6d,0xb2,0x21,0xda, + 0x33,0xec,0x3d,0xff,0xf1,0xdc,0xe2,0x4e,0xda,0xf9,0xa2,0x74,0xb6,0x73,0x8f,0x11, + 0xbb,0x29,0xed,0xb8,0x64,0x10,0xca,0x6b,0xec,0x98,0x5,0x1a,0x9f,0x6f,0x52,0x3b, + 0x65,0x8a,0xee,0xc9,0x33,0x77,0x26,0xba,0x7,0xf8,0x47,0x35,0x91,0x60,0xe2,0x96, + 0xed,0x77,0x8e,0xce,0x17,0x83,0x73,0xa9,0xdd,0x43,0x30,0xac,0x59,0xd0,0x54,0xc4, + 0xab,0x4f,0x2f,0x4d,0xba,0xc3,0xc1,0xb4,0x4,0x4c,0x19,0xaa,0x13,0xb8,0x2,0x3a, + 0x7a,0x22,0x7f,0x72,0x62,0xd4,0xf5,0x47,0x93,0xa,0xb,0xc0,0x34,0x42,0x46,0xa7, + 0xde,0xa,0xa9,0x82,0xcf,0xcd,0xa4,0x8f,0x93,0x84,0x9d,0x1e,0x51,0xe5,0x63,0x48, + 0x1d,0xa7,0xe1,0x41,0x15,0x9,0xe5,0x95,0xc,0x9a,0x8a,0x1d,0x83,0x9d,0x9b,0xda, + 0xde,0x41,0xc6,0x8b,0xe6,0xfd,0xba,0x2f,0x39,0x93,0xad,0x57,0xc5,0xcd,0x70,0x5f, + 0x84,0xe,0x61,0x81,0xef,0xb1,0x10,0xae,0x8c,0x33,0xb9,0x34,0xfc,0xdc,0x56,0x84, + 0x34,0x61,0x99,0xde,0xf,0xb2,0x8a,0x8c,0xd5,0x82,0xae,0x8d,0x74,0xa4,0x42,0xb7, + 0xe9,0xf,0xd0,0x2,0xa0,0x8f,0x93,0xe0,0x4c,0x60,0x4f,0x91,0x8f,0x66,0xb9,0xd9, + 0x3f,0x82,0x26,0xe0,0xdf,0x95,0xad,0x3c,0x5e,0x42,0x66,0xd5,0x27,0x5b,0xda,0x67, + 0x4c,0x2c,0x62,0xeb,0xe5,0x1d,0xfb,0x2f,0x96,0x6d,0x9d,0x4f,0xa8,0x81,0xd0,0x54, + 0x46,0x3e,0xac,0xc1,0xfe,0x76,0x78,0x1f,0x9a,0x26,0xdc,0x71,0xac,0x70,0x2a,0x3, + 0x47,0xd,0x87,0x69,0xa4,0x8d,0xdd,0x9f,0xc0,0x2a,0xc4,0x94,0xae,0x4d,0x21,0x17, + 0xd5,0xf4,0x4f,0xb1,0x3,0x3d,0x5,0x9,0x63,0xc8,0x1f,0xd7,0x3,0x7d,0x4e,0x99, + 0xa2,0xa5,0x81,0x81,0xef,0xe2,0x15,0xa5,0x4c,0x0,0x88,0x1,0x0,0x86,0xa0,0x6b, + 0x49,0xca,0xfa,0x2e,0x58,0x42,0xa7,0x7,0x17,0x74,0x42,0x45,0x26,0x58,0x9a,0xd0, + 0x13,0x64,0xbe,0x5e,0x21,0x58,0xc2,0x24,0x66,0xab,0x5,0x73,0x1f,0x99,0x6b,0x3a, + 0xe0,0x21,0xc,0x54,0xc0,0x30,0x62,0xb5,0xa3,0x17,0xdb,0xd4,0x86,0x13,0x7e,0x31, + 0xc8,0x5b,0xf6,0xb9,0x73,0x74,0x5b,0x17,0x11,0x58,0xd2,0x9f,0x99,0xfc,0x26,0x86, + 0x68,0x99,0xef,0x86,0xcb,0x68,0x9f,0xc9,0x19,0x55,0x32,0x1d,0x63,0x88,0x1e,0x96, + 0x83,0x46,0xab,0xf4,0x30,0x39,0x31,0x11,0xab,0xb7,0xf7,0x85,0xec,0x47,0xf8,0xb4, + 0x2,0x13,0xad,0x28,0xdc,0x2d,0x45,0x29,0x92,0xef,0xb,0xfa,0xdb,0xbf,0xf7,0x7, + 0xef,0x7f,0xfb,0xf7,0xfe,0xe0,0x1d,0x4d,0xbb,0xc5,0x45,0x5d,0x9,0x37,0xdd,0xd5, + 0xb6,0x27,0x1b,0x5f,0xf1,0x2b,0xa1,0x79,0xdb,0x22,0x17,0x32,0xf4,0xce,0xb8,0x1, + 0x7c,0xb2,0x81,0x1,0xbe,0x23,0xad,0xb7,0xd5,0x24,0x74,0x15,0x6,0x64,0xdc,0x84, + 0xc8,0xbc,0x55,0x29,0x4b,0x39,0xbd,0xc,0xbf,0x71,0x25,0x68,0x6c,0xa4,0x45,0x8c, + 0x44,0x98,0xc2,0x2,0x1c,0x98,0x8,0x74,0x62,0x92,0x90,0x4c,0x10,0xf0,0xdf,0xa4, + 0x82,0x96,0xc6,0x24,0x2c,0xc,0x8,0xdc,0x94,0xc5,0xd,0xca,0x48,0x47,0xf2,0x0, + 0xa6,0x6f,0xbb,0x2f,0xf7,0x6a,0x50,0x3e,0xe3,0xad,0x7f,0xeb,0xf7,0xfe,0xf5,0x7b, + 0x55,0xd5,0x6f,0xfc,0xe9,0x9f,0xfc,0x68,0x99,0xa3,0x1d,0x94,0x93,0x5,0xac,0xf2, + 0x2d,0xbc,0xc7,0xb6,0x8d,0xde,0xae,0x1a,0xf4,0x53,0x87,0x8a,0x2e,0x1b,0xdb,0xec, + 0x3d,0x28,0x76,0xff,0x5e,0xa4,0x16,0xbd,0xb1,0x62,0x67,0xb2,0xcf,0x44,0x1e,0xfb, + 0x12,0x5c,0x99,0xe6,0xf,0x39,0x40,0x87,0xb9,0x5e,0xa6,0xd9,0x25,0xaa,0x59,0xf2, + 0x46,0x70,0x74,0x9f,0xb0,0x6,0x28,0x28,0xe0,0xa4,0x4a,0xb2,0x63,0xc0,0x78,0x49, + 0xc6,0xa,0x82,0xcd,0x53,0x1,0x58,0x91,0xd9,0x2,0xae,0x4b,0xd8,0x21,0xd6,0xa1, + 0x69,0xa3,0x3,0x73,0x33,0x48,0x6d,0x88,0x1b,0x34,0xcd,0x2d,0xff,0x1c,0xfa,0x0, + 0xc5,0x72,0x19,0xd7,0x48,0x22,0x58,0x8e,0xa0,0x21,0xc6,0xc6,0x46,0x5e,0x6d,0xc2, + 0xe2,0xc3,0x18,0x15,0xab,0xe5,0xc5,0xa6,0x42,0x49,0xd5,0x37,0xf,0x33,0x42,0x1e, + 0x12,0xad,0xfd,0x6c,0x91,0x9c,0xae,0x16,0x6c,0x29,0x3c,0x1e,0x88,0x45,0x27,0x1b, + 0x45,0xb3,0xda,0x8,0xe4,0x71,0x82,0xac,0xba,0xad,0x2d,0x17,0xf9,0x4e,0xf7,0x13, + 0xa5,0x90,0x48,0x2c,0x90,0x87,0xa2,0x1e,0x4e,0xc2,0xd3,0x35,0x3d,0xd0,0x41,0x93, + 0x3,0x12,0x94,0xd7,0x46,0x5e,0xa5,0xb6,0xdb,0xd0,0xa9,0xa0,0x76,0xf,0xc8,0xb6, + 0x77,0xd7,0xe7,0x87,0x98,0x8,0x84,0xec,0xfb,0x54,0xf9,0x10,0x4b,0x5b,0x6b,0x67, + 0x2a,0x32,0x69,0x73,0x9f,0x83,0xc5,0x75,0xdc,0x7d,0x72,0x22,0xcf,0x6d,0x2e,0x92, + 0x12,0xc7,0x73,0xdb,0x2b,0xc2,0xb2,0x12,0x28,0xdb,0xaf,0x8f,0xb0,0xd8,0xfa,0x25, + 0xc3,0x8c,0x4e,0x47,0x3c,0x60,0x14,0xc2,0xdd,0xde,0xbc,0x72,0x31,0xaa,0xab,0x55, + 0x77,0xc6,0xec,0xd9,0x3e,0x35,0xb3,0x8a,0x2,0x82,0x51,0x7d,0x27,0x29,0xce,0x9d, + 0x74,0x3a,0x31,0x1d,0x28,0xa7,0xf3,0xc7,0x8,0x47,0xeb,0xdb,0xa9,0x44,0xe5,0xf0, + 0x1d,0x4a,0xcc,0xa8,0x20,0x9d,0xad,0x2c,0xf5,0xaa,0x81,0x6c,0x30,0x8f,0x88,0x4d, + 0x89,0xf1,0x28,0x82,0x30,0x54,0xdc,0x7,0xa,0x47,0x40,0xf8,0x75,0xf6,0x8,0xb7, + 0x54,0x13,0xbd,0x33,0x79,0xb3,0x33,0x7f,0xe3,0x3f,0xf9,0xc9,0x8f,0xbf,0xf9,0x2f, + 0xbe,0x2,0xbb,0xb3,0x36,0x3d,0xeb,0x7e,0x66,0xd3,0x4d,0xa5,0x88,0x5d,0x20,0x5, + 0x2a,0x1b,0x85,0x10,0x57,0x99,0x30,0x41,0x81,0xb3,0x73,0xd4,0x68,0x33,0xb1,0xd0, + 0xe1,0xa1,0xce,0x4,0x14,0x94,0x9c,0xfe,0x6c,0xe0,0x6a,0x6b,0x48,0xa7,0xa7,0x51, + 0x15,0x4b,0xe5,0x8c,0x31,0x8c,0xcf,0xb1,0xba,0x58,0x9,0xa3,0x82,0x44,0x53,0xfc, + 0x82,0x9,0xa0,0x8,0xa1,0xf4,0x64,0x6a,0xa1,0xf7,0x56,0x2a,0x4e,0x34,0xab,0x5a, + 0x58,0x9e,0xd1,0xb6,0x23,0xa6,0x11,0x29,0x34,0xa2,0x88,0x8e,0xc0,0xfa,0x60,0x47, + 0x30,0x75,0xd9,0xa5,0x2e,0x51,0x68,0xf2,0xc4,0xcf,0x28,0x5b,0xe7,0xad,0xc2,0xd8, + 0xf9,0x10,0xd4,0xa2,0x82,0xb8,0xa9,0x48,0x52,0x93,0x57,0x45,0x1f,0x7d,0xcb,0x19, + 0x42,0xd6,0x96,0x10,0x16,0xba,0x6f,0xa0,0x8c,0x8,0x32,0xea,0xbe,0x8a,0xed,0x1, + 0x90,0xfa,0xec,0x6c,0xda,0xec,0x49,0xee,0xf3,0xe0,0xee,0x6,0x20,0x84,0x5f,0x7f, + 0x6a,0xf8,0x69,0xe0,0x72,0xf4,0xcb,0x7d,0x1c,0x86,0x93,0x64,0x8d,0x16,0xd2,0xe4, + 0x74,0x77,0xc8,0xa7,0xa0,0x5,0x3e,0x51,0xe1,0x63,0x87,0x86,0x22,0xaa,0x2,0x1a, + 0xd1,0x84,0x98,0x4c,0xd5,0xc,0xc2,0xa3,0x51,0x92,0x1d,0x68,0x91,0x47,0xe7,0xb3, + 0x61,0x16,0xbd,0x58,0xe2,0x39,0x3a,0x79,0xa0,0xea,0x98,0xf,0xda,0xa,0x51,0x57, + 0x54,0x12,0xe4,0x4a,0x50,0x99,0x28,0xcd,0x24,0x47,0x85,0xd8,0x1f,0x5f,0xa8,0x9d, + 0x12,0x16,0x91,0x64,0xb5,0x1b,0x61,0x7b,0x2a,0x74,0x6d,0x13,0x90,0xae,0x84,0x69, + 0xa2,0x66,0x4a,0x94,0x5,0x6e,0xde,0x4,0xec,0x5c,0xe6,0xa7,0x17,0x4e,0xd0,0x6b, + 0xa0,0x4c,0xaa,0xa2,0xa3,0xdd,0x14,0x12,0x6d,0xe6,0xd8,0x17,0xaa,0x86,0xfe,0xe4, + 0xc,0xcd,0x4d,0x55,0xe4,0x8,0x53,0x17,0x86,0x5e,0x61,0xe6,0x77,0x68,0x3d,0xbf, + 0x3e,0xea,0x16,0x96,0x82,0x93,0xee,0x6f,0x25,0x85,0x3f,0xa1,0xc9,0xea,0xf3,0xb4, + 0x4d,0x2,0x53,0x25,0x3e,0x67,0xef,0xf3,0xa1,0xd1,0xd6,0xe6,0xd3,0x4d,0x93,0xd7, + 0x74,0xcb,0x6b,0x8d,0x87,0x99,0x2d,0x5f,0x88,0xcf,0xa8,0xf4,0xaa,0x8e,0xb0,0x21, + 0xc,0x14,0x40,0x1f,0xf5,0x6a,0xaa,0x58,0x88,0xea,0x8b,0x9e,0xc8,0xb0,0x37,0xfa, + 0xeb,0xaf,0xfd,0x99,0x9f,0xfa,0xf8,0x1b,0xff,0xfc,0xf,0xde,0x33,0x63,0x6e,0x12, + 0x95,0x8,0x2,0xa4,0x5d,0x27,0x3a,0x74,0x68,0xb3,0x9d,0x7,0x16,0xaa,0x6d,0xa2, + 0xb9,0x4c,0x1,0xdd,0x8c,0x4,0x9,0x1b,0x46,0x2f,0xac,0x12,0xb6,0x43,0xb0,0x68, + 0x85,0x88,0x62,0x88,0xcf,0xa4,0xdd,0x1f,0xf0,0xa2,0x1e,0xc,0xd9,0x91,0xde,0x1, + 0xe3,0xf2,0xa0,0x34,0xc2,0xeb,0xbe,0x19,0xd9,0x12,0xe9,0x40,0x86,0xae,0x9e,0x88, + 0x6a,0x32,0xfc,0x4,0x36,0xfd,0xae,0x9d,0xa0,0xa2,0x21,0x4f,0xbd,0xe5,0xa5,0x3d, + 0x3e,0x9,0xdc,0x10,0x83,0x96,0x6c,0xc7,0x0,0x2d,0x75,0xde,0x76,0xa3,0x1c,0x12, + 0xff,0xa4,0x32,0xee,0x60,0xf2,0x95,0x20,0xea,0x8c,0xf0,0xcc,0x80,0x46,0xf4,0x41, + 0x9f,0x40,0x82,0x50,0x33,0x34,0xa2,0xed,0xad,0x4a,0x86,0xb0,0xe6,0xec,0xe2,0x20, + 0x82,0x62,0x50,0x66,0x86,0xdb,0xe3,0x63,0x53,0xc6,0x83,0xc8,0x37,0xe7,0x1d,0x58, + 0x53,0x35,0xe8,0x30,0xf0,0x34,0xfb,0xee,0x3e,0x4,0xe9,0x1f,0x31,0x19,0xa7,0x40, + 0xfa,0xc0,0x88,0x33,0xc1,0x3b,0x20,0x4a,0x83,0x80,0xb4,0xba,0x58,0x2e,0xfc,0xc2, + 0x4c,0x56,0x25,0xe1,0x47,0x55,0xb,0x90,0x7e,0xbe,0xea,0xa5,0x5e,0xa1,0x51,0x3e, + 0xe5,0xb6,0x77,0x0,0x1d,0x7c,0x39,0x92,0x8f,0x95,0xca,0x98,0xa,0x45,0xb7,0x20, + 0x8b,0x3,0xb,0x1d,0x62,0xdf,0x8c,0xe4,0x91,0x39,0xc2,0x4a,0x56,0xfd,0xb5,0x3f, + 0xfb,0x27,0x3e,0xfe,0xc6,0x3f,0xff,0xfd,0xf7,0xc5,0x2f,0x2,0x3b,0x64,0xaf,0x48, + 0x2c,0x92,0x1d,0xb6,0x87,0x11,0x39,0x6a,0x81,0x38,0x92,0xab,0x49,0x5b,0x61,0x9a, + 0xf6,0x71,0x72,0x2d,0xd7,0x49,0x87,0x92,0x4c,0xae,0xe,0x76,0x44,0xba,0xf3,0xa9, + 0x8d,0xf,0x27,0x96,0xa4,0x17,0x37,0xb3,0x42,0xd5,0x1b,0x4f,0x87,0xcd,0x82,0xaf, + 0x8f,0xd6,0x2f,0xa4,0x30,0xa6,0xb3,0xdf,0x85,0x4e,0x9e,0xac,0x94,0xc1,0xec,0x82, + 0x6,0xd6,0xd7,0x31,0x4a,0xae,0x3e,0x6c,0x77,0x59,0x82,0x66,0xa2,0xda,0xc7,0xb, + 0x74,0x56,0x21,0x63,0x77,0xa1,0x2b,0x9f,0x5b,0x4d,0xd3,0xb,0xeb,0xc,0xe4,0xc8, + 0x49,0x45,0x3f,0x17,0xad,0x5a,0xb3,0x11,0xa8,0xbb,0xef,0xf3,0xd7,0xff,0xec,0x4f, + 0x7d,0xfc,0xf7,0xff,0xe7,0x1f,0xbc,0x6b,0x4f,0x8,0x8e,0xb8,0xdb,0xbc,0xe5,0x73, + 0x20,0x30,0x7a,0x4a,0x29,0xeb,0x60,0x23,0x3d,0xf6,0xda,0x4b,0xbb,0x36,0x2f,0xff, + 0x83,0xa9,0xb7,0x2b,0x87,0xf2,0x9a,0x1b,0x35,0x3f,0x66,0x8,0x97,0xc3,0xd2,0x52, + 0x63,0xff,0x1b,0x8d,0x10,0xf9,0x77,0xd2,0xfb,0x83,0xc2,0x92,0xba,0x49,0xe8,0xbf, + 0x23,0x7c,0x91,0xfd,0x37,0xf8,0x6c,0xbc,0x12,0xe8,0x9c,0x40,0x4a,0x77,0xa4,0x13, + 0x21,0xb,0x1f,0x91,0x83,0x7,0xb1,0x9a,0xfb,0xe1,0xeb,0x5d,0xd2,0x53,0x35,0x32, + 0xe7,0xd4,0x6a,0x11,0xdf,0x6a,0x9b,0xd1,0x65,0x24,0x6d,0xc2,0xcb,0xd8,0xd2,0xbd, + 0x6c,0xe4,0xcc,0x92,0x20,0xcf,0x1,0xa1,0x5a,0xb2,0xd9,0xd5,0xfb,0x8f,0x7b,0xc4, + 0x53,0xea,0x2a,0xf6,0xb4,0x65,0x18,0xaa,0x89,0x99,0x6a,0x34,0xe9,0x63,0x6d,0xe1, + 0x3d,0x9e,0x1,0xcd,0xa6,0x57,0xc5,0x48,0x6,0x1b,0x4e,0xe8,0x58,0x2b,0xe3,0x79, + 0xab,0x14,0xf8,0xaa,0x98,0x20,0xf7,0xec,0x92,0xdf,0x7c,0x19,0x84,0xb,0xbc,0x36, + 0xd1,0x52,0x7e,0x1d,0xb3,0x6f,0x9c,0xbc,0xa2,0xe,0xb8,0x55,0xd5,0x59,0x49,0x71, + 0x94,0xd2,0x17,0xa4,0x53,0xd1,0xa,0xa,0x70,0xcc,0xca,0x56,0xe4,0x7c,0xde,0x56, + 0xd6,0x2a,0x42,0xd4,0xad,0x13,0xd2,0xa2,0x58,0xc4,0x95,0x9,0x35,0xd7,0xf8,0x5a, + 0x1d,0xdf,0x77,0x2e,0x46,0x11,0xa3,0xb2,0x3d,0xd,0xf,0x3e,0x48,0xec,0xb3,0xe7, + 0xbc,0xfc,0xaa,0xaa,0x9b,0x1c,0xd1,0xe0,0x3e,0x47,0xf3,0xc,0x31,0x8d,0x77,0x60, + 0x55,0xe8,0x91,0xed,0xcf,0xce,0x71,0x29,0x2,0x84,0x89,0x4b,0xb3,0x7f,0xe3,0xa5, + 0x92,0x79,0xdd,0xcc,0x20,0x4c,0xb,0x12,0xf6,0xae,0x59,0xe9,0x88,0x96,0x54,0xb8, + 0x26,0xb1,0x5,0x34,0x9d,0x61,0x36,0x9f,0x5,0xc,0xad,0x3c,0xc,0x44,0xa7,0xae, + 0x95,0xbe,0xc8,0x4c,0x23,0xa3,0x58,0x5e,0x23,0x19,0x2d,0x53,0xf8,0xff,0xb9,0x35, + 0x2f,0xa2,0x11,0x1f,0xc2,0x93,0x28,0x5a,0x55,0xcc,0x18,0xd7,0x10,0xd4,0x70,0x69, + 0x1f,0x13,0xcd,0xdc,0xa5,0xc1,0x71,0x95,0x6d,0x4,0x25,0x2,0x49,0xef,0xcc,0xb4, + 0xf8,0x1f,0xef,0xe8,0xdd,0xc1,0x21,0x37,0x3c,0xc6,0xc6,0xd0,0x2c,0x83,0xbc,0x9c, + 0x55,0x9,0x63,0x5c,0xb7,0x31,0x3b,0xdd,0xe0,0x49,0x3c,0x19,0x18,0xa3,0x30,0xa3, + 0x95,0x44,0x72,0x76,0xa0,0x31,0xc5,0xb5,0x20,0x78,0x59,0x3b,0x6,0x63,0xc3,0xa1, + 0x57,0xa5,0xe5,0xb0,0x1a,0x97,0x94,0xe2,0x46,0x47,0xda,0xd4,0x93,0xb6,0x4,0x9e, + 0x9,0xb,0xb3,0xe9,0x1d,0xac,0x31,0x75,0xd,0xc7,0x28,0xd,0x2c,0xab,0xee,0xc7, + 0xcd,0x24,0x4f,0x4e,0x19,0x49,0x69,0x8a,0xc2,0x8a,0xe4,0x4c,0xbc,0x82,0x70,0x34, + 0xcb,0xa4,0x32,0xd1,0x2c,0xad,0x6e,0x51,0xa,0x61,0xf6,0xb5,0xd,0x35,0xb5,0x71, + 0xd4,0xb3,0x32,0x3f,0x37,0xcd,0x0,0x5c,0x36,0x6e,0x93,0x95,0x2f,0x7,0xb3,0x10, + 0xc6,0xec,0x35,0xf,0x8c,0xfe,0x76,0x78,0xc3,0xcf,0x2b,0x6,0x4a,0xd3,0x7d,0x3, + 0x18,0xf7,0x41,0x90,0x23,0xed,0x77,0x5c,0x61,0x30,0xa2,0xfb,0xe5,0x42,0xc7,0x4f, + 0x4c,0xe2,0x70,0xb0,0xd4,0xc5,0xd0,0xda,0x6a,0xe7,0x2d,0x8e,0xe8,0x67,0x8e,0x3c, + 0x35,0xb5,0xb1,0x46,0x8e,0x1c,0x7a,0xa4,0x71,0xf6,0xe7,0xde,0xde,0x5a,0xfc,0xec, + 0xab,0x3d,0xb,0x40,0x43,0xe7,0xe4,0xb7,0xf0,0xd0,0xfe,0xc2,0x40,0x67,0xcf,0xea, + 0x9a,0xbb,0x95,0xd5,0xc,0x8f,0x46,0x6a,0xd3,0xa0,0x8b,0x72,0xc2,0x13,0xcc,0x91, + 0xaf,0x5f,0xde,0x23,0xd9,0x4c,0xd2,0xe6,0xe1,0x9b,0x49,0x91,0x58,0xef,0xb6,0xe0, + 0xc1,0xdd,0x56,0x23,0x79,0x4b,0xa7,0x77,0x7,0xc4,0x6c,0xb7,0xb5,0x8f,0x38,0x8d, + 0xd9,0xdd,0x17,0xf1,0x56,0x21,0x3f,0xd9,0x44,0x40,0x40,0x99,0xba,0x82,0x91,0xd4, + 0x36,0x97,0x49,0x46,0xb6,0xae,0x7b,0xae,0xd9,0x34,0xbe,0xca,0xc7,0xcd,0xd4,0x12, + 0x31,0x68,0xfa,0xf,0x39,0x4f,0xfb,0x25,0x6c,0xcc,0x0,0x79,0x38,0xd7,0x26,0x33, + 0x40,0x2a,0xaa,0x62,0x97,0x97,0x4,0x3d,0xcc,0xb0,0x92,0x11,0x83,0x57,0xfc,0x5b, + 0x41,0x1,0x42,0x4c,0x1f,0xca,0x86,0x15,0xf5,0xb5,0xf5,0xbd,0xa9,0x81,0xd4,0x15, + 0xee,0x64,0x56,0xae,0xd2,0xb2,0x51,0x33,0x1e,0x68,0xf,0xe7,0xb9,0x57,0x76,0x6e, + 0xec,0xef,0xfd,0xfc,0xdc,0xd7,0xf8,0xfc,0x33,0xf8,0xfc,0x73,0xd4,0xc7,0xd0,0x3f, + 0x67,0xf8,0x55,0x7b,0xd0,0xa1,0x7a,0x43,0x33,0x6c,0x4a,0x28,0xbf,0xe9,0x55,0x42, + 0x54,0x6e,0x3b,0x8b,0x41,0x7,0xda,0x7b,0xf3,0x4e,0xe,0x63,0x9b,0x28,0x72,0xb2, + 0xe4,0x12,0xca,0xe1,0x79,0xca,0x6b,0xcf,0x79,0xc3,0xc8,0x90,0x15,0xc2,0x38,0xe9, + 0x98,0xfe,0xf4,0xe,0x47,0xab,0xc9,0x47,0x66,0xf5,0xe9,0xf9,0x21,0xe7,0x24,0x73, + 0x70,0x8a,0x73,0x6b,0x5d,0xc4,0x44,0x19,0x1,0x5f,0x3f,0x13,0x72,0x5f,0x88,0xd9, + 0x50,0x73,0xa5,0x78,0x57,0xc5,0x1c,0x30,0xaa,0x8e,0xc0,0x21,0xaa,0xd2,0xaa,0x17, + 0x5a,0xa1,0x43,0xf6,0x5e,0x4c,0x5e,0xe8,0x62,0xb1,0x8d,0xc4,0xf6,0x1c,0x63,0x4e, + 0x74,0x26,0x3,0x5,0xdb,0x16,0x3a,0x43,0x9c,0x4c,0x5c,0xd6,0xf9,0x13,0x6c,0x8e, + 0x8a,0x35,0xc8,0x20,0x7a,0xa1,0x96,0x82,0x15,0xc3,0x5b,0xc1,0x48,0x23,0x78,0x26, + 0xcf,0xb6,0x7b,0xd0,0x45,0xfc,0xab,0x26,0x45,0x4a,0x22,0x95,0x74,0x66,0x2,0xea, + 0x7d,0xcf,0xaf,0x87,0xf8,0x77,0x54,0xde,0x1c,0x38,0x2f,0x8d,0xa8,0x39,0x5c,0xbf, + 0x8d,0x64,0x86,0xe4,0x1c,0xd2,0xc5,0x40,0x88,0xc7,0xcf,0x5c,0xb6,0x18,0x33,0x3d, + 0xba,0x4,0xd4,0xea,0xb8,0xcd,0x9f,0xeb,0xfd,0xd8,0x23,0xb2,0xf,0xa2,0xcc,0xc9, + 0x93,0x43,0xaf,0x5,0xe1,0xab,0x80,0x24,0x61,0x96,0x7d,0x66,0x1b,0xce,0xbe,0x3f, + 0xfb,0x39,0x3b,0x3f,0x3f,0x4b,0x66,0xcc,0x3,0xfe,0x8f,0xe0,0xbf,0x13,0x4f,0xf7, + 0x2c,0x61,0xed,0x73,0x96,0x23,0x5c,0xc2,0x7e,0xaf,0x4b,0x55,0x3a,0x7,0xa8,0x45, + 0x1e,0xe1,0x9b,0x4a,0xf3,0x3d,0x15,0x9d,0xd,0xc4,0x43,0xd9,0x7c,0x2a,0xe6,0xc2, + 0xad,0x4d,0x1b,0xb,0x71,0xf5,0xb6,0x28,0xe2,0x19,0x72,0x70,0xaa,0xb0,0xfc,0x13, + 0x10,0xb2,0xd2,0xa1,0xba,0x0,0xa5,0xe2,0x5a,0x8c,0xae,0x6a,0x16,0xbb,0x7f,0xf, + 0xf7,0xdc,0x25,0xfc,0x3b,0x69,0x73,0xea,0x15,0x3e,0xec,0x4a,0x78,0x84,0x77,0x13, + 0xd8,0xf7,0x2,0x22,0x48,0x53,0x66,0x31,0x55,0x94,0x24,0x2d,0x77,0x81,0x39,0xb8, + 0x68,0x25,0x84,0xc1,0xa7,0x97,0x9,0x9e,0xc4,0x5f,0x1a,0xa4,0x18,0x4,0xce,0x87, + 0xa9,0xeb,0xda,0x25,0x77,0x30,0xb0,0xd7,0xc3,0xc,0x77,0x30,0x49,0x18,0xa,0xcb, + 0x1b,0x41,0x91,0x57,0x13,0x9d,0x91,0xd1,0x87,0x66,0xb9,0x33,0xb2,0xa7,0x6d,0x4e, + 0x3f,0x8f,0x68,0x38,0x42,0x3,0x69,0x9,0x2d,0x49,0xdb,0x3c,0x98,0x10,0xf0,0xdf, + 0x93,0x25,0x83,0x4d,0x0,0x68,0x92,0x5,0xf5,0xf5,0xc6,0x70,0x75,0xa0,0xdf,0x9f, + 0x66,0x12,0xc4,0xb9,0x88,0xb0,0x3,0x3c,0x3e,0xd3,0xc6,0xf,0x39,0x1f,0xf8,0x49, + 0xae,0x62,0xa8,0x39,0x98,0x41,0x51,0x36,0x49,0x85,0x86,0xe,0xce,0x63,0x58,0xfd, + 0xd6,0x85,0xc0,0x6,0x66,0x52,0xe8,0x24,0x87,0x9c,0x52,0x9c,0x83,0x30,0x4e,0x47, + 0x4d,0xdd,0x46,0x92,0xa7,0xd7,0x2a,0xab,0x16,0x33,0xec,0xea,0xb7,0x6c,0x9b,0x41, + 0x35,0x4d,0x96,0x71,0xcd,0x4e,0xa2,0x17,0x87,0xf7,0xa4,0xb6,0xf0,0xea,0xef,0x47, + 0xb9,0x90,0x22,0x49,0xec,0x64,0x5f,0xe6,0xf4,0x47,0xbb,0xaf,0xa2,0xfd,0xb0,0xb6, + 0xa5,0xca,0xc9,0xe2,0x3c,0x1d,0x20,0xb2,0xc6,0xe3,0xf4,0x45,0xea,0x87,0xd8,0xcf, + 0xe2,0x88,0x8b,0xb0,0x30,0x24,0xaf,0x88,0xc7,0x43,0x43,0x66,0x3b,0x2f,0x8b,0xc2, + 0x27,0xe1,0x42,0x3e,0x28,0xd7,0xc8,0xb0,0x46,0x62,0x8b,0x1c,0xd2,0xb5,0x56,0x72, + 0xa6,0x3e,0x3,0xb0,0x53,0xb6,0x1e,0x1e,0xc6,0x1d,0xb,0x7f,0xe3,0xff,0xf8,0x57, + 0xef,0x7f,0xf3,0xcf,0xfd,0xc9,0x8f,0x75,0x46,0xea,0x78,0x35,0x5b,0x8e,0xd0,0x4, + 0x9d,0xa0,0x93,0x14,0x52,0x8c,0x94,0x20,0xd1,0x14,0xf5,0x24,0x13,0x33,0xe3,0x50, + 0x9d,0x2b,0xca,0xc8,0x4e,0x39,0x7a,0xcb,0x66,0x7c,0x31,0xab,0x7d,0x34,0x47,0x97, + 0x36,0x57,0x8e,0xbe,0xa7,0x5c,0x93,0x41,0xcc,0x3e,0x47,0xa1,0x1,0x5f,0xac,0x7c, + 0x7a,0x4e,0x53,0xa3,0x48,0x32,0x1,0x6a,0x5,0xc4,0xa,0x21,0x12,0x9a,0x96,0x8, + 0x83,0xa9,0xaf,0xb3,0x7b,0x3d,0x96,0x74,0x61,0x14,0x95,0xb7,0xcc,0x6a,0xd,0xa3, + 0x41,0xd,0xbb,0xb8,0x86,0xef,0xa6,0x6a,0x73,0x8b,0xe0,0xb8,0x10,0x1a,0x76,0x72, + 0xa5,0xbf,0xb0,0x92,0x8a,0x76,0xf0,0xd8,0xae,0x6a,0xdc,0x4a,0x70,0xd8,0xba,0xed, + 0x29,0x22,0xb2,0xd8,0xef,0x18,0xf4,0xf8,0x2d,0xf9,0xa5,0x1b,0xe6,0xc1,0x2b,0xa6, + 0xb4,0x2,0xc4,0xe8,0xd0,0x56,0x75,0xd0,0xd,0xdb,0x30,0x21,0x19,0xc9,0x11,0x9b, + 0xa0,0x91,0xa9,0xb,0xb5,0xbe,0x16,0xe3,0x90,0xcf,0xca,0x2,0xc1,0xa2,0x4b,0xf1, + 0x97,0x6c,0x60,0x4e,0x70,0x76,0x85,0xfa,0xb,0x3c,0xf0,0x85,0x24,0x28,0x2a,0x2d, + 0x7c,0xe3,0x33,0x59,0x7,0xcd,0xca,0xec,0x77,0x60,0xae,0x6,0xa7,0x8a,0x32,0xad, + 0x25,0x25,0x99,0x61,0xd,0x58,0xfe,0x41,0xc7,0x7f,0xa9,0xa,0x62,0xe,0x2e,0x3b, + 0x68,0x69,0x92,0xc5,0x4a,0x39,0xa5,0x3d,0xba,0x29,0xe2,0x52,0x52,0x79,0x15,0x87, + 0x31,0xad,0xea,0xc5,0xb5,0xf7,0xd7,0xd9,0x9a,0xcf,0xe3,0xd1,0xbf,0x8a,0x2f,0x6, + 0x3f,0x85,0x83,0x73,0x5c,0xc2,0xd7,0xbe,0xfe,0x54,0x4c,0x4,0x86,0xfa,0xa9,0xce, + 0x39,0xbd,0x35,0xd9,0xe,0x7b,0xf1,0x6c,0x84,0x4f,0x6f,0xf2,0xd6,0x69,0x30,0xcd, + 0xf4,0xe7,0xcf,0x2f,0x19,0x59,0xc3,0x41,0x63,0x1b,0xf9,0x7c,0xe4,0xf1,0x5e,0x91, + 0xa0,0x5d,0x5b,0xbc,0x4b,0x6f,0xf6,0xbe,0xf,0x8c,0xb9,0xf7,0x5a,0x22,0x3e,0x7a, + 0xaf,0xfc,0x31,0x60,0x40,0x94,0x69,0xd6,0xd8,0x31,0xf9,0xe9,0x6d,0x1d,0x7a,0xdb, + 0x27,0x9f,0x23,0x24,0x1e,0xa8,0xea,0x65,0xa,0xb8,0x20,0xb9,0x5a,0xd8,0xc1,0x77, + 0xf1,0x2b,0x2c,0x29,0xde,0x5,0xe9,0xe6,0x1b,0xe1,0xfe,0xe7,0xc,0x7a,0xb4,0x49, + 0x56,0x55,0xa5,0x2b,0xd7,0x98,0x5a,0x89,0xb2,0x6a,0xc3,0x33,0x25,0xa8,0x85,0xfb, + 0x41,0x71,0x7,0xb5,0x31,0x35,0x8a,0x20,0x58,0xb9,0x30,0xff,0x95,0xc0,0x77,0xef, + 0x49,0x62,0x2e,0xd,0x63,0x90,0x85,0xa1,0x7d,0x8d,0x41,0xe4,0xc3,0x99,0x7a,0x83, + 0xcf,0x2d,0xd0,0x2b,0xa2,0xc9,0xb7,0x7a,0x40,0x1c,0xb8,0xb4,0x93,0x39,0xb2,0x3f, + 0x94,0x44,0x86,0x64,0x13,0xe7,0x77,0x5c,0xf4,0xbe,0x92,0x69,0x1e,0xd3,0xaa,0xee, + 0xc6,0x74,0x1f,0x85,0x3c,0x5e,0xc8,0xbf,0x62,0x78,0x2d,0x12,0xf2,0x8d,0xcf,0x67, + 0x8d,0x15,0x6d,0x13,0x6c,0x90,0x93,0x50,0xb8,0x4c,0xee,0xbc,0xb5,0x60,0xcc,0x90, + 0x5c,0x3c,0x42,0x9,0x81,0x26,0x8c,0xaf,0xeb,0x3a,0xcf,0xdd,0x26,0x1b,0x1d,0xb, + 0xc7,0xd4,0xfb,0xd,0x32,0x8,0x21,0x1b,0xf0,0xe6,0x75,0x2a,0x8b,0x9f,0x43,0x85, + 0x39,0xde,0x33,0xcc,0x53,0x10,0x93,0x7,0x41,0xa2,0xc5,0x19,0xf0,0xa7,0xc7,0x3b, + 0x24,0xc6,0x96,0x77,0xb4,0xb1,0x37,0x77,0x99,0x42,0x1b,0x1b,0xaa,0x26,0x65,0xac, + 0x23,0x77,0xc8,0x8b,0xc4,0x50,0x5d,0x46,0xd2,0xc0,0xf0,0x7c,0x47,0x10,0x4e,0x33, + 0xfc,0x98,0xad,0xb2,0x4e,0x1c,0x0,0x31,0x76,0xda,0x15,0xae,0x66,0xb5,0x3f,0xd, + 0x5c,0x1b,0x95,0x61,0xf3,0x9b,0x4f,0xd7,0xbf,0xcd,0x17,0xd9,0xf9,0x56,0x8a,0xec, + 0xd0,0x68,0x88,0xad,0x25,0x71,0x85,0x30,0x51,0x38,0xf5,0x51,0xb5,0x35,0x86,0x24, + 0xb5,0x9a,0xdf,0x38,0x9c,0x23,0xd2,0x38,0x23,0x35,0x4f,0xe7,0x0,0x83,0x9f,0x8e, + 0x8f,0x3d,0x35,0xb1,0x2f,0xb8,0x75,0x6f,0xca,0x5f,0xdb,0x67,0xb0,0x4f,0x81,0x7e, + 0x5,0x85,0xab,0x27,0x19,0x12,0x50,0x90,0x3c,0x61,0x21,0xa6,0x7a,0xee,0x70,0x35, + 0x6f,0x70,0x5a,0x1c,0xa9,0xe0,0x50,0xc9,0x98,0xb2,0x9a,0xd6,0xc,0x4e,0x86,0xda, + 0x62,0xd2,0x9,0xe,0x36,0x42,0x4f,0xea,0xa0,0x48,0x5f,0x9c,0x49,0x76,0xe,0x69, + 0x6e,0x6d,0x3,0x94,0xa3,0xa,0xb,0x51,0x7e,0xd6,0x3,0x95,0xa8,0x9c,0x52,0xce, + 0x10,0x24,0x82,0xe2,0x7a,0x18,0xb3,0x32,0x50,0xf7,0x36,0x29,0x90,0xe9,0xd3,0x19, + 0x8c,0xb5,0xbc,0xc6,0x42,0x49,0x13,0x61,0x43,0xf0,0x41,0xde,0x7a,0x47,0xb8,0x4c, + 0xe0,0x2,0x1,0x93,0xe,0x14,0xc6,0x1e,0xa0,0xc9,0x5e,0xfd,0x34,0x13,0xe7,0x93, + 0x72,0x15,0xf,0xfe,0xbc,0x43,0x3f,0xd5,0xfa,0xd6,0x26,0x9,0x3c,0x54,0x5f,0x65, + 0x52,0x91,0x99,0x89,0xda,0xdf,0xd5,0xe1,0x92,0x25,0xe5,0xb,0x5b,0xf2,0xd4,0x3f, + 0x19,0x61,0xf4,0x13,0x94,0xd8,0xf6,0x14,0x5d,0x9c,0x23,0x83,0xfc,0xd8,0xa6,0x63, + 0xdf,0xd8,0xfc,0x14,0xd4,0xe3,0xb3,0x4c,0x15,0x6e,0xf7,0xa1,0xf6,0x7b,0x57,0xe6, + 0xc8,0xb2,0x3e,0x55,0x8a,0xfb,0xe4,0xef,0x80,0x40,0x32,0x8f,0x24,0x2a,0xa2,0xa9, + 0xee,0xd2,0x8e,0xb6,0x5b,0xd,0xce,0xd9,0x49,0x59,0x80,0x67,0xec,0x3e,0xf2,0xda, + 0x4b,0xd7,0xea,0x53,0x5d,0xec,0xa,0xd9,0xad,0x76,0x0,0xcb,0xc4,0x37,0x62,0xa2, + 0x60,0x59,0x77,0x42,0xa1,0xbd,0x1b,0x22,0x55,0xe9,0xdb,0x84,0xf5,0xe4,0xf7,0x50, + 0xf4,0xde,0x35,0x30,0x70,0xd8,0x39,0xd4,0xe6,0x8d,0x55,0x6e,0x30,0x13,0xa0,0xa6, + 0x3f,0x18,0x2e,0x75,0xc6,0xc7,0x40,0x47,0x2f,0x8,0xf,0x28,0xd9,0xae,0x54,0x9, + 0x65,0x7b,0x3b,0x53,0x46,0xa4,0x8f,0xda,0x98,0xe4,0xae,0x1c,0x5a,0xde,0xd2,0x45, + 0xe3,0xa2,0x4c,0xd6,0xa4,0x34,0x9e,0x35,0x44,0x22,0xb4,0x4c,0x2,0xdc,0x2b,0x37, + 0x3a,0xaf,0x3,0x7a,0x78,0xc2,0x7d,0xe1,0xc3,0xa5,0x8c,0x48,0x73,0x16,0x36,0x60, + 0x87,0x26,0x20,0x43,0x1f,0x41,0xad,0x6e,0xce,0x46,0x19,0x99,0xa4,0xca,0x3c,0x87, + 0xdc,0x2d,0x52,0x64,0x0,0xe9,0xae,0xb5,0x45,0xaf,0xd2,0x37,0x1,0x21,0x77,0xfb, + 0x8,0xb4,0xec,0x40,0x45,0x63,0xcd,0x27,0x4d,0x9e,0xb6,0x25,0x9f,0x7b,0x98,0x59, + 0x29,0x85,0x17,0x23,0xeb,0x3e,0xd6,0x81,0xee,0x34,0xf5,0xee,0x6,0xd0,0x24,0xbf, + 0xbd,0x4b,0xe1,0x2e,0x79,0xe6,0x15,0x5f,0xa1,0xb3,0x17,0x8e,0x80,0x1b,0x8d,0x75, + 0xfb,0x54,0x8,0xa2,0x82,0x49,0x22,0xd7,0x50,0x50,0x4f,0x5a,0xd7,0x75,0x89,0xc7, + 0xc5,0xaa,0xd6,0xb,0xdf,0x30,0x1a,0x1b,0x32,0x28,0x15,0x36,0xfa,0x9c,0x5a,0xa8, + 0x98,0x35,0xd0,0x1a,0x69,0x13,0x35,0x77,0x2a,0xbe,0x20,0x96,0xab,0x5,0x1b,0x84, + 0xd7,0x2b,0x6,0x48,0xaf,0xa5,0xd8,0xf3,0x1c,0x7a,0x22,0x93,0xc9,0xac,0x6c,0x4a, + 0x7b,0xea,0x94,0x96,0x2c,0x46,0x95,0x96,0xb,0x26,0xe3,0x62,0x78,0x23,0x5e,0xc3, + 0x61,0x74,0xaa,0x79,0x38,0x2b,0x21,0x6b,0x6b,0x1b,0x1b,0x9b,0x16,0x43,0x3b,0x2d, + 0xae,0x15,0x89,0xcd,0xf7,0x39,0xa7,0xaa,0x93,0xe0,0x41,0x1e,0xf6,0x36,0xeb,0x59, + 0x21,0xee,0x80,0xc9,0xef,0xce,0x5d,0xbc,0xb4,0x12,0x7f,0x32,0x47,0x3d,0x5c,0xe9, + 0x99,0x68,0x69,0x2f,0x67,0xe8,0x49,0xa7,0x54,0xad,0xcb,0x8b,0x50,0x24,0xa,0x85, + 0xe9,0xdc,0xe6,0x34,0xbd,0x27,0x6,0x93,0xba,0xd,0xab,0xce,0x8a,0xf9,0x5f,0xcd, + 0xf8,0xb3,0xf7,0x26,0x33,0xd2,0x95,0x58,0x11,0xd2,0xdd,0xce,0x25,0x54,0x39,0xf9, + 0x21,0x97,0xb3,0xb5,0x11,0xdf,0xa3,0xa7,0x20,0xa3,0xa7,0x35,0x3a,0xa1,0x45,0x75, + 0xc2,0xe8,0xe5,0x3a,0x2f,0x49,0x5,0x60,0x50,0x6d,0x4,0x9a,0x3a,0xfa,0x3,0x17, + 0x2e,0x91,0xbe,0x9c,0x49,0xe8,0x72,0xcf,0xe1,0x57,0x6e,0x2f,0x25,0x5,0x96,0xf4, + 0xb5,0x6b,0xf,0x18,0x50,0x89,0x91,0x93,0x66,0x80,0x60,0xc5,0xcc,0x4a,0x5a,0x45, + 0x9b,0xa8,0xf7,0xad,0xa3,0x13,0xa5,0x8e,0x6f,0xf0,0x79,0xf3,0xcd,0xa5,0xe0,0xf6, + 0x49,0xa7,0x1f,0xd4,0x3a,0x83,0x6d,0x92,0xc9,0x4c,0x99,0x91,0x6d,0x8e,0xb1,0xad, + 0xe6,0x7d,0xe2,0x62,0xf3,0x64,0xd5,0x5d,0x31,0xa4,0x49,0xe9,0x42,0x3b,0x8a,0xb2, + 0x2c,0x29,0x53,0x26,0xf7,0x1c,0xe6,0x72,0x98,0xea,0xdd,0x6c,0x7f,0xef,0xe3,0x8b, + 0x80,0x53,0xb0,0xa9,0x6d,0xc1,0xd0,0xf2,0x68,0xeb,0x0,0xf0,0xbd,0xb,0x97,0x41, + 0x1,0xfa,0x24,0x48,0xde,0xcb,0x9a,0x74,0x1,0xe,0x4,0x46,0xea,0x77,0x5f,0x3, + 0xb9,0x71,0xa8,0xf,0xc,0x45,0xdd,0x23,0x5,0x75,0x54,0xf1,0xbd,0x12,0xdd,0x9d, + 0xda,0x6e,0x93,0x49,0xcf,0x14,0xde,0x26,0x77,0x4b,0xd7,0xec,0x60,0xc8,0xe9,0x4e, + 0xb7,0x60,0x98,0x9e,0xb6,0xf5,0xfd,0xdf,0xfd,0xb3,0x1f,0xbd,0xff,0x9d,0xff,0xf4, + 0xa7,0x3f,0xd8,0x1c,0x48,0xe3,0x47,0xc2,0xa7,0x49,0x0,0xe,0x9a,0x20,0x3e,0x12, + 0xf7,0x74,0x63,0x5b,0x96,0x4f,0x4,0xab,0x3a,0xcc,0xe0,0x5b,0x20,0x69,0xc5,0xf4, + 0x30,0x7a,0xf2,0x6c,0x82,0xec,0x2f,0xa6,0xe2,0x59,0xb,0xc0,0x7d,0x68,0xd3,0x42, + 0x23,0xd2,0x80,0x82,0x1e,0xa8,0x7,0xf1,0x5,0x98,0x38,0xc4,0x26,0xd1,0xa1,0x69, + 0xbb,0xc7,0xb8,0x98,0x9,0x56,0x20,0xe6,0x22,0x69,0xc2,0x2e,0x15,0xe,0xc3,0xca, + 0xae,0xcb,0xd1,0x1f,0x86,0x8d,0xa1,0x8a,0x7c,0xf0,0xc5,0xc4,0xe6,0x16,0xe,0x41, + 0x4f,0xd,0xae,0xbb,0xe7,0x73,0xf7,0x30,0x75,0xee,0x51,0x33,0x4d,0x3b,0x50,0x3e, + 0xcb,0x66,0xdb,0x79,0x27,0x77,0x26,0x26,0xc2,0xe8,0x7,0x22,0x49,0x30,0xcf,0x3f, + 0x5c,0xee,0xac,0x17,0x5b,0x66,0xcd,0x3d,0x3f,0x15,0xc,0xa2,0x82,0xa4,0x54,0x78, + 0x7a,0x5f,0x59,0x2e,0x6e,0xd1,0x46,0x4,0xd1,0x4c,0xa9,0x8c,0x30,0xd9,0x2,0xac, + 0x56,0xf,0x2e,0x3a,0x63,0xa,0x65,0xf2,0x7d,0xc,0xa1,0xe,0x87,0x82,0xcb,0xe, + 0xc1,0x74,0xd2,0xd3,0xdf,0x89,0x90,0x3e,0xdf,0x42,0x40,0x31,0xd3,0x4b,0x88,0x58, + 0xc5,0x7e,0xa3,0x8d,0x8e,0x19,0x17,0x5,0x4b,0xe8,0x47,0x2d,0x81,0x95,0xf5,0x41, + 0x4d,0x0,0x19,0xf0,0xa4,0x91,0xdd,0xe0,0xea,0x8a,0xd4,0xea,0x1a,0x1,0x35,0x33, + 0xf4,0xff,0xe9,0x2,0x2e,0x8d,0xe0,0xa8,0xda,0x14,0xb4,0xf5,0x3e,0x77,0xe2,0x94, + 0x71,0xcf,0xb6,0xe6,0xc2,0xe1,0xc0,0x84,0x4c,0x54,0x7a,0xd5,0xfc,0xa7,0x2f,0x84, + 0xe5,0xac,0x27,0x13,0xad,0x25,0xf6,0x7c,0xe0,0xe5,0xc7,0x56,0x79,0xba,0xba,0xb8, + 0x2e,0x68,0x6c,0x66,0xff,0x2e,0xe,0x41,0xe6,0xfc,0x1f,0x44,0x3f,0x1e,0x7,0x52, + 0x7d,0xeb,0x6f,0xc5,0x64,0x1a,0xe,0xa,0x2f,0x7,0x9,0x92,0x76,0x2f,0x2e,0x57, + 0xe8,0x9c,0x2,0x1b,0x4f,0x88,0x5e,0x44,0xba,0x43,0xa0,0xcd,0xd6,0x11,0x62,0xc4, + 0xcf,0x7b,0xd9,0xa7,0x11,0x38,0x29,0x79,0x31,0xb9,0xbc,0xe5,0xf5,0xa7,0x90,0x8b, + 0xf2,0x8a,0x54,0xa7,0x23,0x48,0xa9,0xf4,0xf1,0x3c,0x44,0x3b,0x7a,0x4d,0x4f,0x3c, + 0xae,0x96,0x94,0xcf,0x6d,0xfe,0xca,0xd1,0xb3,0x5b,0xa6,0x39,0x13,0x32,0xc0,0xb8, + 0x3f,0xa8,0x37,0xd5,0xe4,0x7d,0x8,0x16,0x58,0x4c,0x68,0xe7,0x22,0xd3,0xd,0x41, + 0x5,0xce,0xa,0xd8,0x5,0x1c,0x86,0x6a,0x2b,0x88,0x54,0x25,0x96,0x79,0xae,0xe1, + 0xcc,0x68,0xd,0x2f,0x28,0x74,0xcd,0xee,0xd,0xb4,0x54,0x65,0x9,0xca,0xe7,0xf3, + 0x44,0x18,0x9a,0x1a,0x6,0x2b,0xd1,0xb9,0xc4,0x79,0x2d,0xd8,0xfb,0x2d,0x86,0x63, + 0x5b,0xdc,0x71,0x20,0x7c,0x61,0x67,0xf3,0x54,0xeb,0x41,0xc2,0x61,0x29,0xcb,0xa, + 0xbb,0x13,0x54,0x9f,0xdc,0x42,0x93,0x2,0x5f,0x4,0x8f,0x87,0xf8,0xfa,0x29,0x87, + 0xf8,0xa7,0x40,0xc8,0xa,0xb9,0x2b,0x8c,0xf6,0x29,0x35,0x2e,0x44,0xe6,0xb1,0x61, + 0xb2,0xb5,0x74,0xad,0x11,0x9c,0x5,0xf3,0x1c,0xea,0x6,0x57,0xc3,0xc6,0x16,0x62, + 0x94,0x9,0x82,0xac,0x8e,0xaa,0xac,0x43,0x6d,0x87,0xdd,0xf7,0xc9,0xfc,0xaf,0x15, + 0x36,0xa6,0x98,0xb8,0xc8,0xef,0x32,0xa6,0xac,0x6b,0x40,0xab,0xe7,0xbd,0x5b,0x74, + 0xfb,0x41,0xad,0xeb,0x14,0xcd,0xc2,0xcf,0xe8,0x51,0x9d,0x18,0xc4,0xd0,0x59,0xf8, + 0xd6,0xe4,0x83,0xa1,0x5c,0x87,0x13,0x1f,0x90,0xb1,0x16,0xb4,0x73,0x61,0x94,0xe9, + 0xb5,0xaf,0xc8,0xf7,0x85,0xcf,0xb0,0x3e,0x2b,0x95,0x1b,0x6b,0xed,0x79,0x6c,0x18, + 0x3c,0x75,0xe6,0xaf,0x30,0x54,0xaa,0x8a,0xbd,0x8c,0xd1,0x55,0xd0,0xe,0xf2,0x75, + 0x5e,0x5c,0x8b,0x89,0xac,0xb2,0xd4,0xcc,0x73,0xb9,0xf,0xe1,0xc6,0xd9,0xb3,0x67, + 0x8b,0x55,0xf3,0x5b,0xf7,0xd7,0x5a,0x77,0xd9,0x53,0x1b,0xf8,0x15,0x66,0xb1,0x2b, + 0x6d,0x22,0x30,0xf5,0x8,0x68,0xeb,0xbc,0xbb,0xb3,0x89,0xaf,0xfb,0xd0,0xc6,0x7b, + 0x46,0xbe,0x40,0x77,0x95,0x33,0xf6,0x17,0x6b,0x78,0x86,0xa9,0xd7,0xae,0xb7,0x23, + 0x19,0x91,0x75,0x20,0x68,0x8a,0xe2,0xe5,0xe4,0x8f,0xb0,0xf8,0x38,0xee,0xd2,0xb6, + 0x51,0xbb,0x20,0x68,0x12,0x87,0xda,0x16,0x7e,0x8f,0x93,0x3c,0xd8,0x8e,0x11,0xf9, + 0x6e,0x1c,0xe,0x1c,0x83,0xe4,0xb3,0xfd,0x3a,0x94,0xcc,0xf0,0x42,0xe8,0xfb,0xff, + 0xd9,0xcf,0x7c,0xfc,0xb7,0xff,0xfb,0xbf,0x7c,0x27,0xab,0xfe,0xee,0x2f,0xfc,0xcc, + 0x47,0x6a,0x22,0x4c,0x9d,0x62,0xbd,0xcf,0xac,0x2d,0x4e,0xa3,0xc4,0x64,0xe,0x7b, + 0x9c,0xea,0x11,0xa2,0xe8,0x20,0x20,0x63,0xe2,0x68,0x52,0xd0,0x57,0xc2,0x34,0x9d, + 0x96,0xd8,0x75,0x6e,0x4b,0x61,0xb8,0x72,0xb8,0xac,0x59,0x1a,0xe,0x84,0x60,0x3b, + 0xee,0xe0,0xf,0x49,0x35,0xa2,0x1b,0x88,0xfa,0xe8,0x40,0x13,0xad,0x35,0xcd,0x10, + 0x9e,0x31,0xa2,0x54,0x55,0x53,0x55,0x53,0xd7,0x2f,0x46,0xa5,0xe3,0x6a,0x78,0xc3, + 0xef,0x30,0x88,0x9f,0xee,0xeb,0x91,0xa4,0x1f,0x19,0x75,0x68,0xa9,0xf2,0xc3,0x4b, + 0x20,0x86,0xf9,0xcb,0x6a,0xe2,0xc,0x76,0xaf,0x10,0xc2,0x3c,0xb6,0xe1,0xb8,0xe7, + 0xa1,0x65,0xc4,0x61,0x65,0xf5,0x9c,0xf8,0x6b,0x90,0xd7,0x6c,0x63,0x6,0x58,0x56, + 0x3c,0xb,0x10,0x32,0x38,0x11,0x1b,0x8a,0xf,0x29,0x3a,0x74,0xe7,0x73,0x4c,0xd4, + 0xc4,0xa3,0xfc,0x95,0x6a,0x5c,0x33,0x64,0x60,0x13,0xea,0x42,0xb,0xb7,0x8,0xe6, + 0xda,0x82,0x14,0x2f,0xd8,0x6f,0x18,0x39,0x87,0x3,0x9b,0xdc,0x14,0xc2,0xea,0x52, + 0x50,0xb5,0xed,0x97,0x93,0xe,0x46,0x23,0xe3,0x1d,0x54,0x1a,0x59,0x89,0x8a,0x6c, + 0x88,0x80,0x21,0x48,0xe2,0x9d,0xaa,0xcb,0x12,0x1b,0xa3,0xe9,0xac,0xef,0xbb,0xaa, + 0xfb,0x54,0xd6,0xa0,0x38,0x76,0x75,0x76,0xfb,0xb0,0xc9,0x31,0x54,0x75,0x18,0x60, + 0xcf,0xe2,0x30,0xfa,0x65,0x2c,0x79,0x59,0x6d,0x29,0xbe,0xc1,0xde,0x8b,0x47,0xb6, + 0xba,0x92,0x67,0x8b,0x3c,0x68,0xd8,0x92,0xab,0x9c,0xfb,0x44,0xf6,0xef,0xd8,0xd7, + 0xa2,0x6b,0xaa,0x96,0x8d,0x43,0x15,0x6b,0x50,0x2,0x43,0x8f,0x61,0x27,0x2b,0x54, + 0xbd,0x28,0x38,0x83,0xff,0x34,0xf1,0xe7,0xf0,0x7c,0x56,0x94,0x2a,0x79,0x2c,0x86, + 0x20,0x74,0x48,0xc4,0x8,0x9a,0x3,0xff,0x15,0x21,0x3c,0xd6,0x9c,0xc3,0xd0,0x51, + 0xd4,0xbe,0x9e,0x63,0x8b,0x5f,0x29,0x9c,0xf5,0x1c,0xc3,0x97,0x21,0x37,0x6c,0x94, + 0xec,0x24,0x23,0xce,0x22,0x4e,0xbb,0xeb,0xef,0x53,0x5,0xcf,0x18,0xe3,0xe4,0xd6, + 0x41,0x7a,0x9b,0xee,0xfb,0xff,0xf9,0xcf,0x7c,0xfc,0xdd,0x5f,0xf8,0xd9,0x8f,0x5f, + 0xff,0xa7,0xff,0xf2,0x9d,0x55,0x3,0x9a,0x13,0xae,0x6c,0xd1,0x5a,0x75,0x39,0xee, + 0x6a,0x5,0x27,0xc3,0xbc,0x7,0xb1,0xce,0x18,0xc,0x9a,0x25,0x8c,0x76,0x3f,0xf3, + 0x4b,0xf,0x7,0x5a,0x1c,0x4b,0xd5,0x2f,0x81,0x1c,0xb,0x83,0x47,0x31,0x9c,0xe8, + 0x84,0x72,0x32,0x90,0xf4,0xb3,0x90,0x2c,0xd6,0x41,0xe6,0x8e,0x9,0x63,0xda,0x22, + 0x80,0xc3,0x63,0x19,0x62,0xc2,0x74,0x0,0x8,0xc5,0x35,0x86,0x3a,0x1d,0x14,0x86, + 0xc4,0x76,0xe4,0x81,0x58,0x1f,0xe0,0x60,0xe1,0x8,0x4,0x74,0x18,0x3d,0x2b,0xc0, + 0x44,0x14,0xcd,0x5a,0x71,0x82,0x9d,0x10,0x7a,0xc4,0xe7,0x6e,0x53,0x70,0xdf,0xbd, + 0xc7,0x6,0x85,0xd6,0x35,0x23,0xc,0xf8,0x5d,0xbf,0xfa,0xef,0xfd,0xc2,0x4f,0x7f, + 0xfc,0xd7,0xff,0xe4,0x47,0xef,0x0,0xc2,0x92,0xf3,0x0,0xeb,0xa1,0xd7,0x8d,0x1c, + 0xd8,0xcc,0xa8,0xd4,0xe5,0xc6,0x6b,0x38,0x2e,0x89,0x1f,0x9c,0x2c,0x6f,0x7a,0xb4, + 0x9c,0x38,0x19,0x30,0xc,0xe0,0x1a,0x98,0xc6,0x91,0xb0,0x56,0x12,0xc1,0xb2,0x8d, + 0x84,0x91,0xc7,0x5d,0xea,0xbb,0x3e,0x69,0xd2,0xf,0xf3,0xb6,0x35,0x24,0x35,0x8d, + 0xab,0x62,0x6b,0x82,0xce,0xac,0x4f,0x8d,0x41,0xe4,0x5e,0x84,0x89,0xa9,0xf8,0xc1, + 0x43,0xa7,0x2c,0xe3,0xd0,0x8f,0x4,0x6,0xb9,0x43,0x58,0x2b,0xc4,0x49,0x5e,0xca, + 0x2c,0x9e,0xad,0x61,0x4d,0x29,0x30,0x54,0x28,0x4f,0x49,0x1,0x51,0xa3,0x3d,0xee, + 0xee,0x27,0xd7,0xe0,0x58,0x33,0x24,0x41,0x63,0x60,0xdd,0x8,0x8d,0xf7,0x51,0x60, + 0x68,0xc2,0x90,0x57,0x36,0xc5,0x45,0xef,0x77,0xeb,0x57,0x5e,0x33,0xe4,0x7c,0xe9, + 0xbd,0x1c,0x92,0x3e,0xdb,0x6b,0x97,0x15,0xaf,0x8f,0x5a,0x25,0x5a,0x72,0xa1,0xe, + 0x91,0x77,0xcb,0xec,0xaa,0x9e,0x80,0x5c,0x52,0x34,0x5d,0x9d,0x63,0x5b,0x95,0xa, + 0x98,0x15,0xba,0xf2,0x99,0xa8,0xce,0x44,0xe7,0xd6,0xaf,0xf,0xbe,0x48,0x95,0x56, + 0xcc,0x61,0xe,0xc6,0x81,0x6e,0x21,0x6d,0x23,0xda,0x80,0x63,0x9a,0x4d,0x94,0xdb, + 0x64,0x37,0xa1,0x16,0x57,0xb0,0xf3,0x16,0xe7,0x3d,0x52,0xf8,0x59,0xa6,0xef,0xbf, + 0xca,0x89,0xcf,0xce,0xb7,0x78,0xb8,0x67,0x4b,0xaf,0x7d,0xb5,0x57,0xb7,0xc4,0xf3, + 0x43,0xb2,0x7b,0xa0,0xf7,0x3d,0x29,0xb2,0x89,0xb7,0x10,0x59,0xe8,0x87,0x2b,0x1, + 0xd5,0xa4,0x8,0xde,0x8f,0xe6,0xa9,0x6f,0xc6,0x2a,0xc4,0x34,0x32,0xb6,0xd5,0xc8, + 0x68,0x1,0x0,0x6d,0xc4,0xd7,0xe7,0x97,0x75,0x6e,0x93,0x6,0xef,0xd1,0x18,0xa7, + 0x39,0xce,0x80,0x93,0xd5,0x4b,0x28,0x46,0xb9,0x6d,0xdd,0xaa,0x9a,0x39,0xbc,0x67, + 0x50,0x4c,0xb2,0x3f,0x47,0xf4,0x6e,0x75,0x74,0x21,0xd1,0xac,0x55,0x91,0x29,0xf9, + 0x8a,0x65,0x63,0x87,0x81,0x52,0x2b,0x75,0xb3,0x11,0xe6,0x95,0x6e,0x3b,0x19,0xc0, + 0x73,0x86,0x58,0x6d,0xfe,0xda,0xe6,0xc0,0xe9,0x3d,0xd9,0x20,0x77,0xfc,0xda,0x3f, + 0xfe,0xd1,0xfb,0x6f,0xfe,0xe2,0x4f,0x7f,0x44,0xca,0xba,0x3e,0xe3,0x3c,0x23,0x1d, + 0x7d,0x90,0xaa,0xb1,0x69,0xd6,0xc,0x76,0x96,0xd5,0x68,0xac,0xab,0x14,0x52,0x49, + 0xef,0xd3,0x49,0xf,0x35,0xe7,0xf7,0xf5,0x3a,0x98,0x76,0x9f,0x1b,0x13,0xbe,0xd6, + 0x6c,0x73,0x2b,0xf1,0x84,0x11,0xcd,0xd6,0x4a,0x69,0xd,0xb3,0x5,0xa1,0x62,0x2b, + 0x57,0x8d,0xfd,0xcb,0x68,0x6a,0x4f,0xf2,0x93,0xcf,0x9a,0x31,0x4e,0x2,0x7,0x73, + 0x19,0x84,0xfa,0x96,0x38,0x32,0x61,0x26,0x9f,0xfa,0x60,0x49,0xe8,0xb5,0xc3,0xc7, + 0x74,0xd8,0x88,0x86,0x99,0x4,0x25,0xa,0x8a,0x5e,0x5c,0x5e,0x5f,0xff,0xf,0xa2, + 0x16,0xa9,0x96,0xcb,0x44,0xb2,0xf9,0xf,0xda,0x2c,0x97,0xce,0x11,0x67,0x40,0xcb, + 0x49,0x87,0x74,0x9e,0xc3,0xb8,0x5c,0x17,0x99,0xcf,0x8,0xdb,0x6d,0xbe,0x41,0xe6, + 0xe8,0xb1,0x44,0x45,0x60,0xc2,0x2b,0xd6,0x4c,0xf2,0x2e,0x9e,0x20,0x75,0x4b,0xcc, + 0x4a,0xac,0x3c,0x51,0x3e,0xca,0xf4,0x8c,0x1e,0x19,0x51,0x35,0xb9,0x38,0x74,0x4a, + 0xe9,0xd2,0xcc,0x60,0xc0,0x9,0x22,0xc0,0x42,0x96,0x59,0x61,0xef,0xdf,0xe5,0xea, + 0x93,0x6b,0xe2,0x84,0x93,0xd1,0xd6,0x6e,0xa7,0x55,0x85,0xd8,0x54,0x12,0x5d,0xd1, + 0x74,0x83,0x5a,0x1b,0x4d,0xcf,0x3c,0x22,0x94,0x4c,0x90,0x64,0xd5,0xbb,0x5,0xb8, + 0x7e,0x83,0x5a,0x3,0xb,0x5f,0x8a,0xbb,0x3d,0x46,0x20,0x8c,0x62,0x4b,0xae,0x1b, + 0x5d,0xaf,0xa9,0x7c,0xf2,0x8,0x60,0x6b,0xdb,0xaa,0xfe,0x3f,0xe9,0xf7,0x79,0xb5, + 0x95,0x58,0xed,0x77,0x20,0xda,0x17,0x66,0x78,0x3,0xd7,0xa0,0xa0,0xf8,0x50,0x9b, + 0xab,0x68,0x8c,0xe9,0xf2,0x8e,0x39,0x29,0xd6,0x85,0xb8,0xf7,0xcf,0xef,0xbe,0x74, + 0x53,0x4f,0x1c,0x46,0xd,0xde,0xf3,0x84,0x35,0x3c,0x83,0x4,0xc6,0x2a,0x6e,0xa7, + 0x6a,0xd7,0x5c,0xf7,0x41,0xec,0x2c,0xab,0x3a,0x61,0xa1,0x7a,0x55,0xd9,0x4e,0x33, + 0xc6,0xd4,0x1f,0x30,0x54,0xd2,0x92,0xe7,0xd,0x2a,0x56,0x4d,0x7f,0xb8,0xc2,0xdc, + 0xa5,0xdd,0x26,0x1a,0xfb,0x7b,0xcf,0x41,0x86,0x60,0x3f,0x7b,0x75,0x72,0x79,0x7f, + 0xa0,0x13,0x35,0x1c,0xdf,0xea,0x9a,0xce,0x9c,0x2a,0x1,0x31,0xa1,0x11,0x21,0x84, + 0x87,0x84,0xf1,0xf4,0x70,0x6c,0x81,0x6a,0x7e,0xf0,0x19,0x2c,0x4a,0x64,0x1f,0x23, + 0x82,0xf5,0xa,0x8c,0xe1,0x55,0x2c,0x3d,0xfd,0x65,0xa9,0x98,0x10,0x1e,0x26,0x7d, + 0xe7,0x9c,0xc9,0xa7,0x13,0xcf,0x3a,0x46,0x3d,0xb7,0x7d,0xcc,0xd0,0x12,0x42,0x86, + 0xc3,0x5c,0x2d,0x63,0x26,0x84,0xa1,0x7a,0x95,0xcd,0x30,0xf2,0xc0,0x21,0xf5,0x4c, + 0x27,0xb2,0x5c,0x4f,0x6c,0x2e,0x6c,0x5e,0x21,0x4c,0x9d,0xe5,0x4d,0x58,0xec,0xc5, + 0x7c,0xce,0xff,0x4f,0x6d,0x84,0xe4,0xda,0x8d,0xac,0xa9,0xa1,0x68,0x66,0x79,0x2, + 0xa1,0x2d,0x1f,0x9f,0xfc,0xc6,0xa,0x7e,0x40,0xe2,0xde,0x9a,0x90,0xf8,0xfc,0x2c, + 0xd1,0xc0,0x64,0x7,0xaf,0xe8,0x3,0x6e,0x7b,0x30,0x5,0xbd,0x52,0x54,0x64,0x4c, + 0xd7,0x16,0x87,0xa5,0x66,0x3a,0xf2,0x33,0xfa,0x96,0x81,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x65,0x6a,0x98,0xfb,0x5c,0xd8,0x5e,0xe8,0x8f,0x73,0xa2,0x57,0x8d, + 0xdc,0x48,0x5,0x7b,0xe2,0xc4,0x25,0x3,0xac,0x82,0x20,0xca,0x42,0xa7,0xb1,0x24, + 0x11,0x8c,0xf9,0xd,0xd7,0x4a,0x9b,0xa5,0x2,0xe6,0x2f,0x21,0x4e,0x2e,0x22,0xa2, + 0xf0,0x3a,0xe0,0xee,0x77,0x53,0x22,0xe8,0x3,0xe8,0x3b,0xb6,0xa5,0x47,0x7c,0xf2, + 0x94,0x9b,0x6d,0x6e,0x94,0xf0,0xdd,0xc9,0x32,0x70,0xa,0x6,0x6d,0x5d,0x9c,0xe6, + 0x18,0xd3,0x7,0xb6,0xf,0x1b,0xc4,0xae,0x2d,0x87,0xcc,0xa1,0xf,0xee,0x7a,0xb6, + 0x3f,0x2e,0xa9,0xe6,0xef,0x4,0xf3,0xb3,0x46,0xa2,0x26,0x45,0xbe,0x75,0x50,0x54, + 0x71,0xa4,0x46,0x91,0xee,0xfb,0xf3,0x94,0xb0,0xec,0x82,0x56,0x81,0xf8,0x1a,0x4c, + 0x31,0xb4,0x36,0x6d,0xfd,0xe3,0x51,0x8a,0x7b,0x21,0x63,0x18,0x44,0x8e,0x4a,0x92, + 0x14,0x8d,0x85,0x12,0x7,0x34,0x5d,0x99,0x8b,0x87,0x40,0x6c,0xa9,0x5c,0x27,0x32, + 0xf4,0xca,0xcd,0x52,0xdf,0x79,0x66,0x0,0x13,0x29,0x22,0x8,0x78,0x39,0xa,0x47, + 0x74,0xee,0xdc,0x94,0xc5,0x62,0xb3,0x83,0x7d,0x76,0x94,0xcd,0x1d,0x2a,0x21,0x56, + 0x8,0xb9,0x83,0x87,0xcd,0xd5,0x60,0xe7,0x2a,0x1b,0xd,0x9b,0xb2,0x34,0x36,0x4d, + 0x39,0xac,0x16,0xa5,0x2a,0x8f,0x92,0x9d,0x26,0x64,0xe,0x63,0x3c,0xb5,0x8c,0x31, + 0x90,0x3e,0x20,0xd6,0x9a,0xf4,0x19,0xf8,0x27,0x98,0x5e,0x7c,0x4a,0xb8,0xde,0x3a, + 0x49,0x1e,0x84,0x3c,0xdb,0x45,0x36,0xc,0x8b,0xd4,0xac,0x9a,0x16,0x7d,0x2a,0x64, + 0x59,0x29,0xd9,0xf2,0xaa,0xb8,0xe4,0x35,0x4e,0xb5,0x63,0xab,0x85,0x9b,0xc6,0x73, + 0x5b,0xde,0x22,0x99,0x6b,0xe3,0x59,0xbe,0xa6,0xbd,0x45,0x4a,0x9f,0x65,0x8e,0xbd, + 0xb1,0x2b,0xb9,0x69,0xbd,0x27,0x61,0x8b,0x41,0xd0,0x54,0x42,0x16,0x4c,0xfb,0x97, + 0x61,0xa4,0xb2,0xc7,0xc1,0xf6,0xec,0xbd,0x5e,0x97,0xda,0xca,0x5a,0xb,0xd8,0x88, + 0x2b,0xb4,0x1e,0x1f,0x73,0x16,0x5b,0x5a,0x78,0x9b,0xa3,0x44,0x57,0x52,0xe3,0x26, + 0x85,0x52,0xfa,0x95,0x29,0x7d,0xd9,0x26,0x5,0x6c,0x59,0x6c,0xd,0x0,0xf3,0x2f, + 0x6f,0xc4,0xae,0x6a,0x2e,0x6c,0x49,0x99,0xe9,0x1,0xc3,0x8b,0x1a,0xad,0xc0,0x9b, + 0x2,0x58,0x85,0xf9,0x4b,0x1e,0x49,0xc2,0x27,0x61,0x3b,0xf9,0xa4,0x25,0x54,0x4a, + 0x86,0xa3,0x1c,0xda,0x9c,0x8f,0xce,0xf1,0xf8,0x43,0xd7,0x9,0xb0,0xbe,0xae,0x92, + 0x7e,0x18,0x67,0x88,0xcc,0xc4,0xd3,0x5b,0xa3,0xeb,0xe4,0xba,0x6a,0x76,0x92,0x56, + 0xa4,0xf,0xc1,0xc1,0x69,0x44,0x69,0xf1,0xa1,0xc8,0x6e,0xf,0x47,0x8d,0xca,0x9a, + 0x6c,0x68,0x58,0x5e,0x90,0xac,0x7a,0xbd,0x11,0x37,0xb9,0x10,0x1b,0x17,0xe3,0x2f, + 0x27,0x28,0x2e,0x45,0xca,0x9b,0xab,0xc5,0x89,0xae,0xa9,0x52,0x2b,0x83,0xd4,0x71, + 0xe8,0xb1,0xff,0xe5,0xdf,0xfd,0x7f,0xde,0xab,0xaa,0x7e,0xe7,0x97,0x7f,0xf6,0x83, + 0x6a,0xd9,0xa1,0x7a,0x1d,0xc,0xd,0x8f,0x20,0xb5,0xa2,0xa2,0xdc,0xcf,0x9e,0xc4, + 0xfd,0x95,0x6f,0xa3,0x85,0x93,0xc1,0x96,0xad,0x41,0xd4,0xd4,0xda,0x58,0xd9,0xdb, + 0x83,0x5,0xb0,0x9,0xee,0x73,0x36,0xb3,0x43,0xf8,0x27,0xb9,0x6a,0x44,0x1f,0x7d, + 0x2c,0xf4,0xe1,0xd9,0xe2,0xde,0x9c,0xac,0x36,0xe6,0x1,0x8c,0x62,0xe,0x7c,0xd1, + 0xdf,0x65,0xcd,0xd2,0xae,0x67,0x6,0x55,0x4a,0x9a,0x5c,0xb,0x6,0x53,0x13,0x83, + 0x21,0xf7,0x10,0xff,0x69,0xe,0x92,0xa1,0x5d,0x2,0x7,0xa9,0x59,0x1f,0xa3,0x6a, + 0x4f,0x86,0x98,0x42,0x38,0x4b,0xe3,0xbd,0x42,0xea,0x90,0x6c,0x4d,0x7,0xd8,0x61, + 0x1e,0x89,0x5b,0x85,0x44,0x78,0x5c,0xdb,0x5e,0xcc,0x4a,0x53,0x63,0x74,0xa,0x38, + 0x64,0xde,0x74,0x71,0xcd,0x25,0x31,0xca,0xde,0x12,0x56,0x7,0x2c,0x3e,0x41,0xa4, + 0x8c,0x39,0x6a,0xc7,0x83,0xf8,0xd,0x18,0x14,0x47,0xca,0xbd,0x77,0xb3,0x4,0xa6, + 0x1f,0xfb,0x6a,0x2b,0xe8,0xa1,0x51,0x1,0x73,0x3e,0x41,0x53,0xe,0x48,0x39,0xbc, + 0x9e,0x83,0x6c,0x38,0xf7,0x84,0x30,0x8d,0xc6,0xd0,0x4d,0xdd,0x9d,0x7,0x62,0xe6, + 0xe0,0x7b,0xde,0x40,0xa9,0x9,0x3e,0x3e,0xac,0xfd,0x6e,0x88,0x85,0xa3,0xd1,0x95, + 0x4d,0x22,0xa8,0xdb,0x18,0x3a,0x82,0x61,0x13,0x32,0x88,0x14,0x4b,0x39,0x10,0x83, + 0x11,0x48,0xb6,0xf7,0xf4,0xa0,0x20,0x3b,0xc1,0x12,0xa6,0xd5,0xef,0x81,0x8d,0xb2, + 0x7f,0x34,0x79,0x48,0x1,0x9f,0x47,0x1e,0x15,0xad,0xc5,0x34,0x7,0xf3,0x89,0x6f, + 0xd1,0x44,0x58,0x30,0xec,0x6b,0x38,0xe4,0x5c,0xed,0x9d,0x73,0x51,0x4,0x23,0x9d, + 0xaa,0xf7,0x5,0xbb,0xcc,0xb1,0xc7,0x75,0xf,0xca,0xc3,0x3d,0x58,0xc4,0x44,0x7a, + 0xcc,0x0,0x7b,0xe2,0x94,0x1,0xb2,0xf7,0x67,0x39,0x34,0x34,0xb5,0xef,0x79,0x98, + 0x9f,0x4b,0x7b,0x85,0xc9,0x2f,0xa0,0x15,0x8f,0x74,0x67,0xc7,0x9c,0xde,0x60,0x75, + 0x2d,0x8,0x3d,0x43,0xe3,0xa8,0x5d,0x3c,0xa4,0x9,0xb6,0xb6,0x8c,0xf9,0x4b,0xec, + 0x85,0x9f,0x55,0xff,0xf3,0xaf,0x7c,0xef,0xe3,0x2f,0xfd,0xc3,0x1f,0xbe,0xeb,0x39, + 0x5c,0x36,0x1,0xc5,0xba,0x6e,0x68,0xdd,0x99,0x7f,0x21,0x81,0x4e,0x9c,0xb,0x56, + 0xde,0x8a,0x13,0x68,0x40,0xc1,0xc0,0x32,0xcd,0xc5,0x69,0xa2,0xf,0x32,0x96,0x16, + 0xc,0xa5,0xa4,0xed,0x1b,0xd3,0x11,0x30,0xab,0xc2,0x34,0xb7,0xaf,0xe1,0x0,0x46, + 0x40,0xee,0xee,0x9b,0x1d,0xac,0xed,0x55,0x3d,0xb0,0x93,0x46,0x6c,0xae,0x36,0x2c, + 0xf4,0x1a,0xc1,0x45,0xd1,0xef,0x7d,0x48,0x35,0x46,0x36,0x10,0x2a,0x5c,0x52,0xa5, + 0xc1,0xfb,0xed,0x8d,0x15,0x29,0x3e,0xd0,0xe6,0xbf,0x7e,0x7,0x24,0x13,0xbf,0x88, + 0xa4,0x64,0xb5,0x4c,0xcc,0xe6,0xb3,0xba,0x28,0x2,0x5c,0x6c,0x66,0xc3,0x5a,0x52, + 0x69,0x71,0x5b,0x76,0x42,0xa0,0x77,0xc2,0x33,0x42,0x85,0xed,0xdd,0x98,0x86,0x1, + 0x8a,0xd3,0x8,0x8c,0x7a,0xaf,0xd5,0x8,0x6,0x3a,0xf7,0x3d,0x55,0xed,0x2a,0x16, + 0x2,0x65,0x74,0x3b,0x11,0x6,0x49,0x18,0x97,0x9,0x1,0x37,0xfe,0x42,0x8c,0x9c, + 0x5e,0x5b,0xab,0x3c,0xe0,0xf2,0x2a,0x31,0xf4,0xd1,0x14,0x6d,0xcd,0x8b,0x5f,0xe, + 0x75,0x86,0x4c,0xa7,0x55,0xf0,0x6d,0x9f,0x65,0x17,0x5,0xc1,0xca,0x85,0x23,0x24, + 0xb5,0x65,0x29,0x73,0x14,0xb7,0xd0,0x7b,0x6b,0xe5,0x64,0xf0,0x2e,0x96,0x52,0x18, + 0x28,0x26,0x30,0xef,0xf2,0x13,0xdb,0xbe,0xcf,0x58,0x27,0x63,0xcc,0x39,0x34,0x93, + 0xbc,0x73,0xff,0xb5,0x9b,0x50,0x6b,0x53,0x23,0xe6,0xfa,0xb6,0xfd,0x12,0xcb,0x8c, + 0x9d,0x36,0xb1,0x15,0x27,0xc2,0x21,0xd1,0x59,0xf7,0xb6,0x86,0xb7,0xd6,0xc4,0xe2, + 0xe6,0xc0,0xf5,0xbf,0xdd,0xe0,0xa3,0xb3,0xb2,0xbd,0x65,0x34,0x88,0x64,0xc1,0x67, + 0xfb,0xd1,0x88,0x90,0x18,0x61,0xe4,0x66,0x75,0x8a,0x81,0x99,0xd6,0xe6,0xfc,0xa7, + 0x96,0xa3,0x57,0x7f,0x36,0xb,0x3d,0xc4,0x51,0x30,0x9,0x81,0x38,0x60,0xcc,0x27, + 0x93,0x9d,0x2b,0xdc,0xe9,0x4,0x5e,0x17,0xbd,0xa,0x85,0xdb,0x5f,0xa,0x95,0xd1, + 0xf5,0x27,0xfa,0xad,0xc0,0xb,0x24,0xb8,0xfa,0xd4,0xc,0x72,0x7d,0xc8,0x7a,0xa, + 0xf6,0xb4,0xe,0x68,0xe4,0x19,0x51,0x7,0xe,0xac,0x9e,0xbd,0xd6,0x43,0x4f,0x2, + 0xa0,0x92,0x5b,0xaf,0x8e,0xac,0x28,0x39,0x77,0xfc,0x5e,0x54,0xbd,0x4d,0xe6,0x12, + 0xa4,0x13,0xdc,0x4c,0xe0,0x2f,0xe6,0x4b,0xd5,0x31,0x48,0x7b,0x67,0xa,0x7b,0x70, + 0xa8,0xae,0x17,0x7a,0xf8,0x54,0x2d,0x54,0x88,0x2e,0x34,0xb2,0xdb,0x48,0xc8,0xae, + 0x64,0x38,0x12,0x63,0xb6,0xd1,0x2,0x3,0x1a,0x2e,0xba,0x25,0x24,0x38,0x41,0xeb, + 0x5a,0xfd,0xb0,0x59,0x5,0x9a,0xb6,0xb0,0x55,0x4,0x94,0x91,0x3a,0x38,0x4f,0x8d, + 0xe,0xc9,0x72,0xc8,0x18,0x31,0x58,0xb1,0xa4,0x5,0xa8,0x39,0xc3,0x25,0xe9,0x2f, + 0x46,0x85,0x9e,0x1e,0x3a,0xb1,0xfb,0xe9,0xda,0xfb,0x1,0x83,0xc1,0xaa,0x15,0x7a, + 0x3,0xf1,0x3c,0xfb,0xcc,0x9a,0xbd,0x84,0x38,0xc9,0x48,0xaa,0x1e,0x95,0x23,0x4c, + 0x91,0x6,0x53,0xcd,0x8,0xab,0x64,0x13,0xe2,0x45,0xf3,0xaf,0x94,0xfe,0x6a,0x94, + 0x99,0xee,0xe7,0xe6,0xa4,0x4f,0xa4,0xdc,0xe4,0x9a,0xff,0x1d,0x2a,0x9f,0x6b,0xb0, + 0xec,0xbc,0xc4,0xe5,0x4a,0xdc,0xce,0xc,0xa8,0x22,0x7,0x60,0x4b,0x2d,0x56,0x39, + 0x42,0x8a,0x39,0xed,0xae,0xd5,0xd7,0x42,0x32,0x10,0x55,0x13,0x4e,0xf3,0xe6,0x94, + 0x3d,0x24,0xa3,0x2c,0xee,0xe2,0x20,0x4,0xaa,0x3a,0xd0,0xad,0xd9,0xd9,0x0,0xb1, + 0x47,0x4d,0xca,0xb2,0x86,0x8a,0x2f,0xda,0x8,0xd1,0x3,0x8,0x94,0x30,0xd,0x63, + 0x30,0x76,0x4d,0x91,0xf6,0xc2,0x89,0x8f,0x8e,0x56,0xa5,0xf3,0x21,0x9f,0x45,0x81, + 0xd9,0x4e,0x3e,0x8e,0xb1,0xcd,0xd6,0xb7,0xda,0x58,0x9d,0xb9,0xac,0x64,0xb,0xb2, + 0x11,0x71,0x9b,0x70,0xc0,0xb7,0xf5,0x1b,0x52,0x90,0x85,0xe9,0x31,0x94,0xd6,0x1d, + 0xb9,0xf6,0x27,0xcb,0xed,0x59,0xb6,0xc,0x60,0xac,0xbe,0xbe,0x1e,0x68,0x9d,0xf4, + 0xa9,0xec,0xd7,0x62,0xb3,0x41,0x21,0x5b,0x12,0xba,0xa1,0xf9,0xa8,0x6c,0xa4,0xa1, + 0x41,0x26,0x2e,0x1d,0xeb,0xed,0xc3,0xee,0x9f,0xfc,0xac,0xf1,0xf4,0x30,0x29,0xf2, + 0xee,0xe,0x7e,0xfd,0xaa,0x5f,0xf9,0x9d,0x1f,0xbc,0xff,0x83,0xbf,0xf8,0xbd,0x8f, + 0x9,0x13,0x35,0xcd,0xe,0x6d,0xe0,0x3d,0x5a,0xed,0xf7,0xa5,0xfd,0xca,0xef,0xfc, + 0xf0,0xfe,0xc,0xd4,0x3f,0xf8,0x4b,0xdf,0xfb,0x40,0xca,0x6c,0xaf,0xa4,0x54,0x3e, + 0x27,0x4d,0xc4,0x42,0xb9,0x54,0x5b,0x58,0xea,0x3e,0xca,0x52,0xa5,0xb8,0x1,0xe2, + 0xdc,0x6d,0xed,0xd,0x57,0x13,0xd5,0x33,0x65,0x71,0x61,0x2,0xba,0x84,0x5e,0x9b, + 0x88,0x51,0x32,0xa1,0x92,0x57,0x10,0xba,0x5,0x91,0x99,0x27,0x41,0x9,0xd5,0x6, + 0x8f,0x5a,0xff,0xb9,0x8f,0xa1,0x86,0x2f,0xb9,0x4a,0x7b,0x8e,0xa2,0x0,0x5a,0x21, + 0xe5,0xcc,0x34,0xe6,0xd,0xa6,0x6,0x5,0xc9,0x2b,0x43,0x2d,0x5,0x29,0xcd,0xe2, + 0x39,0xe0,0x96,0x48,0xa2,0x44,0x4d,0x99,0x7b,0x6f,0x83,0x30,0xe5,0x40,0xab,0xf7, + 0xd0,0x11,0x73,0xcf,0xb0,0x19,0x75,0x95,0x13,0x74,0x49,0x59,0x4e,0xbd,0xff,0x46, + 0x91,0x44,0xb,0x48,0xe0,0x44,0x42,0x8b,0xdf,0x86,0xe1,0x90,0x56,0x6d,0xf2,0x21, + 0xa9,0xe8,0x82,0x7,0x49,0xaa,0x73,0xe5,0xc2,0xe4,0x2a,0xea,0x88,0x11,0x86,0x91, + 0x97,0xa1,0xc4,0x15,0x98,0x7f,0xe9,0x4,0x8b,0x98,0x4d,0x54,0x87,0xd3,0x68,0x16, + 0x1f,0xf4,0x65,0x20,0xe3,0xe1,0x90,0xe6,0xcb,0x6f,0xb9,0x4c,0xa2,0x39,0x9f,0x3f, + 0x3c,0xd3,0x1d,0x49,0x37,0x15,0xa4,0xc7,0x6b,0xb0,0x99,0xad,0x2e,0xac,0x15,0xd5, + 0xe6,0x74,0x9b,0x80,0xd9,0x37,0xbc,0xad,0x6a,0x31,0xcb,0x40,0x6b,0x81,0x75,0xc4, + 0x6e,0x1a,0x4d,0xec,0xb3,0xd0,0xb9,0x6,0x86,0xf5,0x61,0x85,0x19,0x6,0x49,0xd3, + 0x90,0x10,0xc5,0x30,0xf6,0x16,0xbf,0xd7,0x66,0xe0,0xa1,0x4e,0x72,0x15,0x92,0xac, + 0x7e,0xff,0x56,0xea,0xd5,0xa4,0x51,0x5d,0xd2,0x3a,0xd5,0xdd,0x50,0x9d,0x64,0x48, + 0x60,0x46,0x47,0x67,0x1a,0x5a,0xff,0x1c,0x3b,0xfb,0x65,0x3f,0xeb,0xb3,0x46,0x22, + 0x61,0x8f,0xe0,0x98,0x90,0xce,0x82,0x4c,0xac,0x44,0x63,0xb5,0x6b,0x36,0x1d,0x8, + 0xe8,0x1c,0x79,0x90,0xd7,0x42,0xab,0x7f,0xfb,0x2b,0x28,0x77,0x4,0xad,0xb2,0x27, + 0x2b,0x24,0x54,0xb5,0x35,0x87,0x4e,0xbd,0xa,0x5d,0x3,0xa,0x3f,0x2,0xe5,0xc8, + 0x60,0xe1,0xda,0xe7,0xa8,0xfe,0x1d,0x3c,0x18,0xaf,0xcf,0x50,0xcf,0x82,0xfb,0x7b, + 0xff,0xe1,0x5f,0xf9,0x53,0x1f,0xbf,0xf2,0xdb,0x3f,0x78,0x57,0x2b,0xd6,0x2a,0x27, + 0x0,0x22,0xc6,0x99,0xb,0x1d,0x95,0x85,0x3c,0x7f,0x0,0x75,0x51,0xe1,0x90,0x80, + 0x71,0x77,0x26,0x77,0x55,0x3f,0x2e,0x31,0x6f,0xe6,0x60,0xec,0x62,0xb2,0xd0,0xc3, + 0xd4,0x5f,0xba,0x5f,0x7b,0x45,0xff,0x5b,0x59,0x9e,0x31,0xbb,0xcd,0xaa,0x79,0x26, + 0x6f,0xe8,0xf7,0x79,0x20,0xc2,0x6c,0xe4,0x66,0x7,0xb1,0x9f,0x48,0xc,0xe8,0xcf, + 0x32,0x50,0x71,0xca,0xda,0xfb,0x9a,0x7d,0x13,0xa1,0x33,0xc1,0xdd,0xb0,0x60,0x57, + 0xe3,0xc,0x85,0xae,0xc2,0xf0,0xcf,0x40,0x8c,0x4e,0x5,0x7c,0xf8,0x29,0xaf,0x93, + 0xf9,0x47,0x85,0xe7,0x15,0x52,0xda,0x7d,0x77,0x76,0x3f,0x6c,0xc,0xbc,0xef,0x26, + 0x75,0x3a,0xb0,0xa6,0xc7,0x49,0x83,0x43,0xf3,0x35,0x45,0x38,0x2,0x93,0x6,0x26, + 0x98,0xed,0x0,0x23,0x4e,0xee,0x56,0x38,0x54,0x80,0x3c,0x9f,0xd9,0x3e,0x2f,0x5d, + 0xd5,0xa7,0x1d,0x34,0x5b,0xbb,0xfa,0xf9,0xa9,0x68,0x1,0x53,0x2e,0x37,0x6c,0x1b, + 0x6d,0xfd,0x4e,0xd2,0x98,0x87,0xfb,0x86,0xc3,0x99,0x3d,0xb4,0xd1,0xd8,0x48,0x9a, + 0xd5,0x9c,0xf1,0x74,0x6a,0x0,0x56,0x40,0x87,0x1f,0xb3,0x48,0x21,0x2b,0xd9,0xca, + 0x5c,0xdb,0xe2,0xc6,0x52,0x61,0x75,0x25,0x20,0x42,0x35,0x25,0x74,0x3c,0xca,0x93, + 0xa4,0xc9,0xc1,0xee,0x99,0xd5,0xe1,0x2a,0x5f,0xe8,0x5a,0xe6,0xe8,0xf3,0x11,0x26, + 0xa5,0x6b,0x57,0xcf,0xd1,0x76,0xb6,0x94,0xb,0x61,0xe2,0x2b,0xe,0xa5,0xab,0xb5, + 0x27,0xcd,0xc1,0x8b,0x7e,0x46,0xaa,0x9e,0x7e,0x6b,0x53,0x38,0xbb,0xbc,0x31,0xa5, + 0x63,0x20,0x84,0xd9,0xf5,0xc8,0x75,0x94,0xfe,0x19,0x70,0x76,0xb6,0xe7,0x94,0xe8, + 0xf9,0xf5,0x30,0x3e,0xab,0xcc,0x77,0x6d,0xbf,0xad,0xb6,0x68,0xb8,0xa8,0x6d,0xf4, + 0x17,0xc1,0x5,0x91,0x62,0x63,0x98,0x3c,0x50,0xee,0xb,0x1f,0x2d,0x93,0x74,0x2b, + 0x46,0x4f,0xc0,0x0,0xe9,0xed,0x27,0x83,0x18,0xd5,0x7d,0x32,0x52,0xfb,0xe3,0x3e, + 0xb,0x29,0xfc,0x95,0xe7,0x79,0x81,0xdc,0x8a,0x6f,0x48,0xf,0x88,0xfd,0xac,0xfe, + 0xcb,0xdf,0xfa,0xc1,0xfb,0xef,0xfe,0xea,0xcf,0x7d,0xe4,0xa4,0xd2,0x2a,0x53,0x3e, + 0x7b,0x8b,0xa0,0x4b,0x33,0xd7,0x1,0xb5,0xe8,0x32,0xc9,0xac,0xaa,0x37,0x14,0x1b, + 0x21,0xdd,0x4c,0x26,0x20,0xda,0x35,0x74,0x72,0x89,0xcd,0x28,0xee,0x74,0x64,0xc1, + 0xb9,0x66,0x50,0x30,0xb1,0xd5,0x19,0xce,0x50,0x46,0x52,0xaa,0x18,0xc,0x77,0x57, + 0x2f,0x23,0x3f,0xc,0xd0,0x60,0x15,0xea,0x97,0x7f,0xeb,0x87,0xef,0x55,0x55,0xff, + 0xeb,0xaf,0xfd,0xec,0x47,0x25,0xe4,0x68,0xce,0x18,0x4c,0xd9,0x39,0xf7,0x44,0x3f, + 0x42,0xdb,0x83,0x21,0xfc,0x84,0x81,0x9d,0x54,0xb5,0x54,0x28,0x80,0xd9,0xd3,0xb, + 0x28,0x32,0x74,0x7d,0x99,0xf6,0xa4,0x4a,0x70,0xab,0xaa,0x5f,0xfe,0xad,0x1f,0xbe, + 0xff,0xee,0xaf,0x7d,0xef,0xe3,0xf9,0xaa,0xdf,0xfd,0xb5,0xef,0x7d,0xfc,0xf2,0x6f, + 0xfe,0xf0,0x9d,0x86,0xdb,0x94,0xf7,0x38,0xa9,0xf3,0x9b,0xe1,0xd5,0x9e,0xb0,0x64, + 0xcc,0xaf,0xaf,0xcf,0x1c,0x50,0x43,0x75,0x6e,0x53,0xe2,0xdb,0x62,0xfc,0xd3,0xa1, + 0xb9,0x33,0xd9,0x90,0x35,0x5a,0xd3,0xcd,0x74,0xdb,0x9a,0xdd,0xe9,0xd4,0xd,0x8a, + 0x51,0xf1,0x9f,0xdc,0x4,0x2b,0x9d,0x87,0xcf,0xa8,0x6d,0xe5,0x38,0x98,0x48,0x27, + 0xc3,0xc9,0x7d,0x6b,0x8d,0x5f,0xfb,0x3e,0xb8,0x65,0xa7,0x3a,0xc7,0x9,0x24,0x27, + 0xd0,0x21,0x6d,0x8e,0xdf,0x95,0xc1,0x1a,0x98,0xbf,0x5c,0xb4,0xca,0xe6,0xa4,0x4b, + 0x89,0xab,0xcf,0xcc,0xb2,0x7d,0xf6,0x46,0x20,0xb6,0x34,0x33,0x4,0x51,0xe6,0x7d, + 0xd8,0x26,0x4b,0x99,0xd1,0x1b,0xf7,0xb6,0x9a,0xa2,0xd2,0xce,0x67,0xd0,0x35,0xde, + 0x45,0x94,0x18,0x1e,0xdf,0x4e,0xaa,0x45,0x20,0xeb,0x49,0x2,0xf3,0x9e,0xfb,0xd7, + 0x1e,0xbf,0x76,0x42,0xc0,0xde,0x15,0x40,0xd2,0xba,0xad,0xa5,0x24,0x73,0xc4,0xaa, + 0xf2,0xa8,0xce,0x65,0xc3,0xec,0xfe,0x38,0xeb,0x74,0xff,0xc1,0x5f,0xf8,0x7b,0x3f, + 0x78,0xaf,0xaa,0xfa,0x47,0xbf,0xfe,0x73,0x1f,0x2c,0xda,0x39,0x78,0x9c,0xb5,0xe, + 0x7f,0xf9,0x2f,0xa5,0x48,0xf3,0xa1,0x2b,0x93,0x66,0x35,0xb7,0x45,0x87,0xbd,0x51, + 0xee,0xb4,0xa8,0x2d,0xb0,0x74,0x80,0xdb,0xae,0x74,0xb0,0xb5,0xc8,0x9,0xc1,0x79, + 0xae,0xab,0x64,0x2,0xa5,0x37,0x19,0x5b,0x46,0xac,0xa2,0x2b,0x36,0xb5,0x61,0x73, + 0xfa,0x9,0x7f,0x6b,0xde,0x4d,0x91,0x35,0x77,0x26,0x3a,0x12,0xf1,0xd3,0x64,0x84, + 0xd5,0x39,0x20,0xb5,0xf9,0xaf,0x7b,0x72,0x86,0xa3,0x21,0x38,0xb3,0x7b,0x47,0xfa, + 0xc,0xff,0xd2,0x6b,0x1d,0x98,0xfd,0x1a,0xf3,0x0,0x6b,0x2b,0xd4,0xa9,0x55,0xcc, + 0x12,0xb7,0x35,0x4,0x44,0x28,0xa3,0x2b,0x3b,0xcd,0x42,0x8c,0xd1,0xc,0xbd,0xaf, + 0xf4,0x71,0x56,0x58,0xd7,0x1d,0x46,0x5c,0x32,0x31,0x58,0x6d,0xb6,0x70,0x78,0x90, + 0x58,0x2c,0xcc,0x5e,0xd6,0x32,0x87,0xed,0x4a,0x3f,0xfe,0x1e,0x8c,0xa6,0x33,0x72, + 0x2d,0xda,0x5f,0x18,0x2d,0x59,0x7,0xf7,0xb7,0x74,0xc1,0x69,0x66,0xc6,0x87,0x8a, + 0x31,0xe2,0x99,0xb,0xb4,0x48,0x0,0x9e,0xde,0x97,0xac,0x28,0x51,0x89,0xd3,0x79, + 0xe6,0x75,0x3f,0x4e,0x4c,0xf9,0xdb,0xd0,0x65,0xd6,0x96,0x19,0xd4,0xf8,0x1e,0xa5, + 0xa9,0x2b,0x4c,0x14,0x52,0x89,0x2b,0x3,0x6c,0x5a,0xc,0x5d,0x8a,0xd1,0x4c,0x33, + 0xdb,0xc,0xe,0x43,0x2e,0x17,0x47,0x47,0x12,0x82,0x87,0x40,0x98,0x5d,0x31,0x5a, + 0x5a,0x3,0x70,0xfb,0x1b,0x5f,0x4e,0xb1,0x4e,0x80,0x80,0xd,0xb7,0xdf,0x1,0xd0, + 0xe7,0xd6,0x31,0xea,0xc0,0xc6,0x64,0x3a,0x60,0xc0,0x6,0x27,0x29,0xd8,0x27,0x6f, + 0xa2,0x13,0xe8,0x94,0x18,0x9a,0x5b,0x96,0x49,0x1e,0xdc,0x8c,0x83,0x7a,0x64,0x5f, + 0x41,0x45,0x7d,0x36,0x2b,0x1f,0xc6,0x69,0xb9,0xc2,0x8c,0x46,0xaa,0x14,0x66,0xeb, + 0x4d,0xaf,0xfd,0x6a,0xce,0x72,0xa5,0x7a,0xef,0x43,0xcf,0xbe,0xdb,0x5a,0xde,0x33, + 0xde,0xc,0x27,0x38,0x15,0x84,0x19,0x98,0x8,0x6d,0xd2,0xc0,0x66,0x92,0x93,0xbf, + 0x21,0xe,0x6f,0x26,0xe,0xc2,0x68,0x19,0x21,0x8c,0x43,0x3b,0xe2,0xc2,0x3,0x6a, + 0xb6,0x9e,0x33,0x52,0x66,0x78,0xde,0xa7,0x50,0x2d,0x86,0x38,0x44,0x1,0x15,0x36, + 0x61,0x79,0x5a,0x9a,0xa4,0x3b,0x1d,0x69,0x43,0xc0,0xea,0x58,0xea,0xbf,0x49,0xa8, + 0x6b,0x8c,0xc,0x74,0xeb,0x6b,0x84,0x4b,0x61,0xde,0x53,0x86,0x16,0xc1,0x42,0x33, + 0x1f,0x5b,0xe6,0x36,0xfd,0x70,0x68,0x6b,0x26,0x30,0xa5,0xc8,0xe,0x9a,0x6a,0xc8, + 0xf9,0xec,0xa,0x74,0x51,0x35,0x50,0x4c,0xa6,0xe4,0xf3,0xd0,0xaa,0x1,0xea,0x1f, + 0xfd,0xfa,0xcf,0x7d,0xfc,0x85,0xef,0xff,0xdf,0xef,0x65,0xc4,0x55,0x3d,0xea,0xaf, + 0x8d,0x8a,0xb2,0x44,0x23,0x45,0x4e,0xde,0xcf,0xea,0x42,0x56,0x72,0x2c,0x5b,0xd7, + 0x31,0xb4,0x51,0x3a,0x2,0xf7,0x48,0xbf,0xca,0xa6,0xee,0xf7,0xe0,0xab,0x5f,0x70, + 0x50,0x94,0xf1,0x3,0xfc,0xe0,0xc8,0x86,0xa8,0x8b,0x9a,0xdc,0x6b,0xf6,0x25,0x27, + 0x17,0xa0,0xb5,0xa0,0xe9,0xfd,0x32,0xcd,0x7e,0xb3,0xf,0x13,0x46,0xf2,0x1c,0x18, + 0x8d,0x6c,0xce,0xd2,0x7,0xf2,0x8e,0x9,0x2e,0xe8,0xd0,0xbf,0x3b,0xf3,0x20,0x12, + 0x11,0x48,0x75,0x6a,0xe2,0x31,0xcd,0xe6,0x93,0x2b,0x40,0xa2,0x20,0x22,0x1e,0x68, + 0x26,0x8a,0x36,0x21,0x32,0x8,0x6e,0x2c,0x31,0x88,0x38,0x3d,0x29,0x2c,0x4b,0x64, + 0x62,0xf3,0x5c,0xf,0xab,0xfe,0xb7,0xff,0xe6,0x4f,0x7d,0xfc,0xd2,0xf7,0xbf,0x90, + 0xd,0xef,0x8b,0x75,0x34,0xfd,0x97,0xfe,0xa7,0x1f,0xbc,0xff,0xd2,0xf7,0x7f,0xf0, + 0xae,0x28,0xc,0xd5,0x5e,0x53,0x19,0xd9,0xed,0xa0,0x73,0x21,0x12,0x19,0x38,0x68, + 0xd4,0x2b,0xd,0x9e,0x96,0x60,0x57,0x2a,0x90,0x21,0xd4,0xa0,0x9c,0x7b,0xf5,0x30, + 0xf8,0x15,0x46,0x27,0x36,0x22,0xb1,0xd8,0xf6,0xf1,0xf7,0x64,0xd5,0x8,0x6,0x99, + 0x1f,0xb5,0xa4,0x7,0xa,0x58,0xa8,0x61,0x89,0xe8,0x2e,0x9b,0x95,0x68,0x70,0x14, + 0xd6,0xff,0x12,0x21,0x9b,0x1b,0x86,0x7,0xd9,0x62,0x49,0xbb,0x4d,0x73,0xa4,0xa3, + 0x8b,0x6c,0xb4,0xce,0x46,0x84,0x38,0x49,0xec,0x9,0xf5,0x7b,0x97,0x35,0x6a,0xa6, + 0x39,0x30,0x8,0x39,0xb8,0x64,0x8d,0x59,0x91,0xbd,0x5e,0x84,0x27,0x3a,0xac,0x65, + 0xc7,0x95,0xd4,0x21,0xa4,0x47,0x77,0xd5,0x49,0x53,0x13,0xe8,0x2,0x53,0x68,0xf4, + 0x2a,0xaf,0x43,0x50,0xae,0x12,0xee,0x8a,0xe1,0xaa,0x72,0x46,0xa9,0x96,0x47,0x38, + 0x54,0x7b,0xeb,0x15,0x3c,0x14,0x95,0x24,0x7d,0xce,0x29,0x9b,0x12,0x71,0x36,0xb4, + 0xf5,0xdb,0x5f,0x58,0x5a,0xa3,0xc9,0x4f,0x57,0x13,0x3d,0xc2,0x70,0x8e,0x23,0x8d, + 0xd9,0x30,0x7b,0x2b,0x70,0xe2,0x26,0x60,0x18,0xd5,0x38,0x2a,0xed,0xe,0x37,0xc, + 0x10,0xc4,0x28,0xe,0x86,0x10,0xe6,0x79,0x61,0xac,0x10,0x88,0xc7,0xac,0x80,0xd6, + 0xb9,0x3a,0x8a,0x7e,0x6,0xe2,0xf8,0xec,0x4d,0xe,0xb1,0x4a,0x93,0x1d,0xd6,0x90, + 0x88,0x8,0x4a,0x71,0xbf,0xff,0xa,0x7b,0x60,0x63,0xca,0xb3,0xc6,0xe2,0xb7,0x1e, + 0xae,0x8c,0x7d,0xbf,0xdb,0x33,0x82,0x95,0x3d,0xb1,0x7a,0xeb,0xe6,0xf4,0x51,0x8c, + 0xb2,0x2,0xbe,0x4c,0xe1,0xc,0x8c,0xf8,0xd1,0x23,0x92,0x41,0x69,0x96,0x2c,0xe6, + 0xb7,0x42,0x98,0x12,0x94,0x18,0xb8,0xa5,0x7b,0x17,0xf8,0xec,0x23,0x15,0x26,0xa2, + 0x2,0x37,0x1b,0x96,0xf4,0x6a,0x34,0xc8,0x58,0x52,0x51,0xa8,0xf0,0x4a,0x6b,0x34, + 0x55,0xb5,0xc3,0xc6,0x21,0xaf,0x7d,0xa3,0xa9,0x12,0x8b,0xa6,0xc3,0x3,0x53,0x76, + 0x55,0xe2,0x85,0x32,0x32,0x53,0xb5,0x8f,0x1a,0x98,0x5,0x4e,0x57,0x49,0x43,0x86, + 0x45,0xa9,0x2a,0xbe,0x3d,0x87,0xd4,0x9a,0x69,0xff,0x9c,0x2b,0x73,0x6,0x59,0x70, + 0x3b,0xb3,0xc1,0x46,0x29,0xc8,0x12,0xd8,0x58,0x18,0xf3,0x70,0x3f,0x8a,0x84,0xbf, + 0x29,0xd5,0xa7,0xb9,0x92,0xb1,0x9a,0x20,0x8c,0xeb,0xec,0xf,0xda,0x56,0x51,0x41, + 0xb5,0x75,0xa9,0xb0,0xf6,0x23,0x70,0x81,0xa4,0xc,0xf,0xfe,0x22,0x39,0x73,0x5c, + 0x89,0x88,0xd0,0x92,0x23,0xe5,0x74,0x2c,0x38,0x32,0x5,0x40,0xf2,0x40,0x61,0x99, + 0x68,0x7,0x2f,0xc6,0xba,0x40,0xb7,0xe,0xb6,0xde,0xa0,0xf,0xe1,0x22,0x7b,0x99, + 0x6,0xe5,0x57,0x83,0xf2,0x28,0xb0,0xa5,0x33,0xb3,0xe1,0xd5,0x6e,0x85,0x9c,0x33, + 0x85,0x49,0x7b,0xc3,0xf6,0x8f,0x84,0xa9,0x2a,0xb0,0x51,0xb4,0xa8,0xd,0xe1,0xeb, + 0xc0,0xaf,0x11,0x37,0xc7,0x31,0x3d,0xd5,0xae,0x62,0xaf,0x32,0x31,0x8,0x55,0x24, + 0x51,0x9c,0x3,0x81,0xde,0x94,0xc2,0xe8,0xf2,0xa6,0x4,0x44,0xc9,0x2d,0x25,0x9a, + 0xf5,0x1e,0x5c,0xa6,0xd3,0x61,0x46,0x69,0xac,0xed,0x86,0xa5,0x2,0x39,0x46,0xcb, + 0x9,0x91,0x94,0xf5,0xbe,0x72,0xee,0x4b,0x25,0x8b,0x9e,0xcd,0x41,0x2f,0xe7,0x53, + 0x9b,0x3,0x60,0x2e,0x46,0xc8,0x29,0x3f,0xb5,0xcc,0x62,0x32,0xc7,0xa6,0x98,0x82, + 0xdd,0xce,0x75,0xf3,0x38,0x4,0xd2,0x13,0xb3,0x32,0xc8,0x25,0xa0,0x25,0x9c,0xd4, + 0xd6,0xe2,0x3,0x67,0xe3,0x5b,0xbe,0xac,0xce,0x64,0x87,0xb2,0xe6,0x81,0x93,0xc9, + 0x66,0xfd,0xf9,0xff,0xf1,0xab,0xc2,0xfe,0xc7,0x7f,0xf5,0xe7,0x3f,0x5a,0x66,0x90, + 0xfe,0x17,0x43,0x96,0xa0,0xd6,0xaa,0x36,0xca,0x9,0x34,0xcf,0xc,0xad,0xe4,0x4b, + 0x98,0xf2,0xa7,0x79,0x7b,0x8c,0xa4,0x46,0x34,0xe8,0xdf,0x7,0x2b,0x58,0x6f,0x18, + 0x9c,0xf1,0xc0,0xe8,0x1,0x84,0xc5,0xa9,0x9,0x5d,0xb0,0x4c,0xad,0xc7,0xb4,0x7, + 0xe8,0xd9,0x68,0x99,0xf0,0x96,0x18,0xa8,0x84,0x8c,0x60,0x5b,0xb3,0xd2,0x47,0x30, + 0x7b,0x4f,0x6a,0x1f,0xac,0x44,0x79,0xea,0xeb,0x35,0x9f,0x94,0x3e,0x31,0x59,0xbf, + 0x78,0x3f,0xc0,0x7f,0xf2,0x57,0x7f,0xfe,0x83,0xa2,0xf5,0xcd,0x74,0x55,0xa3,0x67, + 0x96,0x76,0xd0,0x5b,0x9b,0x75,0x43,0x8a,0x5f,0xbd,0xb4,0x2d,0xc,0xa0,0xea,0xf7, + 0x10,0xb8,0x5c,0x6d,0x40,0x2b,0xc7,0xa6,0xa6,0x2d,0x80,0x6e,0x2,0xd2,0xa8,0x8, + 0xf7,0x75,0xfc,0x17,0xff,0xc3,0xff,0x75,0xff,0xbe,0x9f,0xfb,0xf8,0xa4,0x8f,0x3c, + 0x15,0x6b,0xdd,0x8f,0xf4,0xd1,0x65,0x8c,0x8e,0x7d,0x92,0x26,0x51,0x91,0x70,0xda, + 0xf3,0xea,0x4f,0x23,0xf7,0xc5,0xf8,0x46,0xcc,0x4d,0x33,0x75,0xa9,0x23,0x73,0x5f, + 0x9,0xdb,0x55,0x6d,0x3c,0x6c,0xe1,0x28,0x88,0xd1,0xaa,0x3a,0xb5,0x68,0x6a,0x56, + 0xad,0xab,0xc9,0xd6,0xd6,0xeb,0xb2,0xb6,0x61,0xa8,0x42,0x3b,0x33,0x17,0xad,0x4d, + 0x3b,0xb0,0x83,0xb9,0xa4,0xeb,0x58,0x53,0x2,0xa,0x6,0xd2,0x11,0x2a,0xe0,0xfa, + 0x8c,0x4e,0xc0,0x30,0xd2,0x59,0x32,0x5f,0xaf,0xc1,0x52,0xf,0xc8,0x83,0xe3,0x97, + 0x8a,0xa6,0x54,0x88,0xec,0xac,0xc4,0x97,0xe1,0x8e,0xa7,0xa4,0x4a,0xb1,0x19,0x65, + 0x3f,0xb8,0x61,0xe2,0x47,0xfb,0x69,0xe8,0xde,0x6d,0x2c,0x7c,0x72,0xbf,0x76,0x84, + 0x26,0x65,0xc0,0x37,0x85,0x3d,0xa8,0x3a,0xdd,0x14,0x3f,0x77,0x49,0x61,0x24,0xe1, + 0xcd,0x76,0x96,0xc6,0x8d,0xab,0xca,0xfa,0xc3,0x18,0x26,0x20,0xb6,0x8d,0x2f,0x1b, + 0x57,0x23,0x35,0xfc,0xd5,0xab,0x59,0xad,0x9b,0x75,0xff,0xe5,0xe4,0x4a,0x23,0x32, + 0x56,0xca,0xf0,0xed,0xa2,0xc9,0x77,0xdc,0xc1,0x98,0x7c,0xac,0xfa,0x6a,0x8f,0xa8, + 0x61,0xab,0x1b,0xf6,0xe9,0x7,0xd9,0xdb,0x57,0x67,0x69,0x67,0x1,0xd5,0x68,0x15, + 0xd9,0xa,0xe1,0xde,0x5f,0x48,0x45,0xcc,0xcb,0x51,0xaf,0xd3,0x4c,0x7a,0xe6,0x21, + 0x7e,0x76,0x34,0x7a,0x95,0x9d,0x87,0xde,0x18,0xdc,0xbf,0xed,0x93,0x74,0x1e,0xb, + 0x5d,0x85,0xf2,0x93,0xfd,0xde,0x3e,0x9a,0xfd,0x4,0xef,0xf7,0xbb,0x1d,0xb5,0x26, + 0xf0,0x9f,0x71,0xa0,0xa0,0xe2,0xfe,0xea,0x1e,0x62,0xca,0x11,0x85,0xb6,0xee,0x8d, + 0xe6,0xbd,0xad,0x3a,0x88,0x3e,0x72,0xe1,0xe2,0x1a,0x3a,0xf6,0xa4,0xb3,0xae,0x65, + 0xb2,0xb0,0x5b,0x16,0x91,0x21,0xea,0xe3,0xe4,0x1e,0xc2,0x15,0x8d,0xbe,0x8,0x6, + 0xc,0xc5,0x57,0x27,0x65,0x35,0x52,0x1a,0x73,0xe6,0x96,0x1,0x31,0xd1,0x67,0xae, + 0x55,0x7f,0x97,0xb9,0x3e,0x3d,0x0,0x69,0x75,0xa8,0x20,0x66,0xfa,0xa,0xef,0xd, + 0xe1,0x81,0x2c,0xab,0x34,0xd2,0x49,0x1c,0x4,0x26,0x3c,0x43,0xe6,0xfb,0xbb,0xac, + 0x2d,0x43,0x3c,0x67,0x22,0x92,0x25,0xab,0x9d,0xe1,0x78,0xb6,0xef,0x47,0xc0,0x72, + 0x74,0xe3,0x83,0xa7,0x42,0x7f,0xbe,0xff,0x17,0xff,0xd6,0x9d,0x28,0xfc,0xc6,0xcf, + 0x7f,0x0,0x43,0x25,0xa1,0x23,0x58,0x2a,0xfb,0x59,0x5d,0x93,0x3c,0x3b,0x6c,0x79, + 0xd,0x49,0x60,0xda,0xe7,0xfb,0xe5,0x38,0x64,0x1c,0x10,0x34,0x4b,0x69,0x41,0x16, + 0xe8,0x55,0xb8,0x91,0xc,0x2b,0x24,0x61,0x7,0x45,0xa8,0x51,0x24,0x85,0xbe,0xe6, + 0xa8,0x84,0x28,0xa6,0xbe,0x0,0x7b,0x53,0x98,0x2e,0x1f,0xbb,0x27,0x4b,0x38,0x5a, + 0x5b,0x77,0x45,0xc3,0xc,0x14,0xec,0x24,0xd2,0xa,0xe3,0x89,0x46,0x1a,0xac,0x56, + 0x51,0x6c,0x45,0x31,0x34,0x9d,0xe9,0x36,0xfb,0x5b,0x7e,0xe,0xb8,0x34,0x70,0xa8, + 0xba,0x91,0xfb,0xd0,0xb9,0x51,0x93,0xee,0x86,0x46,0x39,0x30,0xbb,0xc1,0xd,0x1a, + 0xc3,0x7d,0x12,0xb6,0xd1,0x3d,0x96,0x83,0x58,0xf7,0x35,0x5d,0xc,0x17,0x38,0x88, + 0xda,0xe5,0xd0,0x63,0xad,0x2e,0xba,0xc3,0x21,0x99,0x64,0x38,0x39,0x22,0x5a,0x4c, + 0xa8,0xd4,0xc4,0xf0,0x3,0x4d,0x1f,0x9f,0x56,0xe8,0xa3,0x3a,0x66,0xcc,0xd6,0x3b, + 0x92,0xea,0x67,0xe,0x6d,0x8f,0xd,0xc1,0x2d,0x4a,0x29,0x6f,0x43,0xd2,0x27,0x41, + 0x18,0x5,0xc0,0x6d,0xe6,0x84,0xf0,0x3,0xd7,0x31,0xd9,0x44,0x1f,0x1a,0x52,0xa4, + 0xf6,0xd3,0xa5,0x44,0x48,0xae,0xb6,0x13,0xe5,0xb5,0x10,0x44,0x8c,0x46,0x42,0xdd, + 0x89,0x81,0x49,0x35,0x4b,0x82,0x4a,0x6,0xa4,0xff,0xa9,0x68,0x1f,0x1d,0xa5,0x7e, + 0x38,0x58,0xd6,0x36,0xf5,0xa0,0x6f,0x3d,0xf6,0xa8,0x94,0xf7,0xf9,0x18,0x5e,0x19, + 0x9a,0x84,0x7c,0x4a,0xb2,0x5c,0x3a,0xf1,0x34,0x87,0x1b,0x43,0xa5,0x97,0xa6,0xca, + 0x6e,0x7d,0xd5,0xee,0xa1,0x7b,0xf,0xcd,0x47,0x4e,0x4a,0x20,0x53,0x98,0x99,0x84, + 0xf5,0x2c,0x4d,0xbd,0xa,0x55,0x6d,0xaa,0x51,0x7b,0x74,0x21,0xd8,0x88,0xff,0x9f, + 0xb1,0x37,0x6b,0xba,0xec,0x3a,0xcf,0xc3,0xde,0x67,0x75,0xff,0x83,0xfc,0xc,0x57, + 0xa2,0x9d,0x8a,0xe3,0xb2,0x2d,0x91,0x92,0x8,0xa2,0xbb,0xbf,0x1e,0x31,0x35,0x66, + 0x70,0x2,0x7,0x11,0x12,0x67,0x4b,0x16,0xc5,0xc4,0x56,0xac,0xc8,0xb6,0x44,0x29, + 0x24,0x25,0x8a,0x83,0x28,0x42,0x9c,0x0,0x90,0x98,0xd1,0xdd,0xe8,0xe1,0xeb,0x6, + 0x7,0x50,0x94,0x15,0xab,0x4a,0xda,0x94,0xa5,0x8b,0x54,0xca,0xf7,0xc9,0x4d,0x2e, + 0x53,0x95,0xb,0xef,0x37,0x17,0x7b,0xd,0xcf,0xf3,0xbe,0xeb,0x80,0x66,0x49,0x64, + 0xf7,0xd7,0xe7,0x3b,0x67,0x9f,0xbd,0xd7,0x5a,0xef,0xf4,0xc,0x64,0x19,0x97,0xc, + 0x25,0x30,0x65,0x1f,0x85,0x75,0x66,0xcc,0xfb,0x75,0xe2,0x54,0x3f,0xfd,0x3f,0xbf, + 0x63,0x7d,0xdf,0xef,0xec,0x1,0xa9,0xcf,0xa6,0xa2,0x77,0xee,0xc4,0xcb,0xc5,0xc2, + 0xb5,0x44,0x61,0x19,0x65,0x2,0x60,0x5a,0xe1,0x89,0xe4,0x2d,0x66,0xc0,0x32,0xaa, + 0x50,0x11,0x67,0x22,0x98,0x8b,0x19,0x21,0xf3,0x54,0x9a,0x1e,0x75,0xff,0x7e,0x1e, + 0x8a,0x16,0x8c,0xd6,0xa2,0x13,0x8b,0xc0,0xeb,0x85,0x39,0x72,0xc1,0xd3,0xdb,0xe0, + 0x84,0x45,0x40,0xd4,0x20,0x70,0x9e,0x3,0xc5,0x87,0x83,0x0,0x8c,0x9a,0x72,0x64, + 0x82,0x62,0x95,0x91,0xfa,0x1a,0xde,0xc2,0x8b,0x1c,0xa9,0xdf,0x24,0x40,0x99,0xa, + 0x41,0x6d,0x15,0x70,0x99,0x1a,0xde,0x10,0xe6,0x23,0x2a,0x66,0x41,0xaf,0x1,0xc9, + 0x45,0x2d,0x52,0x2a,0x3d,0x78,0x94,0x87,0xe7,0xeb,0x8a,0x23,0x60,0x7b,0xdf,0x8c, + 0xdd,0x0,0x39,0x33,0x23,0x5,0xab,0x3,0x7c,0x4b,0x63,0xae,0xf0,0x41,0xb3,0x98, + 0xc4,0xd1,0x87,0xc5,0x10,0x65,0x71,0x84,0x63,0x9e,0xd6,0xd1,0xc,0x4c,0xe3,0xb3, + 0x67,0x64,0x3a,0x57,0xb7,0xa2,0xa6,0x36,0x69,0x63,0x17,0x3d,0xce,0x38,0x89,0x48, + 0x6c,0x44,0x4c,0xf0,0x37,0xac,0xe9,0x80,0x5c,0xad,0x91,0xa3,0x8b,0x9c,0x2a,0xfb, + 0xeb,0xcb,0x54,0xec,0x6c,0xa2,0xc2,0x9b,0xc6,0x9a,0x71,0x1c,0x9b,0xd6,0x18,0xd1, + 0xb7,0x62,0x75,0xef,0x13,0x91,0x2b,0xc5,0xfe,0x4c,0x66,0xe1,0xcc,0xef,0x36,0xb3, + 0xf7,0xfc,0x2f,0x6f,0x2c,0xef,0xfd,0x37,0x6f,0x2c,0x8,0x1a,0xf8,0x91,0xf5,0xa8, + 0xe3,0x8a,0xa9,0x88,0x40,0xb0,0x1,0x66,0x6c,0xc4,0x18,0x2f,0x22,0x8c,0x6e,0x2c, + 0x9e,0xc1,0x6,0xa5,0x98,0x46,0x5c,0x35,0xfb,0x7e,0x47,0x2d,0x8,0x3f,0xd0,0xc5, + 0xeb,0x49,0x2f,0x6b,0x19,0x4,0x53,0x56,0xa8,0xda,0xa0,0xb,0x2,0x83,0xc0,0x78, + 0xe4,0xcc,0x39,0x92,0x8d,0x80,0x6b,0x89,0x3a,0x52,0x3d,0xc1,0x86,0x34,0x90,0x26, + 0x69,0x7f,0xb7,0x52,0xf5,0x98,0x7c,0x43,0x31,0x49,0xee,0x4c,0xc9,0xb,0x5d,0xa2, + 0x9,0x53,0xe3,0x10,0xde,0x81,0xf5,0x55,0xa,0x73,0xec,0xfc,0xa0,0x4f,0x8,0xf2, + 0x5e,0xb5,0xc3,0x8a,0x79,0x9,0x18,0x36,0x43,0xae,0x22,0x50,0x4,0x26,0xfc,0x43, + 0x6,0x8c,0xf0,0x7b,0x24,0xa0,0xcd,0xc4,0xfa,0xb8,0xcd,0x30,0x3c,0x38,0x8d,0x75, + 0x7,0xb2,0x74,0x61,0x7a,0xd0,0x78,0x77,0xe9,0xe2,0x88,0x8c,0xc0,0xe5,0x45,0x32, + 0x70,0x8b,0x77,0x1e,0x11,0xc0,0x20,0x80,0x23,0x4b,0x3c,0xfa,0x64,0xff,0xc4,0xea, + 0x7c,0x8,0xad,0x55,0x45,0x35,0x11,0xaa,0x7f,0xf8,0xed,0x72,0x4a,0xce,0xff,0xce, + 0x72,0x8e,0x8,0x3a,0xfc,0x3d,0xf3,0x84,0xd9,0x7b,0x7e,0xfb,0x8d,0xe5,0xcf,0xff, + 0xd5,0x5d,0x6b,0x9f,0x17,0xd1,0x6,0x62,0x16,0x41,0xd4,0xef,0x8f,0x9d,0x93,0x79, + 0x60,0x57,0x84,0xfa,0xf8,0xfa,0x6e,0x53,0x69,0xa0,0x60,0x99,0xcb,0xf7,0x52,0x18, + 0x9e,0x20,0x66,0x0,0x53,0xf0,0x66,0xc0,0xc7,0x88,0x74,0x9d,0x2,0x9d,0xe,0x39, + 0xc3,0x67,0x30,0x65,0x4,0x76,0x22,0x56,0xb7,0xa9,0xa,0xcc,0x33,0xb4,0x99,0x8b, + 0xec,0x34,0xca,0x70,0x22,0x89,0x49,0xf0,0x92,0x3,0x42,0xe5,0x2b,0x85,0x62,0x7, + 0xd1,0x99,0x4c,0xc1,0x39,0xd3,0xfe,0x4c,0x78,0xd4,0xe2,0x76,0x37,0x29,0x6b,0x63, + 0xec,0x78,0xcf,0x6f,0xbf,0xb1,0xbc,0xe7,0x5f,0xbf,0xb1,0x48,0x8b,0xbb,0x39,0x92, + 0xd1,0x9a,0xf0,0x8,0xe6,0x55,0xa1,0xb5,0x3,0xf8,0x1b,0xde,0x93,0xc1,0x1,0x51, + 0x14,0x5,0x5d,0x2,0x58,0xa3,0xde,0x49,0xfb,0x9d,0x28,0x7a,0x43,0x8e,0x16,0x8a, + 0xdc,0xe,0xb3,0xdb,0x24,0xb0,0x2f,0x46,0x56,0x10,0x8f,0xec,0x78,0x5e,0x38,0x31, + 0x54,0x7a,0x97,0x6c,0x56,0x6d,0xa0,0x5e,0x2b,0x14,0x15,0xef,0xad,0x3a,0xa4,0x6b, + 0xec,0x49,0x3b,0x3d,0xa3,0x21,0x7a,0x35,0x14,0x3,0xc7,0xa8,0xc0,0x33,0x2b,0xc3, + 0xf2,0xf9,0xe7,0x33,0x67,0x41,0x4,0x7c,0x59,0x40,0xb8,0x8b,0xdf,0x38,0x54,0x3, + 0xae,0x55,0xca,0x51,0x57,0x23,0x36,0xa8,0x0,0x9b,0x88,0x78,0xcd,0xb0,0xec,0x51, + 0x51,0x2e,0x89,0xfe,0xe9,0x79,0x18,0x98,0x22,0x8c,0x42,0x7,0xe8,0x7b,0x13,0x48, + 0x91,0x55,0x35,0x3d,0xd4,0x27,0xc3,0xfb,0x5c,0x13,0x79,0xde,0xa3,0xfc,0xfb,0x59, + 0xfe,0x2,0x86,0x89,0x53,0xa2,0x20,0xfb,0x13,0x42,0x1d,0x56,0x10,0x10,0x87,0x40, + 0x84,0xa7,0x86,0x8c,0x3a,0x54,0x64,0x90,0xac,0xce,0x26,0x2,0xfd,0x41,0x7,0x17, + 0x73,0xdb,0xbf,0x83,0xb4,0x1e,0x8,0x84,0x3d,0x58,0xb6,0x4e,0x68,0x5b,0x7c,0x30, + 0x51,0xfb,0xf7,0xdd,0xbf,0xfd,0xfd,0xe5,0x1b,0xbf,0x7d,0xd7,0xea,0xc9,0xae,0xd3, + 0x82,0x88,0xc,0x7a,0xeb,0xf,0x16,0x9d,0x89,0xc2,0xc2,0x49,0xc8,0xf5,0x3,0x2a, + 0x63,0xb2,0xe1,0xdf,0x2,0xa9,0x79,0x48,0x8,0x5,0xd1,0x9d,0x4d,0x5,0x3,0x40, + 0x98,0x82,0x9e,0xd9,0xbb,0x25,0x21,0xb,0xee,0x50,0xf8,0x44,0x50,0x44,0x54,0x96, + 0xe4,0xcf,0x96,0x5c,0xd8,0x1a,0x1a,0xf7,0x1b,0xbf,0x7d,0xd7,0xfa,0xee,0x7f,0xfd, + 0xc6,0x62,0x41,0x8f,0x3c,0x3d,0x2b,0xfb,0xd9,0xc1,0xcb,0xf4,0xc8,0xb5,0x99,0xb, + 0x6e,0x4e,0x8a,0x82,0x81,0x5,0x26,0xaa,0x68,0x16,0x53,0xdb,0x48,0xc7,0x81,0xbd, + 0xd5,0x18,0xd0,0x82,0xc8,0xc7,0x9c,0x5a,0x47,0x16,0xa3,0xae,0xeb,0x3d,0xe9,0xc9, + 0x10,0x60,0x2c,0x8a,0x9d,0x58,0x50,0xb5,0xf3,0xe4,0xa9,0xe,0x75,0x56,0x9b,0x64, + 0xb4,0x4e,0x6b,0xcd,0x2b,0xda,0x16,0xb4,0xae,0x1d,0x79,0xbf,0x80,0x12,0x23,0x48, + 0x45,0x30,0x2,0x7,0x48,0xf4,0xa8,0x4b,0xa,0x7,0xd8,0xea,0xd0,0xce,0xa7,0x49, + 0xae,0xab,0xca,0x59,0x5b,0x87,0x1e,0x92,0x11,0xb6,0xb9,0x85,0xb1,0xcd,0x2f,0x6, + 0x63,0x80,0x3,0xa0,0x30,0x5c,0xa0,0xd8,0xa,0xe1,0x6e,0x43,0xed,0x4c,0x63,0xb0, + 0xe2,0x6a,0xe,0xfa,0xfd,0x21,0xaa,0x68,0xed,0x3a,0x69,0x27,0x3a,0x77,0x2c,0x4d, + 0xbb,0x98,0x93,0x44,0x36,0xb3,0x6c,0xf3,0xe,0xd1,0xfb,0xc3,0x49,0x15,0x12,0x12, + 0x3d,0x75,0xde,0xac,0x64,0xbb,0x6b,0x8c,0xbe,0x4f,0x96,0x6c,0x6e,0xdf,0xb7,0x48, + 0x27,0x35,0x8e,0x9c,0x9c,0xe8,0x8c,0x39,0x78,0x96,0x94,0xec,0xcd,0x60,0x5e,0x59, + 0xef,0x48,0x7f,0x1f,0x93,0x60,0x16,0x93,0xd5,0x1c,0xdc,0xb8,0xe3,0x68,0x93,0x60, + 0xa7,0xf7,0x99,0x65,0xcb,0xfb,0x7d,0x86,0x2,0xda,0x8c,0x3a,0xbc,0x7d,0x67,0xb, + 0xed,0x6c,0xe8,0xb0,0x38,0x8b,0x72,0x11,0x7d,0xf2,0xdd,0xff,0xea,0xf6,0xf2,0x8d, + 0x7f,0x73,0xf7,0xaa,0xf2,0xbc,0xae,0x82,0x91,0x2a,0xd9,0x99,0x84,0x6a,0x64,0xdc, + 0xc4,0x6b,0x3a,0xce,0x37,0xba,0x72,0xa4,0x57,0x94,0x3b,0x3c,0x71,0xde,0x82,0x5d, + 0xce,0x7c,0x5e,0x35,0xd1,0x2,0x56,0xdc,0xd,0x12,0x4a,0x5c,0xda,0x96,0x69,0x1e, + 0x1d,0x7,0xe5,0x7a,0xf4,0xbb,0x1d,0x0,0x89,0x98,0x4d,0x35,0x8b,0xc5,0xd9,0x86, + 0x90,0x85,0x5a,0xaf,0x91,0x8b,0x17,0x14,0x7c,0x1,0x42,0xb8,0x7a,0x14,0xb1,0x98, + 0x7e,0xf6,0x1c,0xd4,0x64,0xae,0xa0,0x2a,0x9b,0xb4,0x44,0xa7,0x31,0x89,0x1,0x81, + 0xd1,0xb1,0x28,0x5a,0xbd,0xfa,0xec,0x7b,0x16,0x45,0x67,0x6f,0x73,0xf0,0x63,0xbc, + 0xf5,0x43,0x3,0x3e,0xdc,0x43,0x6,0x42,0xb6,0x7f,0xab,0x99,0x28,0x3b,0xe7,0x71, + 0xa0,0xf1,0xe,0x24,0x22,0xfd,0x64,0x76,0x54,0x72,0xb,0xf8,0x2,0x5a,0x1,0x1e, + 0x64,0x1c,0xd5,0xbf,0xcd,0xc4,0xea,0x34,0xda,0x45,0x76,0x84,0xac,0xd9,0x13,0xff, + 0xd3,0x9d,0xc5,0xcc,0xec,0xdb,0xbf,0x73,0xd7,0xea,0x98,0x20,0x6a,0x7d,0xd0,0x20, + 0x13,0x98,0x87,0x2c,0x1a,0xdd,0x63,0x2b,0xcc,0xa5,0x53,0x2,0x77,0xa9,0x72,0x19, + 0x28,0x28,0x6b,0x8b,0xe6,0xed,0xe,0x85,0x5d,0xf6,0xfb,0xd8,0x2a,0x54,0x1e,0x63, + 0x42,0xdb,0xfb,0x8a,0x27,0x83,0xb6,0x27,0xdd,0xb2,0xeb,0x1a,0x72,0xf2,0x82,0x3, + 0xbe,0x5d,0x5c,0x21,0xbb,0x23,0x28,0x90,0x21,0xb1,0x0,0xa6,0x6c,0x61,0xe4,0xf1, + 0x1a,0xcf,0x2e,0x93,0x93,0x5f,0x38,0xb8,0xf5,0x18,0x21,0xb9,0xcb,0x84,0x35,0x8b, + 0x1d,0x9c,0x22,0x62,0x39,0x49,0xb8,0x19,0x13,0x97,0xe5,0x38,0xf2,0x9f,0x7d,0x1d, + 0x9f,0xa1,0xb5,0xe7,0xa7,0x90,0x82,0xb,0xe7,0x1a,0x48,0xd1,0xb1,0xb0,0x9,0xc1, + 0x24,0xe,0x7a,0x6a,0x83,0x12,0x8d,0x15,0x1,0x2b,0x44,0xeb,0xb2,0xfb,0xbb,0x73, + 0x46,0xe9,0x24,0x14,0x23,0x63,0xec,0xe1,0x7f,0x1,0xf2,0x58,0x46,0xc0,0xb2,0xc8, + 0xe1,0x41,0xbe,0x5,0xa0,0x79,0x1c,0x7c,0x2,0x72,0x6f,0x82,0x32,0x8a,0x9a,0xe, + 0xb8,0x80,0x8,0x30,0xd,0xd5,0x76,0xa6,0xf6,0x8c,0xe6,0x6a,0xf7,0x13,0xf1,0x30, + 0xd2,0x42,0xf6,0xd9,0x24,0x9d,0x12,0x9b,0xb4,0xaf,0xf9,0x1c,0x4c,0x33,0xf,0x27, + 0x37,0xc6,0x2d,0xc,0xcb,0x38,0x69,0xdc,0x4c,0xa8,0x8f,0x72,0x53,0x12,0x6,0x29, + 0x4d,0xcf,0xd2,0x3d,0x40,0x14,0x72,0x38,0x60,0x73,0x5e,0x32,0x2f,0x15,0x49,0x90, + 0xc4,0x66,0x1c,0x47,0x59,0xcc,0x25,0xb7,0xd5,0x73,0xc1,0x6c,0xa4,0x5e,0x60,0x82, + 0x21,0x9d,0x38,0x11,0xc5,0x8e,0xa6,0xb7,0x4b,0xd,0xf3,0xb2,0x88,0xfa,0x8e,0x15, + 0x3a,0x57,0xa6,0xa0,0xca,0x95,0x67,0x39,0x46,0x5c,0xe4,0x58,0x15,0x72,0x30,0x37, + 0x9a,0x7,0x22,0x2a,0x52,0xf1,0x18,0x81,0xf0,0x5,0xbd,0xe2,0xf1,0x89,0x7b,0xd5, + 0x6c,0x36,0x66,0x16,0x68,0x37,0xa0,0x79,0x36,0x9b,0xb5,0x20,0xb5,0xc5,0x46,0x5, + 0xae,0x6,0x3b,0xe2,0xdd,0xed,0x44,0xc3,0xa9,0x15,0x91,0x93,0x92,0x9,0xc8,0x47, + 0xfd,0x89,0xcf,0xbc,0xb1,0x7c,0xfb,0x7f,0x7d,0xe7,0x6a,0x80,0x7d,0xeb,0x77,0xee, + 0x5a,0x9f,0xf8,0xcc,0x1b,0xb,0x4b,0x21,0x8a,0x3e,0xbc,0xf0,0xce,0x89,0x92,0x44, + 0x73,0x4b,0x39,0x5c,0x9b,0x35,0x29,0x9c,0x46,0x29,0xb1,0xdb,0x11,0xfe,0xe8,0x8c, + 0x59,0xf0,0x54,0x49,0x20,0x82,0x64,0xea,0x33,0x55,0xec,0x84,0x5e,0x9b,0x53,0x76, + 0xef,0x41,0xb0,0xc3,0xc2,0xb4,0x55,0xb,0x7e,0xea,0x7c,0xc0,0x26,0x8a,0x53,0xb9, + 0xfa,0x7,0xb2,0xac,0x6b,0xf6,0x21,0xd0,0x1,0x4c,0x76,0x68,0x9c,0xe8,0xfe,0x23, + 0xa,0x1d,0x22,0xf0,0xf9,0xf,0x50,0x60,0x90,0xdb,0x96,0x91,0xcb,0x3d,0xae,0x7b, + 0x3c,0x43,0xf,0x73,0xcf,0xc7,0x3f,0x73,0x67,0x79,0xfc,0x33,0x77,0x96,0x43,0x98, + 0x7,0xf,0x17,0x38,0x2a,0xd0,0xe0,0xdd,0x76,0xc0,0x29,0x8c,0x9d,0xee,0x3c,0x76, + 0xe6,0xe,0xf0,0x8e,0xb5,0x9d,0x7e,0x68,0xe6,0xbe,0xff,0xe9,0xf1,0xcf,0xdc,0x59, + 0x9e,0xf8,0xcc,0x9e,0xf4,0x8d,0xe0,0x5,0x6d,0x85,0xfb,0xa4,0xef,0xeb,0x33,0x8e, + 0x30,0x27,0x5b,0x8,0xe3,0xba,0x91,0xac,0x1,0xd1,0x82,0x77,0xec,0x6f,0x5e,0xaf, + 0xd9,0xf1,0x4b,0x16,0xb2,0x54,0xf4,0x8a,0x99,0x23,0xd6,0x1,0x75,0x50,0x10,0x75, + 0xec,0x1b,0x3,0x20,0xea,0xc4,0xcf,0xf4,0x40,0xe4,0x43,0xe3,0x48,0xc3,0x72,0x27, + 0xd7,0x42,0x52,0x10,0xbb,0x8e,0x33,0x59,0xe8,0x43,0xc5,0x62,0xd0,0x66,0xb7,0x98, + 0x90,0xce,0xac,0xb,0x27,0x75,0xba,0xb4,0xbf,0xdd,0xec,0xdb,0xbf,0x7b,0xf7,0xfa, + 0xf8,0x6f,0xdd,0x5e,0x26,0xe1,0x63,0x54,0xd0,0xb3,0xef,0x57,0xf5,0xdc,0x33,0xe6, + 0x82,0x3b,0x9b,0x45,0x8a,0xb6,0xe8,0x59,0xe0,0x7,0x5b,0x82,0xb3,0x80,0x6e,0x13, + 0xe9,0xec,0x4c,0xfa,0x2f,0xaa,0x7,0x8e,0x7e,0xb0,0x26,0x8e,0xdb,0x44,0xa1,0x46, + 0x81,0x8,0x5c,0xbd,0x59,0x2,0x8d,0x75,0xc,0x25,0x5b,0x4c,0xb6,0x23,0xa2,0x66, + 0x5e,0x8f,0xff,0xd6,0x1b,0xcb,0xe3,0x9f,0xbe,0xb3,0x58,0x3c,0xa0,0xd,0x49,0xa1, + 0x4a,0xcb,0x13,0x12,0x93,0x8,0xb3,0xa5,0x38,0x3b,0xfe,0xf6,0xef,0xbe,0x73,0x7d, + 0xec,0xd3,0x75,0x7e,0xd7,0xde,0xdd,0x77,0x8d,0xe0,0x8,0x4,0x63,0x41,0xfe,0x2e, + 0xbe,0x5f,0x67,0x4c,0x8e,0x61,0x69,0xa,0x83,0x58,0x67,0x4a,0x9,0xe1,0x2e,0xed, + 0xda,0xb8,0xa9,0x9c,0x13,0x89,0x6e,0xf,0xa,0x12,0x9d,0xc8,0x33,0x58,0x1c,0x50, + 0x9d,0x1b,0x18,0x1,0x13,0x8e,0x24,0x18,0xf9,0xbe,0x59,0xe,0x44,0x61,0xb1,0xfa, + 0x66,0xf6,0xf8,0x6f,0xdd,0x59,0xbe,0xfd,0xbb,0xef,0x5c,0x39,0x3,0xd7,0x79,0x93, + 0x25,0x8f,0x75,0x13,0xc1,0x91,0xd4,0x25,0xb6,0x99,0xa2,0x56,0x53,0xa8,0x43,0x15, + 0x2d,0xc4,0x5b,0xe1,0x30,0x0,0x51,0x62,0x9a,0x22,0x9e,0x2d,0x52,0xd1,0x68,0x56, + 0xc6,0x1b,0xc,0x53,0xe8,0x63,0x48,0xe2,0xf7,0xf,0x7b,0xec,0xd3,0x77,0x96,0xc7, + 0x3e,0x7d,0x67,0xf1,0xd8,0x3e,0x4,0x26,0x7a,0x17,0xd1,0xe5,0x20,0xb6,0xfa,0xc9, + 0xa2,0x93,0x5a,0xf2,0x59,0x4d,0x2e,0x28,0xb1,0x89,0x8d,0x2c,0xb5,0x41,0x2d,0xfb, + 0x51,0xb3,0x9b,0xc2,0x78,0x1f,0x76,0xcf,0xaa,0x7b,0xc4,0x5d,0x83,0x4d,0xfd,0xbd, + 0xc7,0x3e,0x7d,0x7b,0x79,0xec,0xd3,0x77,0x96,0x21,0xed,0x39,0xc4,0x5b,0xc0,0x46, + 0x3b,0xae,0x33,0xdf,0x5e,0xc9,0x8b,0x30,0x8f,0x8b,0x56,0x3,0x78,0x9d,0xc6,0x71, + 0x1c,0x89,0x2c,0x21,0xa2,0xc8,0x81,0x94,0x0,0x27,0x40,0x97,0x47,0xd5,0x8e,0x0, + 0x9f,0x86,0xc9,0x4c,0x17,0x80,0x3d,0xf6,0x9b,0xb7,0x97,0xef,0xfc,0xdb,0xbb,0xd7, + 0x3e,0xef,0x44,0xae,0xc0,0x11,0x3,0x86,0x1f,0x1a,0xff,0x1c,0x0,0xd5,0x5,0xe1, + 0x71,0x4c,0xc6,0x43,0x12,0xbb,0x58,0x29,0x2e,0x52,0xf5,0x26,0x76,0xb0,0x71,0x5f, + 0xa3,0xa9,0xff,0xc5,0x96,0xec,0x41,0x1c,0x8,0xe6,0xd9,0xe1,0xb4,0x3,0xb,0xad, + 0xc8,0x71,0x0,0xe3,0x11,0xf3,0x32,0xfc,0xac,0xcf,0x8d,0x38,0x7,0x3b,0x80,0x37, + 0xc9,0xf6,0xc3,0x36,0xb1,0xd9,0xc5,0xc,0x52,0x3d,0xd1,0x6a,0x1f,0x1d,0x23,0xb6, + 0x3d,0x26,0xb5,0x4d,0x4c,0x52,0x83,0xda,0xe5,0xeb,0x78,0x2c,0xcb,0x95,0x7c,0x56, + 0xe4,0x8c,0xe2,0x40,0x8,0xce,0x96,0x93,0xcc,0x1c,0xa0,0x22,0x86,0xee,0x70,0x6b, + 0x21,0x9,0x2d,0x73,0xdf,0x37,0x27,0x67,0xad,0x6e,0x76,0x92,0x12,0x7d,0x24,0xb0, + 0x7c,0xa7,0xb,0xa8,0x29,0x4a,0x18,0xe,0x8d,0xe7,0x10,0x9e,0xdd,0x29,0xf3,0xad, + 0x7,0xc8,0x6f,0xde,0x59,0x60,0x66,0xcf,0xfc,0xdb,0xbb,0xd6,0x47,0x3f,0xfd,0xc6, + 0x92,0x5c,0x7e,0x2,0xf0,0x60,0x56,0x8d,0x59,0xe0,0x19,0x3f,0xfa,0x9b,0x77,0x96, + 0x67,0xfe,0xdd,0x3b,0x57,0x98,0xd9,0x33,0xff,0x6e,0x4,0x26,0x99,0xb,0x4f,0x36, + 0x6e,0xa4,0x38,0xc9,0xd0,0x1,0x66,0xf0,0xc1,0x35,0xef,0xde,0xe8,0x25,0xb6,0xaf, + 0x21,0xe2,0x30,0x36,0xe5,0x19,0x8f,0x76,0x3c,0xca,0xce,0x53,0x96,0x20,0x44,0xdc, + 0xdf,0x19,0xa5,0x6a,0x50,0x85,0xd1,0x2d,0x3a,0x65,0x84,0xe8,0x59,0xf0,0x45,0xe8, + 0xad,0xae,0x8b,0xc6,0x89,0xdf,0xfd,0xcc,0xbf,0x6f,0xf7,0xab,0x5d,0x23,0xdb,0xfa, + 0x51,0xe2,0xe7,0xec,0xe2,0x7,0xb2,0xa,0x45,0x4e,0xad,0x3d,0x2,0xe5,0xb8,0x72, + 0x20,0x47,0xb6,0xd9,0x17,0xe9,0x5a,0xc6,0x44,0x77,0x4c,0xfa,0xd9,0x10,0xbd,0x71, + 0xa6,0xa2,0xb9,0x7,0x20,0x9d,0x5b,0xa2,0xcc,0x8c,0x96,0x39,0x42,0x65,0xe1,0x74, + 0xdf,0x90,0x7,0xeb,0x7,0xe,0x36,0xbc,0x5,0x90,0x2c,0x8d,0x5c,0x78,0xcc,0xe5, + 0x48,0x4c,0x6,0x1c,0x98,0x4c,0x41,0x7c,0x38,0xed,0xad,0xfa,0x76,0xc9,0xae,0x20, + 0xe1,0xd,0x58,0x30,0x27,0x18,0x5a,0x60,0x7a,0xf1,0xe3,0x20,0xf3,0xa0,0xdb,0x90, + 0xbb,0x77,0xca,0x6d,0xd1,0xd1,0x53,0x31,0x11,0x40,0x71,0x4,0x12,0x3,0xa6,0xa3, + 0x81,0xa9,0xb,0x6a,0xa8,0xda,0x67,0x66,0x4a,0x49,0xa0,0x28,0xfa,0x53,0xc7,0x68, + 0x5d,0x42,0x72,0xc0,0xfd,0x73,0x51,0xa4,0x3a,0xe0,0x45,0x10,0xc0,0xa1,0x6a,0x81, + 0x3b,0x8a,0x84,0x68,0x97,0x39,0x7d,0x96,0x41,0x9d,0xaa,0x8f,0xc5,0x3c,0x8f,0x5, + 0x3c,0x38,0x7f,0xcd,0xa1,0x96,0x2e,0x1f,0xc1,0xda,0xef,0x79,0x4,0x1,0xd5,0x9a, + 0x31,0x35,0xfc,0x81,0x7b,0x12,0x27,0xe2,0x96,0x77,0xe0,0xf1,0xd6,0xf7,0xde,0xf7, + 0xea,0xa3,0xbf,0xb1,0x57,0xc8,0xcf,0xfe,0xde,0xa9,0x55,0xaa,0x51,0x96,0xf8,0x75, + 0xd3,0x31,0x1d,0xa1,0xe2,0x9d,0xd9,0xa4,0xf4,0xfd,0x1e,0xfd,0x97,0xc7,0x8b,0x99, + 0xd9,0x73,0xbf,0x7f,0x6a,0x65,0x8a,0xb4,0xc1,0xec,0xd1,0xdf,0x38,0x5e,0x9e,0xf9, + 0xbd,0x53,0xab,0x88,0x2,0x89,0xf4,0xb0,0x8f,0x19,0x79,0x48,0xf2,0xdb,0x6a,0x7e, + 0xf6,0xdf,0x9f,0x5a,0x1f,0xf9,0x97,0xc7,0xcb,0xb3,0xbf,0x77,0x6a,0xed,0x53,0x51, + 0x77,0xe1,0xd4,0x1f,0xc2,0x4a,0xc1,0x33,0xb7,0xfe,0xd1,0xdf,0x38,0xee,0xf7,0xa1, + 0x63,0xa2,0x92,0xfe,0x80,0x25,0x8a,0x35,0x3f,0xaf,0x93,0xb3,0x20,0x16,0x3,0xa7, + 0x80,0x3d,0xbc,0x4c,0x8c,0xad,0x83,0xcb,0x52,0x54,0x0,0xd6,0x15,0x40,0x59,0xc5, + 0x98,0x65,0x3c,0xfb,0xfb,0xef,0x5c,0xad,0x70,0xa6,0xe9,0xc9,0xb3,0x39,0x82,0xe9, + 0x1e,0xa9,0xb,0xe1,0xb9,0xdf,0xbf,0x7b,0x1d,0x74,0x5,0xf,0xf3,0xe4,0x61,0x4a, + 0xd1,0xd,0x29,0x28,0x23,0x1b,0x87,0x91,0x2b,0x2b,0xc8,0x91,0x16,0x3c,0xb7,0xd6, + 0xe0,0x1e,0x3e,0x3f,0xf6,0x86,0x48,0x5e,0x85,0xe,0x69,0x56,0xa,0xeb,0x82,0x14, + 0x22,0x84,0xe2,0x79,0xe,0xc5,0x54,0x12,0x37,0x51,0xee,0x12,0xe0,0xc8,0x66,0xf6, + 0xdc,0x67,0xdf,0xb9,0x3e,0xf2,0x1b,0x77,0x96,0x3e,0xd7,0xb6,0x80,0x5e,0xb7,0xb8, + 0x40,0x3c,0xf8,0x72,0x87,0x3,0x84,0x5c,0xae,0x7a,0x46,0x9,0xed,0x2,0xa4,0x59, + 0x53,0xe2,0xb8,0xb9,0x8,0xa0,0x24,0xd,0xf2,0x30,0x8f,0x8e,0x1,0x99,0xe7,0x6b, + 0x6e,0x1,0x95,0x2f,0x80,0x83,0x68,0xc7,0x19,0xb3,0xe5,0xfd,0x7,0xfd,0xb9,0x7d, + 0xb6,0x3e,0xb7,0x39,0x6f,0x51,0x32,0xe9,0xb7,0xec,0x8a,0xfd,0x8c,0x7f,0x49,0xff, + 0x1e,0xb6,0xcf,0x23,0xbf,0x71,0x67,0x5c,0xcf,0x3c,0xf2,0x4f,0xf0,0x28,0xec,0xb9, + 0xe9,0x99,0x49,0xe6,0x39,0x98,0xbc,0xd5,0x55,0x8a,0xe8,0xe9,0xa6,0x50,0x8d,0xb9, + 0x39,0xb7,0xf7,0x80,0x17,0xef,0x6f,0x74,0x4e,0x9,0xf9,0xa3,0xe8,0x17,0xc8,0xfe, + 0xf6,0x21,0x32,0x24,0xe,0xf0,0x51,0xf1,0xd0,0x26,0x38,0x18,0xca,0x44,0x44,0xd7, + 0x32,0x5,0x48,0xf4,0xae,0xdc,0xc3,0xbf,0x7e,0xbc,0x3c,0xf7,0xfb,0xf5,0x50,0xdf, + 0x4c,0x94,0xd2,0xd0,0x3c,0xeb,0x5d,0x3b,0x76,0x4c,0xab,0x6a,0x2a,0x66,0x3c,0xdd, + 0x12,0xc4,0x8f,0x48,0x10,0x40,0xc6,0x3e,0x2e,0xa0,0x9c,0xb1,0xef,0xdd,0xe3,0xfd, + 0x21,0x59,0x67,0x9f,0x29,0x76,0x2a,0x36,0xc6,0xe,0x30,0x90,0xfa,0xf9,0xd7,0x3, + 0xac,0x27,0x16,0x3,0x48,0x0,0x4c,0x3,0x88,0x4b,0x70,0x77,0x64,0x3f,0x7a,0xb7, + 0x0,0x8e,0xe,0xeb,0xdf,0x25,0xb1,0x14,0x93,0xee,0x34,0x4b,0x76,0x57,0xdd,0x11, + 0x40,0x4d,0x6e,0x78,0x4d,0x7a,0x38,0x23,0x7d,0xb2,0xef,0x7d,0x2,0x7a,0xe5,0x35, + 0xdb,0x18,0x2,0x10,0xe0,0xd9,0xa8,0xa0,0x1d,0x6a,0x56,0xc3,0x54,0x69,0xe6,0xa2, + 0xb,0xc4,0x69,0x13,0x85,0x1,0xb,0xb6,0x4c,0xfd,0x3c,0x95,0x9f,0x6f,0x11,0xff, + 0xa,0x61,0xc7,0xbb,0x3c,0x7b,0x4f,0x31,0xb1,0x1b,0x21,0x3,0x13,0xa0,0x88,0xa9, + 0x89,0x86,0x8b,0x33,0x93,0xa2,0x97,0x1d,0x41,0x32,0x33,0x18,0xb2,0x30,0x82,0xd7, + 0x99,0x18,0x6f,0x6e,0xf,0xff,0xfa,0xed,0xe5,0xb9,0xcf,0xbe,0x73,0x75,0xe2,0xe6, + 0xf5,0x4b,0x17,0x34,0x36,0x52,0x60,0x1d,0xb3,0x26,0x4f,0x60,0x3d,0x8f,0x2d,0x10, + 0x9a,0x3f,0xbb,0x87,0xef,0xa,0xcf,0xa8,0xf9,0xd4,0x6,0xc9,0x99,0xbf,0x7,0xeb, + 0xbf,0x84,0xf2,0x97,0x9b,0x69,0x41,0x97,0x99,0x84,0x3f,0x12,0x7f,0x78,0xd6,0xca, + 0xd2,0xd9,0x59,0xd2,0xcc,0x34,0x45,0xb8,0x47,0x4,0x25,0xcf,0x2e,0x67,0x68,0x73, + 0xf5,0xed,0xe,0xb3,0xdd,0xfa,0xb1,0xdf,0xfd,0xec,0xdd,0xeb,0xc3,0xbf,0x7e,0x67, + 0xb1,0xd0,0xd5,0x7c,0xee,0xb3,0x77,0xaf,0xf,0xff,0xfa,0xed,0x3e,0x43,0x7d,0xf8, + 0xd7,0xef,0x2c,0xf,0xff,0x8b,0xdb,0x4b,0xfb,0xc5,0xfe,0xf7,0x83,0xf4,0xf2,0x68, + 0x29,0x39,0x19,0x11,0xd,0xb8,0xd3,0xe1,0x2a,0xe8,0x80,0xde,0x33,0x7f,0x6f,0x65, + 0x3,0xcc,0x6a,0xea,0x88,0x15,0x41,0xba,0x6f,0x79,0x2e,0x8b,0x9c,0xc0,0xd2,0xda, + 0x79,0xf8,0x5f,0xdc,0xae,0xf7,0xc3,0xc8,0xd4,0x46,0x65,0x8c,0x5d,0xb0,0xa2,0x44, + 0xe5,0x9b,0xb5,0x26,0x67,0x93,0x8b,0x94,0xf4,0x42,0x7c,0xe,0x4,0x83,0x11,0xcc, + 0x7c,0xd8,0xbc,0x25,0x69,0x89,0x8b,0xfa,0xba,0xae,0xd7,0xde,0x29,0xea,0xaf,0x7f, + 0xb,0x55,0xb2,0xb6,0xff,0x6b,0xd0,0xfa,0xee,0x67,0x4f,0xad,0xf,0x7f,0xea,0x78, + 0x89,0xd7,0x89,0x30,0x23,0x76,0x1,0x8e,0xf2,0x99,0x33,0x11,0xc6,0x6,0x8d,0xa9, + 0x2c,0x83,0xe5,0x78,0x6e,0xcd,0x8e,0x59,0xfd,0xd7,0x83,0x7f,0x27,0x26,0x8b,0xd5, + 0x39,0x30,0xc4,0xf3,0x91,0xba,0xf,0xed,0xbd,0xc4,0x6,0x13,0x21,0x71,0x71,0x8, + 0x5,0xd7,0xc8,0x87,0x61,0x6c,0x6f,0xe2,0xdb,0x40,0xc7,0x4e,0x8e,0x8c,0xd6,0xf6, + 0xba,0x43,0x7c,0x32,0xa,0x50,0xcf,0xf6,0x62,0xd1,0x6b,0x43,0x12,0x7d,0x10,0xaa, + 0x1f,0x6a,0xae,0xa3,0x10,0xc3,0xf1,0x9e,0xf,0x7f,0xea,0x78,0x79,0xa8,0x3e,0xd3, + 0x88,0xf9,0x10,0x9d,0x8,0x4a,0x22,0x18,0xe3,0xc2,0xd2,0xbf,0x3d,0x18,0x16,0x8, + 0x16,0x83,0x53,0x36,0x3f,0x20,0x56,0x5,0x33,0x7b,0xe8,0x53,0xc7,0xcb,0x77,0xff, + 0xe0,0xf4,0xea,0x44,0x85,0x7c,0xf8,0x53,0xc7,0xcb,0xc3,0x9f,0x3a,0x5e,0x86,0xe4, + 0x30,0xc7,0x1c,0xf5,0x2d,0x78,0xe8,0x53,0xc7,0xcb,0x73,0x7f,0x70,0x6a,0x65,0xe1, + 0xb4,0x21,0x20,0xd6,0x2e,0x63,0x48,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x34, + 0xe8,0xd2,0x2e,0xa0,0xde,0x11,0x70,0x7d,0xa2,0x15,0x62,0xd1,0x24,0x8a,0x9f,0x31, + 0xe2,0x39,0x83,0x20,0x75,0xc3,0x3e,0x25,0xfb,0xdf,0x1e,0xfe,0xd4,0xf1,0xf2,0xf0, + 0x27,0x6f,0x2d,0x1c,0x62,0x44,0x4d,0x1,0xc1,0x88,0x17,0xb4,0x10,0x40,0x33,0x5d, + 0xe5,0x6c,0x7b,0xe0,0xba,0x26,0x39,0x2c,0x9b,0x36,0x1a,0xa5,0x6a,0xa4,0x59,0xc1, + 0xa6,0x75,0x8,0x84,0x78,0xae,0xf4,0x30,0x99,0x1d,0xc5,0x79,0xc5,0x66,0x49,0x17, + 0x9e,0x33,0x32,0x1c,0x8c,0x9e,0x7,0x8c,0xdb,0x3d,0x7f,0x17,0xe5,0x31,0x8e,0xdb, + 0xfe,0xd0,0xa7,0x6e,0x2f,0xf,0x7d,0xf2,0xf6,0x62,0x98,0xcf,0x94,0xa,0xe7,0x53, + 0xf4,0x4f,0xf,0x7d,0xf2,0xf6,0xf2,0xd0,0xa7,0xee,0x2c,0x87,0xf4,0x7d,0xf3,0x1c, + 0x7d,0xbc,0xee,0xa1,0x4f,0xde,0x5e,0xbe,0xfb,0x7,0x7b,0xc5,0x29,0xae,0x6a,0x85, + 0xc0,0x5a,0x74,0xbd,0x73,0xb0,0xe4,0xcc,0x30,0x27,0x6c,0xa8,0x80,0xa4,0x37,0x53, + 0xbc,0x42,0xfa,0xfc,0xc0,0x57,0xc7,0xc4,0xa1,0xc9,0xc4,0x58,0x35,0xcc,0xeb,0xa0, + 0xb7,0xde,0x5,0x59,0xbd,0xff,0xf0,0xa1,0x4f,0xd6,0xfb,0xcd,0xb4,0x1e,0x68,0x85, + 0x3d,0x54,0x2,0x67,0xeb,0x26,0xd2,0x82,0x42,0x73,0x69,0xcb,0x55,0x13,0x5b,0x7b, + 0x82,0xdb,0xfc,0xc1,0x48,0x46,0x7f,0x1f,0xc9,0x46,0x77,0x7f,0x6e,0xa7,0x3a,0xcf, + 0xbf,0x3,0xc0,0x82,0x4f,0x7d,0xe7,0xd4,0x3,0x66,0x33,0xe4,0x7a,0x3,0x5a,0xd1, + 0xde,0x75,0x68,0x32,0xe4,0x2a,0xdf,0x98,0xdc,0xe9,0x40,0xb3,0x45,0x99,0x29,0xcf, + 0xb8,0xd3,0x3c,0x6e,0x23,0x7d,0x7,0x4,0xe0,0x12,0x60,0xf6,0xe0,0x27,0x8e,0x97, + 0x87,0x3e,0x71,0xbc,0x80,0x14,0xba,0x1c,0xfc,0xc,0x90,0x5d,0xbe,0x3c,0x60,0x1b, + 0xdc,0xec,0xa1,0x4f,0xee,0x1,0xe3,0xc1,0x4f,0xee,0xad,0x49,0xb0,0x6e,0x37,0xb4, + 0xbb,0x33,0x34,0xfc,0x4b,0xaf,0xb2,0x5c,0x41,0xd7,0x52,0x19,0x72,0xa5,0x25,0xa2, + 0x42,0x13,0x3c,0xc8,0x6c,0xef,0xc,0xac,0x54,0x0,0xd7,0x9a,0x5,0x35,0x3d,0x2a, + 0x68,0xe,0xec,0x73,0x5d,0x9f,0x1e,0x8a,0x80,0xec,0xe,0xc7,0xd8,0x19,0x31,0x83, + 0x89,0x34,0x4d,0xa8,0xe1,0xcd,0x43,0x9f,0x38,0x5e,0x1e,0xfc,0x44,0xd,0x70,0x48, + 0xb5,0x34,0x51,0x16,0x7d,0x8,0xa6,0x48,0xd0,0xa5,0xf3,0xe7,0x13,0xc7,0xcb,0xf7, + 0xfe,0xf0,0x74,0x5d,0xc7,0x6e,0x98,0x8e,0x32,0xd5,0xb6,0x19,0x54,0xa1,0xf,0xef, + 0x89,0x90,0x8c,0x79,0x9c,0xb8,0x53,0xc5,0x4b,0x85,0x90,0x83,0xfc,0xe7,0x7b,0x57, + 0xcd,0xd3,0x79,0xd5,0xf9,0xfa,0xdb,0xd8,0x8e,0xbd,0x3b,0x13,0xba,0x9d,0x40,0x9c, + 0x81,0x73,0x33,0x65,0xff,0xc7,0xef,0xfd,0xe1,0xe9,0xf5,0xc1,0x4f,0x1c,0x2f,0x51, + 0x58,0x8a,0xbb,0x99,0x69,0x21,0x38,0xf1,0xd4,0x6d,0x72,0xce,0xc8,0xfe,0x64,0xd0, + 0x6e,0xc6,0x0,0xf4,0xee,0x28,0x38,0xa2,0xc4,0x1c,0xa7,0x66,0x64,0xf,0x7e,0xe2, + 0xf6,0xf2,0xe0,0x27,0xee,0x2c,0xf,0x7e,0x62,0xa0,0x0,0xe1,0x7,0x78,0xd6,0x69, + 0x79,0x97,0x29,0x0,0x23,0xce,0xd9,0xb8,0x72,0x9a,0x6a,0xf6,0xb2,0x53,0x4d,0x0, + 0xe,0xc4,0x4c,0x96,0x4f,0x63,0x71,0xca,0xe1,0x4b,0x29,0x61,0x46,0x78,0xe8,0x3b, + 0xd0,0x35,0x5c,0xfe,0x78,0xb,0xce,0x9e,0x50,0x92,0xc2,0xd9,0xb6,0x88,0xaa,0xf7, + 0x79,0x0,0xee,0xb4,0x40,0x97,0x4d,0xe6,0x6e,0xf6,0xbd,0x3f,0xbc,0x7b,0x5f,0x20, + 0x16,0xd1,0xf0,0x81,0x1f,0x4c,0x54,0x8,0xc4,0x2c,0x33,0x55,0xa0,0xae,0xd7,0x4b, + 0x8a,0x68,0x6e,0x48,0xdd,0x1,0xa9,0x43,0x67,0x5d,0x0,0x40,0xfe,0xec,0xa6,0xa, + 0x7c,0x11,0x55,0x2e,0x8a,0x72,0x32,0x79,0x19,0x8,0x7b,0x9f,0x88,0xf2,0xb4,0x2e, + 0x4c,0x14,0xa1,0x11,0x8f,0x69,0xb8,0xae,0x3,0x99,0x2d,0x8f,0x8e,0xcc,0xf7,0x3e, + 0x77,0xaa,0xde,0x57,0xad,0x88,0xd,0xc1,0xd2,0x30,0xfa,0x8f,0xc6,0x8a,0xde,0xd9, + 0x23,0xfb,0x0,0x7a,0x3a,0xa8,0x8b,0xa,0xa,0x99,0x9a,0x2c,0xf,0x7e,0xfc,0x78, + 0xf9,0xde,0xe7,0x4e,0xaf,0x9c,0xe9,0x77,0xa4,0x73,0x84,0x21,0x90,0xc8,0x10,0xd8, + 0x4a,0xd4,0x72,0x77,0x40,0xe4,0x5c,0x3d,0x82,0xcb,0x26,0x73,0x68,0x42,0xaf,0x67, + 0x1e,0xb4,0x76,0x23,0x30,0xa9,0x86,0x14,0x95,0xbd,0x7f,0xaf,0x7,0x3f,0x7e,0xbc, + 0xcc,0xd8,0x17,0x8c,0xe9,0x51,0xad,0xf9,0xcc,0x31,0x7e,0xe0,0x63,0xfb,0x41,0x9, + 0x7a,0xe,0xcf,0xff,0x6f,0xa7,0xd6,0xe7,0x3f,0x77,0x7a,0x7d,0xf0,0xe3,0xc7,0x8b, + 0x47,0x7b,0x5c,0x55,0xae,0x17,0xd4,0xbf,0xd6,0x94,0x30,0x2f,0xa,0x7c,0x75,0xd7, + 0xf1,0x4f,0x16,0x4f,0x1,0xbb,0x33,0x24,0x65,0xb0,0xc,0x9d,0x52,0x30,0x54,0x37, + 0xee,0x81,0x13,0xf,0x86,0x9c,0xfe,0x24,0x99,0xc9,0xf4,0xd9,0xa8,0xc3,0xdf,0x6a, + 0xc1,0xcb,0x1f,0x3f,0x5e,0x9e,0xff,0xdc,0xe9,0x55,0x3b,0x72,0x46,0x6a,0x72,0x2e, + 0xec,0x19,0x4c,0x2a,0x63,0x17,0xf8,0x46,0xdb,0x93,0x8c,0x92,0x67,0xe1,0xa7,0xec, + 0x73,0x7e,0xb9,0xae,0x63,0xd5,0x65,0x47,0x70,0x9c,0x24,0x69,0x5c,0xcc,0x3b,0x68, + 0xa2,0x89,0x42,0xb7,0xf4,0xf2,0xc7,0x6f,0x2d,0x97,0x3f,0x7e,0x6b,0x61,0xfb,0xd2, + 0x29,0x17,0xab,0x2e,0xe0,0xcb,0x1f,0xbb,0xb5,0x3c,0xff,0xf9,0xd3,0x2b,0x53,0x85, + 0xd5,0x6d,0x12,0x49,0x9a,0x36,0x16,0x8d,0xee,0xb1,0x80,0x8c,0x9d,0x44,0x88,0x62, + 0x26,0x9f,0x37,0xf,0xb6,0xcf,0xf,0xb1,0xc4,0xc9,0x32,0x5c,0x19,0x57,0x8,0x9d, + 0xae,0x78,0xe,0x46,0x95,0xd6,0xf1,0x19,0xf2,0xdc,0x45,0xfa,0x95,0xde,0xa4,0xe9, + 0xc2,0xfa,0x66,0xf6,0xfc,0xe7,0x4f,0xad,0xcf,0x7f,0xfe,0xee,0xf5,0xf2,0xc7,0x5a, + 0xcb,0x54,0x5b,0x33,0xd2,0x6,0xc0,0xa4,0xa,0x43,0x74,0x3d,0x19,0xa0,0xa8,0xcb, + 0x1f,0xbb,0xbd,0x3c,0xff,0xf9,0x53,0x2b,0x6f,0x20,0xad,0x20,0x61,0x62,0x60,0xd2, + 0x6f,0xa6,0xf7,0xdf,0x1d,0x9a,0xe5,0xb4,0x70,0x3b,0x47,0x3a,0x54,0xd6,0x4d,0x35, + 0x69,0xb3,0xa9,0x9c,0x65,0xd0,0xf7,0x32,0x98,0xd9,0xe5,0x8f,0xdd,0x5e,0x5e,0xf8, + 0xfc,0xa9,0xf5,0xf2,0xc7,0x8e,0x17,0x2e,0x6b,0x2e,0x7f,0xf4,0x78,0x79,0xfe,0x73, + 0xa7,0xd6,0xe7,0xeb,0xbf,0xd,0x94,0x3f,0xb2,0x2,0x11,0x60,0xf7,0x7f,0xf4,0x78, + 0xb9,0xfc,0xf1,0xe3,0xe5,0xf2,0xc7,0x6e,0x2f,0xce,0xf7,0x86,0x47,0xea,0xb5,0x2a, + 0x7a,0x3e,0x7e,0x9e,0x33,0x8,0x6d,0x64,0xf9,0x20,0xbd,0xe6,0x56,0xf5,0x58,0x44, + 0x11,0x13,0x2a,0x99,0x15,0xa8,0x10,0x69,0xa0,0xd0,0x56,0x9b,0x76,0x71,0x4b,0x42, + 0xb6,0xf7,0x67,0x97,0xe6,0xa2,0x5a,0x31,0xb4,0xbf,0x3f,0xff,0xb9,0xd3,0xfb,0x77, + 0x62,0x8e,0x75,0x3c,0x8e,0x23,0x8d,0xab,0x56,0x9d,0x97,0x3f,0x7a,0xbc,0x5c,0xfe, + 0xe8,0xf1,0x12,0x81,0x97,0x7d,0x84,0x13,0x32,0x5b,0x3e,0xce,0x2f,0x7f,0xec,0x78, + 0x79,0xe1,0xf3,0x63,0x4e,0xca,0x15,0x8d,0xa0,0x49,0xa1,0xad,0x59,0x41,0xa6,0x8b, + 0x72,0x97,0xd,0xa3,0x5,0x10,0x70,0x8a,0xaa,0xfc,0xcb,0x1f,0xdb,0xaf,0xd7,0xcc, + 0xec,0x81,0x8f,0x1e,0x2f,0x2f,0x7c,0x7e,0xaf,0x5c,0x3c,0xa4,0xea,0xad,0x8a,0x18, + 0x1d,0x25,0xda,0x7f,0x91,0x5,0x50,0x86,0x44,0x72,0x9f,0x1d,0xc6,0x71,0x14,0xb5, + 0x93,0x5b,0x55,0xe5,0xa4,0xbc,0xe7,0xe9,0x95,0xda,0xc2,0xc3,0xb4,0xf3,0xe5,0xb2, + 0xa7,0x67,0xa8,0xe8,0x51,0xf9,0xc4,0x75,0x6,0x7b,0xe0,0xa3,0xf5,0xe0,0x99,0x74, + 0x73,0x64,0xc6,0x49,0xea,0x66,0x70,0xb3,0x7,0x3e,0x7a,0x6b,0x79,0xe1,0x8f,0x4e, + 0xaf,0xf,0x7c,0xf4,0x56,0x3f,0x77,0x7a,0x97,0x7,0x41,0x4f,0x22,0xe6,0xca,0x98, + 0x81,0xbe,0x20,0xf6,0xce,0xdd,0xb3,0xa0,0xb6,0xda,0x5f,0xf8,0x7c,0xfd,0x2c,0x1b, + 0xe,0x8c,0x39,0xdf,0x87,0x28,0x81,0x5,0x8,0x74,0xe8,0xec,0x41,0xfc,0xb3,0xe3, + 0x68,0x29,0xc9,0x9f,0xd5,0xbf,0x3e,0xf0,0x91,0x5b,0xcb,0xb,0x5f,0x18,0xf7,0x4b, + 0x40,0xb0,0x13,0xe4,0xb8,0x22,0xb5,0xc3,0x38,0x0,0x46,0x6b,0x60,0x22,0xbf,0x2a, + 0xe8,0xf8,0x99,0xa0,0x4c,0xb4,0x2e,0x45,0x1e,0x49,0x81,0x3b,0x9e,0x3,0x4f,0x73, + 0xb0,0x56,0x4a,0x6c,0xe,0xed,0x8,0x1,0xf9,0x86,0xfa,0x66,0xf6,0xc2,0x17,0xce, + 0xac,0xf,0x7c,0xe4,0xd6,0x92,0xeb,0xcf,0x18,0x63,0x26,0x5d,0x44,0xc2,0xfc,0xbc, + 0xf0,0x85,0xd3,0xeb,0x3,0x1f,0xb9,0xb9,0xf0,0x6b,0x5e,0xf8,0xc2,0x99,0xfe,0xec, + 0x2d,0xe8,0xb0,0x8b,0x9f,0x8,0x7c,0x56,0xf2,0x58,0x7c,0x56,0xea,0xc2,0x16,0xbb, + 0xaa,0x1e,0x3a,0x9c,0xc8,0x9d,0xc4,0x89,0x2c,0x34,0x17,0x6f,0xfb,0x1a,0x39,0xb3, + 0x66,0x7c,0x8f,0x57,0x12,0x38,0xb8,0xed,0x6d,0xc2,0x5b,0xee,0xd4,0x8,0x8f,0x73, + 0x46,0xef,0x33,0xa0,0x19,0x25,0x83,0x54,0x5,0x2d,0xab,0xa8,0x8d,0x8c,0x84,0xf9, + 0x9a,0x30,0xb3,0x17,0xff,0xe8,0xd4,0xfa,0xc0,0x47,0xc6,0xfc,0x15,0x81,0xf3,0xcb, + 0x33,0x8a,0x5e,0xd1,0x3b,0x29,0x19,0x5,0x5b,0x46,0x44,0x1,0x15,0x98,0xbd,0xf0, + 0x85,0x53,0xeb,0xfd,0x1f,0xdd,0xbb,0xe,0x71,0x6f,0x39,0x6d,0xc4,0xfb,0x3f,0x7a, + 0xbc,0xbc,0xf8,0x47,0xa7,0x56,0x6,0xc5,0xf0,0x3c,0x1a,0x50,0x44,0x39,0x8b,0xa9, + 0xb0,0x90,0xfe,0x3,0x1f,0x39,0x5e,0x5e,0xfc,0xa3,0xd3,0xeb,0xb,0x5f,0x38,0xb5, + 0xea,0x7d,0xd4,0x44,0x8c,0xc7,0xe2,0xfb,0x61,0x56,0x13,0x5,0x2,0x49,0x8,0x97, + 0x1a,0xea,0x7f,0x1e,0x95,0xa6,0x62,0xfb,0x3c,0xce,0xfc,0xe3,0xd8,0x21,0x63,0x28, + 0xe6,0xdd,0x7,0x4,0xc4,0xbb,0xaa,0x2a,0xb1,0x12,0x58,0xb0,0xa7,0x74,0x4b,0xf8, + 0xb,0x99,0x3e,0xb5,0x8e,0x30,0x75,0x54,0xee,0xff,0xc8,0xf1,0xf2,0xe2,0x1f,0xd7, + 0x59,0x98,0xe8,0x5,0xd0,0x6c,0x75,0xe2,0x7b,0x1f,0x11,0xdb,0x2d,0x21,0xba,0xff, + 0x23,0xfb,0x33,0xf5,0x99,0x38,0x9,0xdc,0xee,0xff,0xc8,0xf1,0x72,0xff,0x47,0x6e, + 0x2d,0xf7,0x7f,0xe4,0x78,0xe9,0x92,0x8f,0xd1,0x3,0x0,0x41,0x9b,0xdd,0x21,0x88, + 0xdf,0xa4,0x7,0x40,0x9d,0x6,0x36,0xe6,0x88,0x73,0x3c,0xa3,0x39,0x23,0xba,0x57, + 0xbb,0xee,0x2f,0xa5,0xe8,0xe8,0x2f,0x32,0x47,0xbc,0xb7,0x4b,0xa5,0x15,0x8,0x51, + 0xf,0xf4,0xc8,0x1e,0x9,0x7e,0xdc,0x8c,0x36,0xd6,0xf3,0x1c,0xf3,0xd7,0xd3,0xfa, + 0x7f,0xf1,0x8f,0x4f,0xaf,0xf7,0xff,0xda,0xad,0x45,0x99,0x10,0xca,0x3a,0xf0,0x89, + 0xc3,0x1a,0xd0,0x9e,0xf9,0x99,0x95,0xf7,0xb7,0x56,0x4d,0x1,0x73,0xe0,0xd9,0x3a, + 0xb5,0x71,0x85,0x93,0x5a,0x1b,0x59,0x3b,0xa,0xcf,0x98,0xfe,0x1e,0x5b,0xad,0x71, + 0xa3,0x2,0x98,0xd0,0x2b,0xb9,0x4b,0xac,0x58,0x82,0xfb,0x7f,0xed,0xe6,0x72,0xff, + 0xaf,0xdd,0x5a,0x42,0x17,0x39,0x43,0x27,0x9,0x99,0x1e,0xfd,0xd0,0x93,0x59,0x10, + 0x20,0xaf,0x73,0x67,0x76,0x8d,0xb6,0xce,0x31,0x1b,0x6b,0xd0,0xbe,0x29,0x7,0xf0, + 0x2c,0x8a,0x5f,0x99,0x0,0x2b,0x4b,0xd6,0x34,0x7f,0xf1,0x8f,0xcf,0xac,0xf7,0xf7, + 0xc0,0x3b,0xd3,0xc2,0xa3,0x99,0x47,0xe8,0xb4,0xce,0x95,0x32,0xf3,0x1e,0x4a,0xc8, + 0xfd,0x30,0x8a,0xe0,0xd7,0xc9,0x4c,0xda,0x33,0x26,0x86,0x75,0xd5,0x63,0xf7,0xf7, + 0xd0,0x8,0x36,0xe9,0xf1,0x73,0x77,0x50,0x10,0xee,0x93,0xa4,0xf,0x50,0x9c,0x17, + 0xe,0x75,0x32,0xa3,0x56,0x49,0x5c,0xa7,0xba,0x87,0x5a,0x42,0x56,0x8c,0x66,0x72, + 0x4e,0xfc,0x68,0xf4,0x4a,0x16,0x89,0xab,0x37,0xd5,0xe6,0x26,0x54,0x5e,0xef,0xf7, + 0x3b,0x52,0xd5,0xce,0x62,0xff,0x3a,0x37,0xc9,0x1c,0xbe,0xc4,0x27,0x9e,0x20,0x65, + 0xc7,0x6c,0x36,0x70,0xa1,0x29,0xfb,0xf7,0x58,0xc5,0x48,0x66,0x3,0x5,0xe0,0x71, + 0xeb,0x6e,0x23,0x0,0xde,0x16,0x14,0xcd,0x52,0xc5,0x31,0xde,0x4d,0x78,0xa4,0x11, + 0x35,0xbc,0xf1,0xf8,0x21,0x80,0xa3,0x36,0x4d,0x3a,0xbb,0x12,0x1b,0x18,0x78,0x43, + 0x55,0x34,0x83,0x8d,0x26,0xb3,0x22,0x6,0x6b,0x89,0xf6,0x3a,0xb7,0xaf,0xd,0x19, + 0xec,0xc5,0x6d,0x42,0x4c,0xe6,0xa5,0xa6,0x3c,0x62,0x37,0x97,0xce,0x8a,0xf0,0xe1, + 0x63,0x15,0x91,0x30,0x16,0x22,0xe2,0x69,0x66,0xb0,0xfb,0x9e,0xba,0xb5,0xdc,0xf7, + 0xab,0xc7,0xcb,0x7d,0xbf,0x76,0xbc,0xbc,0xf4,0xc7,0xa7,0xd7,0xa1,0xda,0x14,0x8c, + 0x11,0xe8,0xf3,0x5e,0xfc,0xe2,0xe9,0xf5,0xbe,0x5f,0xad,0x0,0x11,0x2,0xee,0xc, + 0x4c,0x6,0x64,0x56,0xd7,0xd5,0xf0,0x68,0xae,0x7d,0xdf,0x53,0xc7,0xcb,0x4b,0x5f, + 0x3c,0xbd,0xbe,0xf4,0x45,0xaa,0xa8,0xdd,0x32,0xcf,0xda,0x26,0x9c,0xe3,0xfa,0x4f, + 0xf7,0xff,0xea,0xad,0xfe,0x1e,0xf7,0x3d,0x75,0x6b,0x69,0xdf,0xf9,0xa5,0x3f,0x3e, + 0xbd,0xde,0xff,0x54,0xd,0x70,0x30,0xbb,0xef,0x57,0x6f,0xed,0xdf,0x8d,0xb3,0xfa, + 0x9,0x4e,0x83,0x51,0x58,0xe2,0x79,0xf,0xb3,0xfb,0x9f,0x3a,0x5e,0xee,0xfb,0x55, + 0xee,0x5c,0x14,0xda,0x87,0x91,0xfc,0x3e,0x7,0x8a,0xc5,0x8a,0x2c,0x6b,0xf4,0xcf, + 0xd0,0xff,0xa3,0x5c,0x6c,0xdf,0x97,0xe7,0xe1,0xbc,0x37,0x63,0x5,0xd9,0x3a,0x58, + 0x63,0xcd,0xc6,0x5d,0x8e,0x49,0xe7,0x82,0xe7,0xa1,0x2e,0x58,0x9b,0xa9,0x8,0x4a, + 0x12,0x2c,0xe1,0xd1,0x97,0x27,0xc,0x88,0x60,0x6b,0xc2,0x4e,0x98,0xcb,0x9e,0xcd, + 0x83,0x15,0x26,0xff,0x7b,0xdf,0x53,0xb7,0x96,0x97,0xbe,0x78,0x66,0x9d,0xee,0xfb, + 0x49,0xcc,0x68,0xdf,0xf7,0xe5,0xba,0x7e,0x66,0xed,0x5e,0xf1,0xb0,0xdc,0x26,0xc, + 0x96,0x4,0x7e,0xb4,0x74,0x6f,0xb8,0x42,0xf7,0x89,0x56,0x8f,0xf9,0xc4,0xf8,0xc6, + 0x2d,0x7c,0x5b,0x4,0xfc,0x81,0x9e,0xc9,0x62,0x49,0xc1,0x5d,0x12,0xaa,0x28,0xf2, + 0xb9,0x14,0xf4,0xda,0xe9,0xfd,0x5e,0xfa,0xe2,0x99,0xf5,0xbe,0xf,0xdf,0x5c,0xc2, + 0xdc,0xae,0x17,0x9c,0xb3,0xca,0x77,0xe8,0xb1,0x4f,0x3c,0x3d,0xd8,0x3d,0x6d,0xd3, + 0x52,0x43,0xbe,0x53,0x8c,0x8b,0xc1,0xae,0xf9,0xe5,0x2f,0x9e,0x59,0xef,0x7d,0xea, + 0xe6,0xb2,0x33,0x9,0x10,0x94,0x10,0x8d,0xba,0xa4,0x38,0xb0,0xde,0xc6,0x99,0x24, + 0x1d,0x6a,0xe8,0xbd,0xef,0x6d,0xf9,0x6d,0xdc,0xff,0x97,0xff,0xe4,0x68,0xbd,0xef, + 0xa9,0x9b,0x8b,0xd,0xb7,0x35,0x4f,0xf8,0xde,0x2e,0x2e,0xef,0x11,0x35,0xee,0x1, + 0xe5,0xab,0x33,0x26,0xd7,0x24,0x7e,0xcf,0xe0,0x30,0xa5,0x61,0x4b,0x95,0xdd,0x1a, + 0x84,0x4e,0x28,0xdb,0xf6,0x6d,0xee,0xfd,0xf0,0xf1,0x72,0xef,0x53,0xc7,0xb,0x8b, + 0x71,0xdc,0xfb,0xd4,0xf1,0xf2,0xf2,0x9f,0x9c,0x5e,0xe3,0x7b,0xf0,0xd,0x90,0x99, + 0x58,0xe0,0xf0,0xe9,0xdc,0xc3,0x87,0x7a,0x13,0xcd,0x6e,0x11,0x66,0x23,0x23,0x7b, + 0xa7,0xec,0x36,0xa2,0x24,0x53,0x45,0xc7,0xdf,0x87,0xee,0x69,0x14,0x74,0xe6,0xc, + 0x92,0x4a,0x9f,0x97,0xbf,0x74,0x7a,0xbd,0xf7,0xc3,0xb7,0x16,0x44,0x87,0xa5,0xfa, + 0x9d,0xef,0xfd,0xf0,0xad,0xe5,0xbe,0xf,0xdf,0x1a,0x73,0x61,0x20,0x65,0xa0,0x7e, + 0x0,0xed,0x3d,0x3,0xed,0xc8,0x61,0x18,0x33,0x28,0x42,0x34,0x1b,0xcd,0x9d,0xd4, + 0x2b,0x9c,0xaa,0xf3,0x4e,0xf3,0x41,0xcf,0x3a,0xdb,0xf7,0x99,0xce,0x90,0x48,0x89, + 0xd0,0xdd,0xec,0xe5,0x3f,0x39,0xbd,0xbe,0xfc,0x27,0xfb,0x5c,0x4e,0xaa,0xa9,0x68, + 0x1e,0xed,0x81,0xf,0x1f,0x6d,0x31,0x3d,0x57,0xce,0x8,0x5a,0xf7,0x2e,0xca,0x4d, + 0x9a,0x75,0xdf,0xfb,0xd4,0xad,0xe5,0xe5,0x2f,0x9d,0x59,0x25,0xeb,0x4e,0xfc,0xda, + 0xa0,0xd6,0x57,0x2f,0xfa,0xe5,0x2f,0x9d,0x5e,0x5f,0xfe,0xd2,0x99,0x95,0xf7,0x10, + 0xaf,0x1f,0xee,0xeb,0x72,0x75,0x78,0xef,0x87,0x6f,0x2e,0xfb,0x73,0x9f,0x14,0x89, + 0xa1,0x3a,0xe3,0xca,0x78,0xb4,0x33,0x5d,0x59,0xc3,0x98,0x1,0xb0,0xdc,0xee,0x7d, + 0xea,0xd6,0x72,0xef,0x53,0xb7,0x96,0x7b,0x7e,0xe5,0xd6,0x22,0xad,0x40,0x41,0xad, + 0xcf,0x5a,0xed,0x48,0x2a,0x66,0xdc,0x5d,0x6a,0xf7,0xf1,0xe5,0x2f,0x9f,0xd9,0xbf, + 0x3f,0x54,0xed,0x8c,0x2b,0xae,0x7b,0x3e,0x7c,0x73,0x11,0xb1,0x1f,0x64,0x2f,0x1, + 0xa4,0xb9,0xa6,0x9b,0x4f,0x1d,0x6c,0x98,0xae,0x13,0x9c,0xfc,0xcc,0x4,0x54,0xc8, + 0x7e,0x7,0x32,0xbb,0x9e,0x74,0xae,0xe,0xb5,0x77,0x63,0x95,0xee,0xa1,0x4d,0x7f, + 0xcf,0x87,0x6f,0x2e,0x2f,0x7f,0x79,0x7f,0xfe,0x2f,0x7f,0xe9,0xcc,0xbe,0x97,0xe5, + 0x31,0x14,0x5,0xc6,0xb2,0xd3,0x2c,0x7f,0x5f,0xc7,0x5c,0x0,0x8a,0x5,0xb0,0x22, + 0x17,0x3d,0xca,0x84,0x42,0x2a,0x82,0x9,0x9b,0xc1,0x26,0xb6,0xb0,0x1c,0xc0,0x46, + 0xd1,0x73,0xcf,0x87,0x6f,0x2e,0xf7,0x7c,0xf8,0xe6,0xd2,0x70,0x16,0xb1,0xdb,0x15, + 0xbb,0x4d,0xc3,0xe1,0xce,0xc8,0x4b,0x1d,0x22,0x89,0xfd,0xf2,0x97,0x8f,0xd6,0x7b, + 0x7f,0xe5,0xe6,0xa2,0x6e,0x9d,0x10,0xbb,0x7b,0x90,0x3f,0xc7,0xf0,0x11,0xf1,0x20, + 0x66,0x94,0xad,0x5b,0x3b,0xa0,0xb7,0x32,0xa2,0x22,0xa6,0xa7,0x73,0xf9,0xe1,0xdd, + 0x4f,0x20,0x56,0xf0,0x2c,0xb5,0xb,0x76,0x49,0x63,0xdc,0x54,0x64,0x1b,0x45,0xe6, + 0x4b,0xc3,0x4f,0xd4,0xa4,0xe6,0xe5,0x2f,0x9f,0x59,0xef,0xf9,0x95,0x9b,0x4b,0xee, + 0xac,0x22,0x81,0x33,0x7b,0xec,0x1,0x88,0x9d,0xe1,0xfd,0xfe,0xb7,0xe7,0x53,0x0, + 0xd8,0x3d,0xbf,0x72,0xbc,0xdc,0xf3,0x2b,0x15,0xa9,0x47,0xa,0x6e,0xa9,0xea,0x63, + 0x6a,0xb,0x73,0xc9,0x2d,0xd2,0xcc,0x77,0x50,0x4,0x28,0xe8,0x61,0x62,0x59,0xca, + 0xfc,0x3f,0x31,0x41,0xa8,0xd9,0xd3,0x3d,0x1f,0x3a,0x5e,0x5e,0xfd,0xf2,0xe9,0xf5, + 0x95,0x2f,0x9d,0x5e,0xef,0xfd,0xd0,0xbe,0x19,0x80,0x5c,0xf1,0x7a,0x68,0x49,0x2, + 0x19,0x2d,0x98,0xda,0xcf,0xe4,0xf9,0xcd,0x26,0x19,0x7d,0x91,0x5,0xa4,0x7c,0xab, + 0x10,0x99,0x43,0xd8,0xce,0x86,0x57,0xbe,0x74,0x7a,0xdd,0xf,0x45,0x48,0x45,0xc7, + 0xd5,0x57,0x43,0x20,0x8f,0xeb,0x8d,0x2d,0x2e,0x4c,0xb5,0x85,0x65,0x1e,0x43,0xaa, + 0x74,0x9,0xbd,0x1d,0xba,0x29,0xfb,0xe7,0xb8,0xa8,0x54,0xbe,0xf2,0xe5,0xd3,0xeb, + 0x2b,0x5f,0xde,0xc1,0x22,0xf1,0xa1,0xe1,0x0,0x35,0x4f,0x1,0x8d,0x50,0x25,0x3a, + 0xb8,0x54,0x75,0x31,0xf3,0x57,0x4,0x71,0xe8,0x7a,0x0,0x59,0xf1,0xe,0xb1,0x72, + 0x9b,0x54,0x6d,0xe0,0x75,0xa7,0xf7,0xad,0xfd,0xef,0xa5,0xf,0xdd,0x5a,0xee,0xf9, + 0xd0,0x1e,0x28,0x3a,0xea,0x76,0xe6,0x46,0x47,0xa8,0xda,0x7b,0x3e,0x74,0x6b,0x79, + 0xe5,0xcb,0x67,0xd6,0x1e,0x30,0xa4,0x3,0xe4,0xd2,0xa1,0xba,0xa7,0xbe,0x7f,0x84, + 0x88,0xdd,0xf3,0xa1,0x9b,0xcb,0xab,0x5f,0xde,0x5b,0xc5,0x8c,0x17,0x81,0xdc,0x23, + 0x9f,0x56,0x87,0xaf,0x7c,0xe5,0xcc,0x7a,0xcf,0x87,0x6e,0x2e,0x1e,0x3a,0x2c,0x36, + 0x81,0xa1,0xa1,0x7e,0xd6,0x2b,0x5f,0x3e,0xb3,0x8a,0x42,0x58,0x7d,0xe9,0x7e,0x7d, + 0x5c,0xdd,0xcd,0x0,0xac,0xfb,0xf5,0xbc,0xf2,0xe5,0x33,0xeb,0xab,0x5f,0x3d,0xb3, + 0xde,0xf3,0x21,0x9d,0x55,0x37,0x65,0x3d,0xc0,0xe,0x6b,0x4d,0x87,0x4e,0x99,0x63, + 0x36,0x1b,0x1c,0x5d,0xe,0x7e,0x7f,0xa0,0xd8,0xab,0x5f,0x3e,0xaa,0x9f,0x5d,0xf, + 0x72,0x37,0xbb,0xe7,0x83,0xfb,0xf7,0xea,0x14,0xb4,0x6d,0x98,0x6e,0x8c,0x35,0xe, + 0xd9,0x7f,0x91,0xef,0x88,0xe8,0x74,0x7,0xc2,0x67,0x38,0x61,0x45,0xb6,0x20,0xb1, + 0xbd,0x85,0xc0,0xc6,0xad,0x75,0x20,0xb9,0xb7,0xb1,0xc4,0x6e,0xb4,0x11,0x35,0xea, + 0x70,0x22,0xae,0x7d,0x1b,0xe8,0x71,0x71,0xd,0x24,0x2c,0xc,0x77,0x21,0x1,0xef, + 0xa8,0x7d,0x98,0x9a,0x3,0xb5,0xd7,0xbc,0xf2,0x95,0xa3,0xb5,0xaf,0x79,0xa1,0xa7, + 0x41,0x81,0x8d,0x8,0x6e,0x94,0x5b,0x3,0x7a,0x46,0xb3,0xa3,0xd0,0xa1,0x60,0x0, + 0x6e,0xc0,0xe8,0xa8,0x83,0x25,0x72,0x87,0x35,0xe4,0x59,0x3d,0xb8,0xf1,0x59,0x6c, + 0xcc,0xcb,0x56,0x26,0x5,0x3f,0x97,0x57,0xbe,0x72,0xb4,0x5e,0xfa,0xe0,0x8d,0x25, + 0x9a,0xbe,0x48,0xdf,0x22,0x7a,0x5a,0xd0,0x5c,0x1c,0x80,0xbd,0xf2,0x95,0xa3,0xf5, + 0x95,0xaf,0x1c,0xad,0x9d,0x3e,0x6a,0xb0,0x57,0xbf,0x7a,0xb4,0xde,0xf3,0xc1,0x9b, + 0x8b,0x74,0x80,0xa1,0xb8,0x14,0xa6,0xd2,0xa9,0xc0,0xd9,0xe4,0xfc,0x9b,0xf1,0xbb, + 0xa0,0x9d,0x60,0x3d,0xeb,0x2,0xc6,0x49,0x1b,0x10,0xca,0x56,0xd9,0x88,0xc4,0x2b, + 0xdd,0x2f,0xb3,0xc2,0xe8,0x3a,0x27,0x8a,0xd8,0xa5,0xf,0x1d,0x2f,0xaf,0x7e,0xe5, + 0xf4,0x6a,0xe4,0xed,0x2a,0x63,0x1,0xec,0x9b,0xd2,0x23,0xc7,0xd1,0xb,0xad,0x4f, + 0x4,0xa1,0x96,0xf1,0xba,0x4b,0x1f,0xbc,0xb5,0xbc,0xfa,0xd5,0x33,0x2b,0x26,0xd5, + 0xaa,0xcc,0x85,0xa2,0xf7,0xb6,0xe9,0xec,0xeb,0xd5,0xaf,0xec,0x87,0x91,0xc3,0xed, + 0xd2,0x87,0x6e,0x2d,0x97,0x3e,0x38,0x2a,0xd6,0x99,0x94,0x5e,0x1a,0x3d,0x46,0x6d, + 0x60,0xcc,0xfc,0x6e,0xd9,0x64,0x4,0x76,0x4f,0xbd,0x76,0xb3,0x58,0x75,0xe4,0x6b, + 0x5,0xcd,0x80,0x58,0x75,0x69,0xd6,0xc6,0x9b,0xcd,0x6d,0x52,0xa5,0xd4,0x29,0x4c, + 0x9e,0xdd,0xd5,0x42,0x85,0x55,0x12,0x88,0x45,0x71,0xc0,0x19,0xb0,0x98,0x59,0xd8, + 0x9,0xa0,0x12,0x2a,0x82,0x66,0xea,0xf0,0xea,0x57,0xcf,0xac,0x97,0x3e,0xb8,0xdf, + 0xff,0x57,0xbf,0xca,0x15,0xad,0xa5,0xf9,0x7a,0xe0,0x3d,0x84,0xee,0xca,0x9c,0xd3, + 0x9c,0x31,0x1c,0xa1,0xaa,0xa9,0xef,0x7d,0xe9,0x83,0x37,0x97,0xd7,0xfe,0xf4,0xcc, + 0x2a,0x9d,0x84,0xfa,0xe6,0xaf,0xfe,0xe9,0x1e,0xbc,0x6c,0xe2,0xe3,0xce,0xa8,0xfc, + 0x34,0xcb,0xf4,0x3,0x1d,0x88,0x50,0xbd,0xb9,0x67,0x1b,0x4f,0xb1,0x9c,0xf4,0xda, + 0x16,0x8f,0x5e,0xcb,0x13,0xd5,0xb2,0xd7,0xbe,0x7a,0xb4,0x5e,0xfa,0xc0,0x1e,0xe8, + 0x10,0x5a,0xfc,0x8e,0xa8,0xd9,0x3f,0x28,0x79,0x16,0x66,0xf8,0x56,0xef,0xc9,0xa5, + 0x7a,0x58,0xb5,0xb7,0x69,0xf7,0x49,0x5b,0x96,0xaa,0xf9,0x9f,0xcc,0x76,0x22,0x6f, + 0xcb,0x70,0x70,0xfd,0x25,0x70,0x55,0x7d,0xdd,0xa5,0xf,0xdc,0x58,0x5e,0xfd,0xd3, + 0x33,0xab,0xd3,0xc8,0xe5,0xd5,0xf6,0x5d,0x79,0x16,0x4c,0xd5,0x1f,0x7c,0xfc,0x5e, + 0x3c,0x23,0x72,0x49,0x48,0x89,0x83,0x8d,0xcf,0xbc,0xf8,0x81,0x9b,0x4b,0x3,0xbb, + 0x39,0xa3,0xf3,0x91,0xd7,0xa6,0xb8,0x95,0x21,0xa3,0xd7,0xfb,0xe8,0xad,0x1d,0xea, + 0xbb,0x9a,0x87,0x5d,0xfa,0xc0,0xcd,0xe5,0xd2,0x7,0x6e,0x2e,0x40,0xbe,0xac,0x51, + 0x59,0x5,0x8f,0xee,0x48,0x85,0x75,0x92,0x84,0x16,0x5,0xb3,0xf1,0x9a,0x8b,0xf5, + 0xfb,0xe8,0x39,0x16,0xf7,0x4d,0xc0,0xbe,0x4,0x5c,0x38,0x77,0x12,0x1,0x4d,0x80, + 0x7c,0xe2,0x9c,0x38,0xf7,0x8c,0xa0,0xf3,0x86,0xc0,0xa5,0xaf,0x7d,0xad,0x3d,0x4f, + 0x44,0xd1,0x43,0xea,0x98,0x22,0x30,0x67,0x44,0x14,0xb2,0x1f,0x4f,0x17,0x3f,0x70, + 0x63,0x79,0xed,0x6b,0x47,0xab,0x73,0x3b,0xdc,0x99,0x21,0x13,0x74,0x9a,0xb8,0x13, + 0xd6,0xf4,0xd6,0x2b,0xcd,0xc9,0x49,0xc7,0x7,0x18,0xe0,0xc7,0x59,0xa7,0xaf,0xe3, + 0xbb,0x10,0xdd,0xda,0x4c,0x4,0xb2,0x5c,0xb0,0xf,0x93,0xb3,0x8a,0x71,0x60,0xd2, + 0xd5,0xf4,0x84,0x45,0x9a,0x9e,0x2b,0xce,0x9c,0x8,0x97,0x6e,0x65,0x14,0x2c,0xaa, + 0x2d,0x77,0x24,0x14,0xaf,0xa0,0x6e,0xe1,0x82,0xa6,0xe4,0xaa,0xe9,0xe2,0xfb,0x6f, + 0x2e,0x97,0xde,0x7f,0x4b,0x85,0xed,0x31,0x71,0x85,0x4f,0xb3,0xad,0xf8,0x7e,0x1, + 0x99,0xb9,0x99,0x5d,0x7c,0xff,0xad,0x71,0xe0,0xf4,0xaa,0x3d,0xcf,0xd8,0xb8,0x2, + 0x66,0xd4,0xe6,0x54,0x27,0x37,0x54,0x27,0x11,0x1d,0x99,0xe,0xd8,0x38,0xfb,0x6, + 0x26,0x9c,0xd5,0x90,0x15,0x86,0xeb,0xe0,0x6c,0xcf,0x2d,0x54,0x16,0x50,0xca,0x18, + 0x6b,0x3,0xb7,0xc3,0xe4,0xb5,0xaf,0x9d,0x59,0x2f,0xbe,0x7f,0xef,0x4e,0x5c,0x7c, + 0xff,0xcd,0xe5,0xe2,0xfb,0xf7,0x59,0xcd,0xc5,0x27,0x6f,0x2d,0xaf,0x7d,0xed,0xcc, + 0xfa,0xda,0x9f,0x9e,0x59,0x2f,0xbe,0x7f,0x47,0x6d,0xb6,0xdf,0xb9,0xf2,0xa7,0x67, + 0xd6,0xd7,0xbe,0x76,0xa6,0x8b,0xf5,0x70,0x4b,0xd6,0xa3,0x78,0xc,0x2,0xff,0x37, + 0x8d,0x1f,0xf4,0xd1,0xe9,0xcc,0xae,0x18,0x6b,0x14,0xcb,0x6c,0x6a,0x53,0x77,0x2d, + 0x8f,0x8,0x50,0xb,0xc8,0x5b,0x57,0xa7,0xa2,0xe,0x68,0x62,0x24,0x35,0x2,0xf5, + 0x11,0x5a,0x1d,0xb6,0xef,0x6d,0xb6,0x1f,0x2a,0x17,0x9f,0xac,0xf7,0x85,0xbc,0xb6, + 0x2d,0x56,0x7b,0x66,0x76,0xf1,0xfd,0x37,0xfa,0x5a,0x6b,0x2d,0xd9,0xd7,0xbe,0x76, + 0x34,0xee,0x2b,0xeb,0xd8,0xcb,0xac,0x4b,0x85,0x56,0xfa,0x67,0x4d,0x12,0x21,0x5e, + 0x7,0x17,0x9f,0xbc,0xb9,0xbc,0xf6,0xb5,0xa3,0x35,0x96,0xbc,0xdc,0x3d,0x70,0xf8, + 0xfe,0xec,0x9f,0xbc,0xb9,0xc4,0x5a,0x84,0x7f,0x7f,0x7c,0xf,0x74,0x4a,0x94,0xcc, + 0x24,0xd3,0x6c,0xe,0xa4,0x52,0x45,0x15,0x60,0xc0,0x7c,0x5c,0xf9,0xda,0xd1,0x7a, + 0xf1,0xc9,0x1b,0x4b,0xc4,0x7a,0xb0,0xaa,0x24,0x42,0x7,0x3,0x86,0x9d,0x87,0xbd, + 0x11,0xe,0x23,0xbc,0x3f,0x63,0x1a,0xc6,0x8,0xcc,0xc3,0xfd,0xb6,0xde,0x4a,0xbd, + 0xf2,0xb5,0xa3,0xf5,0xc2,0xfb,0x6f,0x2c,0xc3,0x1,0x70,0x82,0x9d,0x11,0x7b,0x65, + 0x24,0x59,0xd2,0xbe,0x2e,0x8b,0x56,0x8e,0x7c,0xef,0xcc,0xcc,0xae,0x7c,0xed,0xec, + 0xbe,0x66,0x8c,0xe8,0x5b,0x16,0xa8,0x5e,0x66,0x76,0xe1,0xc9,0x9b,0xcb,0x78,0xdd, + 0x58,0xbb,0x91,0xdd,0x22,0x98,0x98,0xfe,0xfe,0x37,0x16,0x1,0x71,0x21,0xe8,0xef, + 0x6d,0xa3,0x20,0x16,0x87,0xc3,0x50,0x1,0x47,0x2c,0xb,0x8c,0x67,0xab,0x7a,0xac, + 0x5d,0x78,0xdf,0x8d,0xe5,0xe2,0x93,0x37,0x16,0xf,0x63,0x22,0xdf,0xcc,0x5e,0xfb, + 0xb3,0xb3,0xeb,0x85,0x27,0x47,0xc5,0x6b,0x6e,0x76,0xf1,0xc9,0xfd,0xf5,0xdd,0xb6, + 0xd6,0x6,0xaf,0xff,0xc2,0x93,0x37,0x96,0x2b,0x5f,0x3b,0xbb,0x46,0x6c,0x4a,0x77, + 0xf,0x74,0xea,0x52,0x32,0xd6,0xc7,0x60,0x17,0x9f,0xbc,0xb1,0x5c,0x78,0xf2,0xc6, + 0xd2,0x29,0x78,0xe,0xc1,0x43,0x88,0xa6,0x3a,0x75,0x39,0xf4,0xc,0x83,0x5d,0xf9, + 0xb3,0xa3,0xf5,0xc2,0xfb,0xae,0x2f,0x60,0x45,0xbb,0xf6,0x19,0xef,0xbb,0xb1,0x5c, + 0xf9,0xb3,0xa3,0xb5,0xcf,0x9c,0xb7,0xf1,0xe4,0xe4,0x79,0xbb,0x3a,0x21,0x72,0xb5, + 0x8c,0xc0,0x3a,0x19,0xc8,0x4b,0xc5,0x25,0xc0,0x42,0x97,0x1,0xba,0x8f,0xcd,0x2, + 0x46,0x29,0x3,0x15,0x52,0x5c,0x51,0xd5,0x45,0x24,0xd1,0xa8,0xfd,0xfb,0x9d,0x5d, + 0x65,0x5d,0xd2,0x5e,0x2e,0x17,0xde,0x7f,0x73,0xb9,0xf2,0x67,0x67,0x56,0xf7,0x19, + 0xdf,0xd8,0x3,0xea,0x4f,0x3f,0x20,0x2a,0x70,0x49,0x7d,0x7,0xe5,0xd0,0xc5,0x6b, + 0xe3,0x19,0x46,0x7,0xd,0x4c,0xdc,0xd1,0xda,0x7f,0xae,0x7c,0xfd,0xcc,0x7a,0xe1, + 0xc9,0x9b,0xcb,0x85,0x27,0xf7,0xeb,0x15,0xeb,0x51,0xaa,0x6c,0xae,0xfc,0xd9,0xfe, + 0x3a,0x51,0x83,0x9b,0x18,0x11,0xcb,0xe7,0x7b,0x0,0xe6,0x79,0x91,0xb9,0xa0,0x23, + 0xf0,0x90,0x39,0x93,0xf,0xd5,0x7c,0xe4,0xe5,0xc6,0x19,0x87,0x20,0x88,0x5d,0x79, + 0x9e,0xdc,0x79,0x60,0xd,0x7c,0x8f,0xfe,0xbd,0xa6,0x33,0x1e,0x56,0x8a,0xea,0x12, + 0xb2,0xac,0x7d,0xdc,0x9e,0x1,0x65,0x88,0xea,0x65,0xa1,0xc8,0x5e,0xb8,0x89,0x61, + 0xcf,0x18,0x77,0xc1,0xae,0x7e,0xfd,0xcc,0x7a,0xe1,0x7d,0x37,0x16,0x99,0x7f,0x77, + 0x69,0x4a,0xb,0x33,0x55,0x62,0x33,0xc8,0xdc,0xdc,0xc9,0xb5,0x2e,0x57,0x7e,0xdd, + 0xce,0x91,0xdb,0x54,0x9e,0xbd,0xa6,0xdd,0x98,0xd1,0x10,0x55,0xbe,0xdc,0xae,0x7c, + 0xfd,0x68,0xbd,0xf2,0xf5,0xa3,0x35,0xfb,0x60,0x7b,0xaa,0x30,0x50,0x32,0xf0,0x8b, + 0xf9,0xd8,0x43,0xc1,0x30,0xce,0x1e,0x5d,0x90,0xea,0x1e,0x29,0x9d,0x54,0x29,0xba, + 0x9b,0x9d,0x7f,0xdf,0x8d,0xe5,0xca,0xd7,0x8f,0x56,0x4b,0x5c,0x7f,0x4,0x6,0x1, + 0x3d,0x5b,0xd6,0x7b,0x2a,0x10,0x46,0xc3,0x95,0xaf,0x1f,0xad,0xe7,0xdf,0x77,0x63, + 0x69,0xef,0xd1,0xde,0x7f,0xd6,0xb1,0x69,0xf7,0xfb,0xc2,0xfb,0x6e,0x2c,0x57,0x9e, + 0x3e,0x5a,0x85,0x65,0x30,0x59,0xeb,0xbc,0x86,0xbb,0xa7,0x76,0x74,0x76,0xe3,0xce, + 0x45,0x58,0xdf,0x40,0xc6,0xcb,0x78,0x30,0x9b,0xe0,0x59,0xc1,0xd5,0xa7,0x8f,0xd6, + 0xab,0x4f,0x1f,0xad,0xfd,0x59,0xa5,0x75,0x3f,0x96,0xf4,0xd5,0xaf,0x1f,0xad,0xe7, + 0xdf,0x7b,0xa3,0x8b,0x30,0xc1,0x61,0x17,0xde,0x7b,0x63,0x39,0xff,0xbe,0x1b,0xb, + 0xe3,0x71,0x2f,0xbc,0xef,0xc6,0x72,0xf5,0xe9,0xb3,0xab,0xa8,0xc2,0x19,0xf6,0x7b, + 0xd0,0x9f,0x3,0x9,0xb6,0x72,0xb1,0xcf,0x37,0x7a,0x86,0x45,0xc1,0x18,0x3f,0xca, + 0x3e,0x74,0xe5,0x1d,0xb3,0xa8,0xca,0xd5,0xa7,0xeb,0x75,0x1b,0x39,0x29,0xb6,0xbd, + 0x1,0xed,0x1c,0xd,0x7e,0xf4,0xf0,0x20,0x38,0xff,0xbe,0xeb,0xcb,0xd5,0xaf,0x9f, + 0x5d,0xaf,0x7e,0xfd,0x68,0xec,0xc3,0xfa,0xe5,0x3c,0x3a,0x92,0x41,0xcf,0x23,0x46, + 0x39,0x9d,0x7f,0xef,0xf5,0xe5,0xca,0xd7,0x8f,0x56,0x84,0xbd,0xd0,0xaa,0xcd,0x2b, + 0x4f,0x9f,0x5d,0xcf,0xbf,0xf7,0xfa,0x22,0x3a,0x19,0xd4,0xd5,0xc8,0x9d,0x1,0xad, + 0x46,0x79,0xee,0x1d,0xf7,0x13,0x3b,0xc7,0xf9,0x84,0xf5,0x30,0xe,0x3f,0xf,0x7c, + 0x70,0xad,0x66,0x93,0x16,0x4a,0x54,0x8,0x9d,0xe1,0xa0,0x8,0xa1,0x1f,0xb9,0x75, + 0x33,0x26,0xc6,0xa1,0x4e,0xa5,0x4d,0x3a,0x2b,0x66,0x99,0xa1,0xf0,0xd6,0x5e,0x6a, + 0x25,0x55,0xf6,0x57,0x9f,0x3e,0xb7,0xdf,0xf7,0x49,0x1f,0xd3,0x42,0x47,0xa6,0x5d, + 0xff,0xd5,0xa7,0xcf,0xae,0x17,0xea,0x9a,0x3a,0xb9,0xd5,0xc,0x61,0x23,0x85,0x36, + 0x87,0xd9,0xb6,0x69,0x39,0xbf,0x31,0x3f,0xae,0xbe,0xfb,0xc6,0x73,0x52,0x9e,0x61, + 0x74,0x51,0x2,0x6,0xd7,0xf9,0x58,0x9b,0xfd,0xfd,0x4c,0xad,0x42,0x6b,0xdb,0xf0, + 0xea,0xd3,0x67,0xd6,0x61,0x86,0x32,0xe8,0x6f,0xdb,0x16,0x9f,0xdf,0xbe,0xc8,0xda, + 0xcf,0xdb,0x7b,0x5e,0x7d,0xfa,0xcc,0xa,0xf6,0xa0,0xed,0x9b,0x64,0xf0,0x78,0xb7, + 0x2d,0xd3,0x24,0x44,0x85,0xbd,0xdf,0x13,0xfe,0xae,0x90,0x3f,0x77,0x27,0xb6,0xfe, + 0x7e,0xae,0xf7,0xa5,0x5e,0xe3,0x46,0x1c,0xdd,0x6d,0x53,0x9a,0xd4,0x90,0x30,0xac, + 0xaf,0x73,0xb,0x42,0x2f,0xfb,0x7b,0x9f,0x7d,0xcf,0xcd,0xe5,0xda,0xd3,0xfb,0x1, + 0x74,0xee,0xbd,0x37,0x96,0x8d,0x78,0xb8,0xdb,0x96,0x1a,0xd1,0x41,0xc0,0x87,0x94, + 0x95,0xd8,0x7b,0x7b,0x32,0x18,0xed,0x46,0x66,0x51,0xcf,0x99,0x7a,0x61,0xdb,0x16, + 0x71,0x73,0xfb,0xf5,0xf2,0xf3,0xd9,0xba,0x62,0x54,0xfb,0xfe,0xfb,0x35,0xf1,0x7d, + 0x4,0x87,0x43,0xa,0xae,0x1b,0xb1,0x1f,0xda,0x72,0x93,0xb5,0xd6,0x4d,0x6b,0xf4, + 0xf9,0x5b,0x62,0x89,0x1e,0xf0,0x4f,0x71,0xbe,0xa6,0xb2,0xff,0xbe,0xfa,0xc5,0xe8, + 0xf7,0xe4,0xf5,0xef,0x7c,0xbf,0x8b,0xe8,0x95,0x6f,0x1b,0x77,0x3d,0xdc,0xa2,0x21, + 0xd0,0x35,0xa,0xa2,0x9d,0x6d,0x1e,0xf6,0xc4,0xd9,0xf7,0xdc,0x58,0xae,0x3d,0x7d, + 0xb4,0xb6,0xdb,0xbd,0x6d,0x39,0xd1,0xe6,0xfb,0x29,0x9f,0x5b,0xaf,0x19,0x30,0xbb, + 0xf6,0xe7,0x47,0xeb,0xb9,0xf7,0xec,0x9b,0xbc,0x7d,0xee,0xb9,0xf7,0x5c,0x5f,0x5e, + 0xff,0xe6,0xd1,0xba,0x6d,0x62,0xd4,0x34,0xf6,0x3f,0x60,0xe7,0xde,0x7d,0xbd,0xaf, + 0xb3,0xfd,0x75,0xaa,0xaf,0xde,0xee,0x79,0x5b,0x4b,0x7c,0x7e,0xb4,0xb8,0xb3,0xb1, + 0x46,0x35,0x9d,0x15,0xde,0x5e,0x67,0xea,0x84,0x6,0x52,0x1e,0x13,0xda,0xab,0x85, + 0xfb,0xdd,0x82,0xa3,0xeb,0x1a,0x33,0xc0,0xce,0xbe,0xfb,0xfa,0x72,0xed,0xe9,0xb3, + 0xab,0xc3,0xec,0xdc,0x7b,0xae,0x2f,0xd7,0xbf,0x79,0x76,0xb5,0x70,0x36,0x80,0x9c, + 0xa9,0xf4,0x59,0x8d,0x56,0xf5,0xb6,0xa9,0xa7,0xc5,0xb9,0x77,0x5f,0x5f,0x5a,0xb2, + 0xbd,0xbf,0x27,0xaf,0x7f,0x95,0x9c,0xe6,0xeb,0x94,0xbf,0x1b,0x44,0xff,0x7c,0xdb, + 0xe6,0x8d,0xc3,0x76,0x56,0x18,0xf2,0x59,0xd1,0xf6,0x33,0xff,0xec,0xda,0x9f,0x9f, + 0x5d,0xf9,0x3d,0xb6,0x6d,0x4e,0xfc,0xde,0xb6,0x8c,0x9,0xd8,0xa8,0xe3,0xb9,0x6d, + 0x26,0x95,0x68,0xbb,0x37,0x7a,0xae,0x8c,0x9f,0x95,0xfe,0xfb,0x63,0x3d,0x42,0x79, + 0xca,0x61,0x4f,0x82,0x62,0xc,0xff,0xb4,0xd8,0xd9,0x77,0xbf,0xbe,0x5c,0xfb,0xf3, + 0x73,0xab,0xb5,0x67,0xc2,0x2d,0x7f,0x7,0x3d,0x37,0x13,0xbd,0xfe,0x2d,0xfa,0xd, + 0x84,0x3d,0xdb,0xe2,0xc7,0x46,0x9d,0x1d,0xf9,0xfc,0x34,0xde,0x1c,0x31,0x1,0xfd, + 0x73,0xa9,0x2b,0xe8,0x3e,0xcc,0xb4,0x90,0x83,0xeb,0x46,0x1e,0x24,0xed,0x7e,0x74, + 0xed,0x75,0xf,0xbe,0x2,0x74,0xd1,0x1c,0x57,0xdb,0xe7,0x8f,0x7b,0x8b,0x2e,0x9c, + 0xd5,0xf6,0xcb,0x46,0xba,0xfd,0xe,0xfd,0x5d,0x0,0x56,0x18,0x71,0x3a,0xe6,0x4b, + 0x34,0xef,0x41,0xe6,0x19,0x1b,0xbf,0xc6,0x95,0xd6,0xa4,0x7a,0xe5,0xec,0x86,0x45, + 0xdc,0x69,0xa9,0x42,0x8c,0xac,0x16,0xb3,0x9b,0x9a,0xb1,0xec,0x2c,0x55,0xee,0xc2, + 0x88,0x4f,0x8e,0x49,0xc1,0x65,0x3a,0x30,0x78,0xf8,0xfb,0x20,0xc8,0x74,0x5a,0xe4, + 0x13,0x17,0x48,0x95,0xac,0xfa,0xbd,0x3a,0x73,0x85,0x5,0xff,0xed,0x9,0xc7,0x98, + 0x3b,0xf,0x2c,0xec,0x71,0xf6,0xdd,0x37,0x96,0xd7,0xbf,0x71,0xb4,0x36,0x66,0x80, + 0x9b,0xbd,0xf5,0xcc,0x8a,0x90,0xa5,0xd7,0xbf,0x71,0xb4,0xbe,0xfe,0xcd,0xa3,0x55, + 0x2d,0x1b,0xf9,0x2f,0x85,0x2a,0xd8,0x32,0x5,0x2d,0x47,0x65,0x32,0x16,0x58,0xf1, + 0xd0,0x22,0x17,0x9e,0x79,0x98,0x7d,0xb7,0xff,0xbf,0xfe,0x8d,0xa3,0xf5,0xe8,0xdd, + 0x37,0x97,0xa3,0x77,0xdf,0x58,0xae,0x7f,0xe3,0x6c,0xf,0x50,0x8c,0xc5,0x90,0x39, + 0xb8,0x29,0x62,0xd4,0x44,0x6a,0x52,0x91,0xa3,0x7c,0x7f,0xce,0xbe,0xfb,0xc6,0x72, + 0xfd,0x1b,0x47,0xab,0x73,0xe2,0x21,0x60,0x25,0x4c,0x50,0xbc,0x34,0x67,0xb,0x15, + 0x95,0x9b,0x22,0x88,0xf3,0x8c,0x18,0xea,0x21,0x40,0x6a,0x60,0xce,0x3d,0x58,0xa1, + 0xaa,0x4,0x49,0x54,0x51,0xdc,0xc2,0x9c,0x8f,0xdb,0x40,0xa5,0xa4,0xc,0x7,0xaa, + 0x34,0x38,0xc1,0x72,0x4a,0x58,0xe3,0xba,0x8b,0xa,0x6d,0x67,0xdf,0x75,0x63,0xf, + 0x76,0xa1,0x9d,0x98,0xb8,0xbe,0xd0,0xaa,0x1b,0xc4,0x8,0x89,0x15,0x3a,0x98,0x65, + 0x11,0x79,0xb8,0xf5,0xff,0xaf,0x7f,0xf3,0xec,0x7a,0xf6,0x5d,0xd7,0x17,0xf7,0xc3, + 0x74,0xb8,0x43,0xe,0x75,0x71,0xbd,0x47,0xef,0x82,0xa3,0x77,0xd5,0x0,0x4e,0xbc, + 0xe8,0xa3,0x27,0xae,0x2f,0x47,0xed,0xf3,0xa4,0x6a,0x8a,0x8c,0x12,0x4b,0xdc,0xec, + 0xf6,0xd7,0xb3,0xef,0xba,0xbe,0x5c,0xff,0xd6,0xd9,0xf5,0xf5,0x6f,0x9c,0x9d,0x76, + 0x3c,0x10,0xd5,0xf9,0x82,0xd2,0x17,0xaf,0x19,0xee,0xc4,0x5c,0xff,0xe6,0xb9,0xf5, + 0xe8,0x5d,0x37,0x96,0x61,0xa7,0x81,0xfc,0xf9,0x36,0xab,0x12,0x3,0x93,0x3,0xb9, + 0x63,0x1a,0xef,0x63,0xbb,0x37,0x91,0xe7,0xcd,0x1d,0x26,0x27,0x4d,0xd3,0xa3,0x77, + 0x5d,0x5f,0xae,0x7f,0xeb,0xdc,0x6a,0x66,0x76,0xe3,0x5b,0xe7,0xd6,0xa3,0x77,0x5d, + 0xef,0xdd,0x9f,0xfe,0x5e,0x41,0x9b,0x61,0x9c,0xc9,0xae,0xbc,0x6e,0x62,0x5d,0x1c, + 0x3d,0xf1,0xfa,0x72,0xe3,0x5b,0xe1,0x3e,0x62,0xac,0x3b,0xb,0x5d,0x18,0x8b,0x9d, + 0x9f,0x60,0xfa,0x34,0x53,0x90,0xd4,0x9f,0xfb,0xe8,0xa,0x30,0x43,0xc7,0x10,0x18, + 0x21,0x15,0x34,0x7,0xdb,0x9f,0xcb,0x13,0xd7,0x97,0x84,0xdc,0xa7,0xa2,0x6b,0xac, + 0x1f,0x2,0x28,0xba,0x6a,0xf8,0x73,0xa7,0x4e,0x46,0x72,0x91,0x25,0xd2,0xf6,0x4a, + 0x60,0x8a,0xf0,0xd9,0xea,0x61,0xee,0x29,0xac,0x16,0xee,0x47,0xd6,0xcf,0x3f,0x79, + 0xe3,0x9b,0xb5,0xed,0xb2,0x8d,0x8a,0xe2,0xcc,0x13,0xfb,0x42,0xe6,0x42,0xd2,0xb7, + 0x1,0xe3,0xe8,0xa2,0xfd,0x9b,0x87,0xd6,0x73,0xcb,0x62,0x68,0xe5,0x14,0x3a,0x78, + 0x6a,0xf6,0x73,0xe6,0x89,0xeb,0xcb,0x8d,0x6f,0x9e,0x5d,0x59,0xb3,0xd9,0xcd,0x62, + 0x24,0x4b,0x4,0xfe,0xb6,0x20,0x9a,0xed,0x5e,0xef,0x44,0x6d,0x6e,0x47,0x4f,0xdc, + 0x58,0x6e,0x7c,0xeb,0xec,0xca,0xd9,0x3d,0xe8,0xa9,0xf4,0x36,0x32,0xfd,0xce,0x58, + 0x4,0x18,0xea,0x5f,0x3e,0xee,0xc1,0x8d,0x6f,0x9e,0x5d,0x7,0x72,0x9c,0xf4,0xc6, + 0x37,0x4f,0xe7,0xd1,0xb8,0x7f,0xfb,0xbf,0xdf,0xf8,0xf6,0xd9,0xf5,0xe8,0x89,0xeb, + 0xcb,0xcd,0x6f,0x9f,0x5d,0x7d,0xf3,0x81,0x89,0xd8,0x86,0xe4,0xfe,0xd1,0x13,0xaf, + 0x2f,0x66,0x66,0xfd,0x35,0x16,0xbc,0x94,0xea,0x8d,0xb9,0xfe,0xcd,0xa3,0x71,0x1d, + 0x70,0xbb,0xfe,0xad,0xa3,0x75,0x14,0x82,0xe4,0xf6,0x14,0x14,0x36,0x5c,0x12,0x2a, + 0x9f,0x54,0xef,0xae,0x6e,0x68,0xbd,0xcd,0x45,0x4f,0xd9,0x65,0xb0,0x50,0xf5,0x9, + 0xd4,0x7d,0x69,0xe0,0x3,0x5c,0xaa,0xab,0xf6,0x77,0xc6,0x1b,0x5c,0xff,0xd6,0xd9, + 0xf5,0xe8,0x89,0xd7,0x97,0x9b,0xdf,0x39,0xb7,0x32,0xb5,0x0,0xd4,0xe7,0x1a,0xf7, + 0x9a,0xda,0x86,0xdb,0xa8,0xe6,0xce,0x3c,0x5e,0xef,0xdb,0x77,0xce,0xad,0xfb,0x67, + 0x20,0xa1,0xaf,0xe1,0x10,0x1d,0xeb,0xd0,0x20,0xa3,0x6b,0x73,0x79,0x6f,0xf1,0x48, + 0xda,0x46,0xfb,0xa8,0x7f,0xe,0xe8,0xe7,0xf1,0x40,0xdf,0x2,0x67,0x79,0xa6,0xf8, + 0x74,0xe0,0x4f,0xbc,0xae,0x74,0x5e,0xea,0x49,0x3f,0x7d,0x5c,0x3b,0x64,0x2d,0x9f, + 0x79,0xfc,0xf5,0xe5,0x46,0x3d,0x8c,0xf5,0xfd,0xac,0xaf,0xe1,0xc0,0x5c,0xa3,0xf9, + 0xbd,0xeb,0xe7,0x39,0x3d,0x7,0x70,0x9f,0x92,0xd3,0xe2,0x32,0xd6,0xf3,0xe6,0xa4, + 0x5e,0xe6,0x52,0x3e,0xd,0x37,0x29,0xcf,0x94,0xc8,0x78,0x2d,0xd5,0xc6,0x97,0x1, + 0x3f,0xf1,0xf7,0x7a,0x72,0xbf,0xf9,0xb8,0x1f,0x54,0xf5,0xdc,0xf8,0xd6,0xd9,0x55, + 0x11,0x4c,0xfc,0x8c,0xe7,0x6b,0xb5,0x9d,0x94,0x72,0x2e,0x6c,0xc3,0xe5,0x8a,0x9f, + 0xed,0xd8,0xc3,0x34,0x2b,0x85,0xcb,0xf3,0x3b,0xf3,0xd8,0xb5,0xe5,0xc6,0xb7,0xce, + 0xaf,0x23,0x2b,0x83,0x3a,0xb9,0x6d,0x3,0xe1,0x3e,0x8c,0x6,0x61,0x7c,0xe,0xf0, + 0xb5,0x98,0xb9,0x9d,0x79,0xec,0xf5,0xe5,0xc6,0xb7,0xcf,0xaf,0xc6,0x14,0x2e,0x72, + 0x4f,0xdb,0xcf,0x19,0x75,0xbc,0xe3,0xe7,0xda,0xec,0x56,0xf9,0xe7,0xb2,0x9e,0xeb, + 0xf7,0xef,0xb4,0xb9,0xf6,0x5d,0x1d,0xb4,0x7e,0x40,0xd7,0x5f,0xbf,0x27,0x5d,0x13, + 0xaf,0x3d,0xee,0x4c,0xc8,0x75,0xb0,0xbb,0xdc,0x46,0x31,0x65,0x53,0x5b,0x9d,0xd3, + 0x8f,0x5f,0x5b,0x6e,0x7c,0xfb,0xdc,0x9a,0x19,0x84,0xba,0x7,0x3c,0xad,0xf1,0x51, + 0x68,0xdc,0xfc,0xf6,0xb9,0xf5,0xcc,0x63,0xd7,0x96,0x5b,0xdf,0x39,0x2f,0xe7,0xf0, + 0xc0,0x25,0xe8,0xf9,0xd1,0xd6,0x49,0xfb,0x7e,0x51,0x89,0x7c,0x8c,0x58,0xb4,0xc3, + 0x36,0x3b,0xe3,0x6d,0x42,0xd7,0x16,0xe6,0xad,0x9b,0xec,0xef,0xb8,0x97,0x4e,0x3f, + 0x76,0x6d,0x3f,0xe7,0x9e,0x39,0xbf,0x82,0x62,0xae,0x0,0x4,0x6d,0x9c,0x3d,0xde, + 0x71,0xef,0x9c,0x1d,0x98,0xea,0xea,0x3a,0xc9,0x8e,0x5a,0x45,0xb5,0x3,0xc1,0xb5, + 0x4a,0x0,0x5e,0xb0,0x33,0x8f,0x5f,0x5f,0xce,0x3c,0x7e,0x7d,0x39,0xfd,0xd8,0xf5, + 0x45,0xc6,0x33,0x6e,0x76,0xfa,0xf1,0xeb,0xcb,0xcd,0xef,0xd4,0xc0,0xeb,0x96,0xb5, + 0x78,0x3,0xd7,0xcc,0xdd,0x72,0x59,0x6a,0xc1,0xe0,0x85,0x50,0xcb,0xad,0xf5,0xa3, + 0x6d,0xd7,0x71,0x6d,0xed,0x56,0xdc,0xfc,0xf6,0xd9,0xf5,0xf4,0x63,0xd7,0x17,0x76, + 0xfa,0x3d,0xf3,0xd8,0xf5,0xe5,0xf4,0xe3,0x75,0x6e,0x24,0xf3,0x2f,0x97,0xea,0x2b, + 0x3a,0x99,0xf5,0x39,0x6e,0x33,0xbe,0xf7,0x10,0xec,0x68,0x7e,0x79,0xf3,0xdb,0xe7, + 0xd6,0xd3,0x8f,0x5f,0x5f,0x58,0x83,0x5c,0x54,0xaa,0x3c,0x97,0xcf,0x2c,0x19,0x18, + 0x69,0x2b,0xd1,0xc,0x2e,0x4d,0x76,0x83,0xf,0xe9,0x18,0x13,0x18,0xd1,0xfc,0xa2, + 0xc4,0x61,0x18,0xb,0xf0,0x46,0x8d,0x15,0x53,0xe0,0x8f,0x4f,0xb1,0x4,0xf1,0xec, + 0x3e,0x34,0x9f,0x42,0xa9,0xeb,0x83,0x83,0xbd,0x4d,0xbb,0x1c,0xd2,0x95,0x29,0x76, + 0xc0,0x29,0x63,0x96,0x18,0x46,0xde,0x6e,0x51,0x6d,0x0,0x20,0x75,0x1c,0x9a,0xfe, + 0x3f,0x92,0x6b,0x9d,0xfd,0x57,0xcc,0xf5,0xaa,0x7e,0xd3,0x8c,0xf3,0x15,0xbe,0xff, + 0x4c,0xcb,0xf9,0xd6,0x77,0xce,0xaf,0xa7,0x1f,0x7b,0x7d,0x61,0x36,0x82,0xfa,0x1f, + 0xec,0x9f,0x7b,0xfa,0xb1,0xd7,0x97,0x9b,0xcf,0x9c,0x5f,0xed,0x80,0x62,0xa1,0x1, + 0x76,0xf3,0x3b,0xe7,0xd7,0x5b,0xcf,0x9c,0x5f,0x95,0xf4,0xe1,0x72,0x3f,0x66,0xda, + 0xb,0xc,0xde,0x64,0xd3,0x8e,0x53,0x8f,0x5d,0x5b,0x6e,0x3e,0x73,0x6e,0x45,0xa8, + 0x68,0xa4,0xad,0x48,0x3c,0xe1,0xac,0xe9,0x3f,0xf7,0x37,0x70,0x11,0x8a,0xf1,0xa4, + 0xa0,0xe5,0x96,0xd1,0xd1,0x5d,0x9a,0x93,0xab,0xaf,0xc0,0x5f,0xee,0x1a,0xe,0xae, + 0x7b,0x98,0x7,0x40,0x8c,0x14,0x67,0xf4,0x76,0xdb,0xd3,0xa7,0x1f,0xbb,0xb6,0xdc, + 0x7c,0xe6,0x7c,0xaf,0x78,0x51,0x37,0x44,0x7b,0xe,0x37,0x9f,0x39,0xbf,0x9e,0x7e, + 0xec,0xda,0xa2,0x1c,0x77,0xd6,0x34,0xa7,0xe,0xa5,0x8f,0xaa,0xf,0xcc,0x50,0x48, + 0xba,0x8,0x66,0xa7,0x1f,0x7d,0x7d,0xe9,0xcf,0x8e,0xf9,0xcf,0x30,0x59,0x7,0x6e, + 0x21,0x51,0xab,0xd7,0x71,0xf3,0x99,0xf3,0xeb,0xa9,0x47,0xaf,0x2d,0xe2,0xfd,0x0, + 0xe5,0x91,0x9f,0x7e,0xf4,0x9a,0xae,0x21,0x1b,0xdf,0xe7,0xf4,0xa3,0xd7,0xf6,0xcf, + 0xaf,0x5d,0xbe,0x29,0xbb,0x21,0x11,0xf,0xf6,0x37,0x39,0x55,0xdf,0xd7,0xd,0x72, + 0x1d,0x6d,0x5f,0x79,0xd9,0x9f,0xd1,0xcd,0x67,0x2e,0xac,0xa7,0x1f,0xbd,0x26,0xa, + 0x8d,0x6a,0x87,0x3c,0x40,0x7d,0x37,0x9f,0x39,0xbf,0x9e,0x7e,0xf4,0xda,0x12,0x37, + 0x7c,0x2b,0xf8,0x24,0x0,0xfb,0xbe,0x56,0x6f,0x3d,0x73,0x61,0x15,0x25,0xfd,0xa2, + 0xb9,0x65,0xbb,0xbe,0xd3,0x8f,0xd6,0xe7,0x67,0x59,0xb6,0x37,0xa9,0x7c,0x3a,0x75, + 0x65,0x83,0x9e,0x8,0x2b,0x0,0x26,0x1,0x22,0x57,0x57,0x36,0xee,0x8a,0xbb,0xc7, + 0xce,0xd4,0xfe,0x7b,0xa7,0x1f,0xb9,0xb6,0xdc,0x7a,0xf6,0xc2,0xca,0x7e,0xe8,0x8, + 0x9d,0x9d,0x62,0x88,0xe8,0xd3,0xa8,0x58,0x46,0xca,0x68,0xee,0x52,0xc5,0xf8,0x66, + 0x76,0xeb,0x99,0x73,0xeb,0xa9,0x47,0xae,0x2f,0xac,0x30,0xd6,0x7e,0x7e,0xeb,0xd9, + 0x73,0xeb,0xe9,0x47,0x6a,0xd0,0x84,0xd9,0xa9,0x47,0xaf,0x2f,0xb7,0x9e,0x39,0xb7, + 0xaa,0x24,0x1e,0x5,0xd,0xe8,0x9c,0x5b,0xb4,0x7d,0xa1,0x96,0x92,0xce,0xc2,0x3, + 0x49,0xd9,0x4a,0x81,0x3,0x59,0x94,0xc1,0x93,0xba,0xda,0xa9,0x47,0xf6,0x6b,0x8b, + 0x9c,0xe6,0xf6,0x79,0xed,0x7b,0x1e,0xf2,0xc7,0x8e,0xee,0x62,0xed,0x7f,0xdb,0xfb, + 0xa,0xc0,0x2c,0x28,0x16,0x29,0x4a,0x3e,0xfc,0x6f,0xa1,0x4e,0xc7,0x5b,0x82,0x34, + 0x2c,0x20,0x30,0x67,0xad,0xcd,0x92,0xf5,0x6c,0x2,0xca,0x1f,0x81,0x33,0x39,0xe4, + 0x33,0x15,0xf1,0xaf,0x5c,0x71,0x13,0x1e,0x65,0xfe,0x7b,0x56,0x48,0x9a,0x5,0x3e, + 0x46,0x2f,0x8b,0x59,0xc2,0x5b,0x28,0xe1,0xb1,0x82,0x5c,0x46,0x3e,0x86,0xd4,0x3a, + 0xb9,0x31,0xd9,0x40,0x9a,0x72,0x12,0x5b,0x3f,0xfa,0xd6,0x33,0xe7,0xd7,0x5b,0xcf, + 0x9e,0x5f,0xe1,0xb0,0xe3,0x67,0xcf,0xaf,0x77,0x3f,0xb2,0x1f,0x20,0x82,0x66,0x26, + 0x5e,0x6d,0xf6,0x5,0x47,0xf2,0xa4,0x57,0xf1,0x9e,0x11,0xb4,0x0,0xd8,0xf1,0xb3, + 0xe7,0xf6,0xcf,0x8b,0xb6,0x9c,0x1b,0x19,0x52,0xb0,0xf2,0x5e,0xdd,0x8b,0xc7,0xcf, + 0x9c,0x5f,0x6f,0x3d,0x73,0x6e,0xb5,0x60,0x80,0x73,0xfc,0x6c,0xb,0xe0,0x4e,0xad, + 0x43,0xb7,0x24,0x64,0xe4,0x7a,0x3f,0x55,0xb7,0x9f,0xd0,0xa0,0x8d,0xf,0xdd,0x66, + 0xe9,0x84,0x66,0x3f,0x7e,0xf6,0xfc,0x7a,0xea,0x91,0xd7,0xfb,0xfd,0x41,0x72,0x48, + 0xcc,0xda,0xe1,0x71,0xc4,0x16,0xc7,0x5f,0xed,0x30,0x3b,0x7e,0xf6,0xfc,0x7a,0xfc, + 0x6c,0xd,0x26,0x81,0x3,0x7f,0xf7,0xc3,0xfb,0x21,0x67,0x16,0x3c,0xc2,0x89,0xae, + 0xe5,0xf5,0x5e,0x9c,0x7a,0xf8,0xda,0xc2,0x1a,0xe,0xc9,0x36,0x9e,0x38,0xd5,0x30, + 0x5d,0xe3,0xc7,0xcf,0x9e,0x5f,0xef,0x7e,0xf8,0xda,0x40,0xdb,0x6f,0xb5,0x43,0x41, + 0xf4,0x5d,0x61,0x29,0x6c,0xfa,0xc8,0xdd,0x54,0x85,0xee,0xd6,0xb3,0xe7,0xd7,0x53, + 0x8f,0xec,0xd7,0xc3,0x1a,0xeb,0xdd,0x35,0x8d,0xae,0x51,0x78,0xd1,0x40,0x74,0x45, + 0xcd,0xe7,0x4a,0xfd,0xe0,0x53,0xf,0x5f,0x5b,0x8e,0x9f,0x6b,0xeb,0x89,0xbf,0x33, + 0x92,0xb2,0x63,0xd2,0xd6,0x37,0x4a,0x14,0xb6,0xe0,0xdd,0x8d,0x76,0x3f,0xaf,0x2e, + 0x89,0x6d,0x20,0x6c,0x16,0x53,0xd,0x7e,0x63,0xc6,0x8,0xba,0xf3,0x21,0x4b,0xaf, + 0x25,0xe,0x79,0x13,0xb6,0x41,0x10,0xa3,0x37,0xc8,0x1e,0x64,0xed,0x14,0x77,0x15, + 0x3a,0x8b,0x4a,0x74,0xe3,0x9c,0x23,0xa6,0x14,0x8d,0xc,0xd4,0x9d,0x91,0xa9,0x7b, + 0x71,0x4c,0x8,0xf1,0xab,0x60,0xd,0x14,0x68,0x1f,0x40,0x7f,0xf,0xc3,0x3b,0x23, + 0x32,0x80,0xa2,0xa2,0xdd,0xf1,0x73,0x17,0xd6,0x53,0xf,0x5f,0x5d,0xee,0x7e,0xf8, + 0xea,0x72,0xfc,0xdc,0x85,0xd5,0x42,0x1,0xed,0xe1,0x19,0x9e,0x94,0x8a,0x25,0xba, + 0xc2,0x50,0xd7,0xea,0xf8,0xb9,0x73,0xeb,0xdd,0x8f,0xbc,0xbe,0xdc,0xfe,0xee,0xb9, + 0x35,0xce,0x86,0x5d,0x31,0x2e,0x79,0xe,0x54,0x2c,0xc8,0xf3,0xc1,0xb2,0xa,0x95, + 0x72,0xc5,0x93,0x25,0xcf,0xc1,0x70,0x16,0xb9,0xcd,0xa1,0x9f,0xc7,0x32,0x4e,0xa6, + 0x2d,0xcd,0x76,0x60,0xdc,0xfd,0xc8,0xeb,0xcb,0xf1,0x73,0x7b,0xd0,0xd5,0xac,0x5f, + 0xaf,0x35,0x71,0x9b,0xb9,0xb5,0xd5,0xf9,0xa3,0x9e,0x51,0x9b,0xd2,0x2f,0xb4,0xa9, + 0x5e,0x73,0xd2,0x6e,0x96,0x2e,0x63,0xb0,0x44,0xea,0x7d,0xba,0xc9,0x98,0x82,0x5f, + 0x1a,0xf2,0x38,0xe7,0xd1,0x83,0x79,0x50,0x5d,0x73,0x5a,0xdf,0xad,0x82,0xf7,0xc4, + 0x81,0x8f,0xdc,0x57,0xbe,0xa7,0xb7,0x9f,0x3b,0xd7,0xf,0x5d,0x24,0x24,0xf8,0x0, + 0xba,0xb1,0x1a,0x96,0xb4,0xb8,0x9,0x9f,0xe0,0x50,0xcc,0x82,0x93,0xbe,0xc5,0xb4, + 0x1a,0x24,0xa1,0x23,0xd6,0x21,0x77,0x79,0xf6,0xde,0xc7,0x2e,0xdd,0x75,0xc9,0x22, + 0x17,0xd7,0x33,0x9b,0x3,0x1,0xa1,0xed,0x66,0xb7,0xbf,0x77,0x7e,0xbd,0xfb,0xa1, + 0x6b,0xcb,0xed,0xef,0x9d,0x5f,0xe1,0xf9,0xda,0x7,0x98,0x2c,0x3b,0x4e,0x7b,0x40, + 0x80,0xd3,0xd4,0x5d,0xdb,0x68,0x88,0x7e,0x5,0x66,0x77,0x3f,0x74,0x6d,0xb9,0xfd, + 0xdd,0xf3,0xab,0x78,0xf,0x98,0x7a,0x54,0x8b,0x98,0x6a,0xc5,0x50,0xb0,0x99,0x4c, + 0x7f,0x5f,0x54,0xf4,0x63,0x31,0x3b,0xfe,0xee,0xfe,0x7d,0x98,0xab,0x2b,0x6a,0x59, + 0xce,0x3,0xa1,0xbc,0x66,0x3d,0x9c,0x7,0xd,0xb0,0x3,0xd7,0x3d,0x32,0xba,0x16, + 0x4e,0x77,0xdb,0xe5,0x1e,0x38,0x6,0xc2,0xbc,0xe3,0x1c,0xa4,0xd5,0x1f,0xbc,0xc7, + 0x65,0x4c,0x14,0xc0,0x93,0x3,0x9a,0x64,0xf9,0xbb,0x99,0xaa,0x43,0x6,0xf,0x6, + 0xa9,0xd6,0x27,0x9c,0x6f,0xa7,0xea,0x7f,0x7f,0x2e,0x17,0xa4,0x5b,0xe1,0x9d,0x31, + 0x62,0x92,0xd8,0xb1,0xe3,0x17,0x8b,0x6f,0x99,0xbb,0x74,0x12,0xda,0x9f,0xdf,0xf9, + 0xe0,0xd5,0xe5,0xf6,0xf7,0x2e,0xac,0x16,0xe0,0xac,0x8,0xe3,0xa,0xc1,0x5f,0xc8, + 0x75,0xc4,0x4e,0x6,0x75,0x34,0xad,0x5d,0xff,0xfe,0x19,0xa2,0x1b,0x52,0xbf,0xe3, + 0xed,0xef,0x5e,0x58,0xd5,0xbe,0x38,0x62,0x4,0x7c,0xea,0xd3,0xc1,0xfb,0x55,0xce, + 0x9f,0xf8,0x1c,0x90,0x9f,0x8b,0x47,0x0,0x19,0x32,0xb3,0x98,0xef,0x95,0xc1,0xec, + 0x9d,0x97,0xaf,0xed,0xdf,0x21,0x64,0x52,0x1e,0x12,0x75,0xc6,0x16,0x39,0xdb,0x7f, + 0x47,0xcc,0x13,0xe6,0x7b,0x36,0xee,0x67,0xf0,0x99,0x6,0x23,0xfc,0x99,0x1e,0xff, + 0x7d,0x8f,0x8f,0x19,0xa9,0xf0,0xdd,0x63,0xdc,0x68,0xff,0x7b,0xfb,0x7b,0x17,0xd7, + 0xe,0x2a,0x9f,0x8c,0xa9,0xbc,0x63,0xe0,0x60,0x27,0x99,0xf,0x27,0xd9,0x9b,0x59, + 0x80,0x9f,0xdb,0xd4,0xbf,0xd5,0x2c,0x3b,0x33,0x39,0x21,0xfe,0x66,0x95,0xab,0xce, + 0xef,0x74,0xde,0xa6,0xe2,0xed,0x9e,0xe3,0x3f,0xcf,0xdc,0xeb,0x7f,0xdf,0xfe,0x6e, + 0x9b,0xe1,0xf8,0x8,0x62,0x8e,0xd4,0xd5,0x94,0x20,0xe2,0x51,0x5,0x8c,0xae,0xd1, + 0x55,0xc7,0x9d,0x33,0xe0,0x77,0x5e,0x7e,0xbd,0x1e,0xa8,0x3e,0x6c,0x2,0x6d,0x28, + 0xb3,0x71,0x95,0xe9,0x9b,0xa5,0x99,0x68,0xbf,0xd7,0x98,0x54,0xf5,0xa1,0x9b,0xe0, + 0xd0,0x60,0xe3,0x93,0x7b,0x7,0xcf,0x4a,0x97,0x30,0x13,0xd0,0xc7,0x30,0xed,0x8, + 0xa,0xe,0xfc,0x3b,0xc8,0xad,0xcc,0x7e,0x98,0x72,0xb2,0x66,0x59,0xe5,0x2c,0x44, + 0xf,0xcd,0x5a,0xe9,0xbd,0xf9,0xf7,0x1d,0x50,0x94,0x7b,0x58,0x53,0x2c,0x60,0x3a, + 0x2a,0x17,0x24,0x67,0x29,0x79,0x7d,0xfb,0xe,0xa5,0x72,0x58,0xcd,0xa5,0xcb,0xc2, + 0x94,0x32,0xe6,0x6e,0xb2,0xb2,0x93,0x9a,0xde,0xf2,0xba,0x9,0x19,0x34,0x3b,0x7e, + 0xb1,0x86,0x7d,0xbb,0xe7,0x65,0x34,0x9e,0x44,0x16,0x35,0x5,0x5c,0x1a,0xeb,0xb0, + 0xfb,0x1e,0x7,0x3a,0xe2,0x23,0xf7,0xb5,0x55,0x9f,0x3d,0x83,0x4d,0x39,0x71,0x85, + 0x8c,0x58,0xa8,0x62,0x76,0xf5,0x73,0x6b,0x8,0xde,0xd4,0x5,0x71,0x88,0xf3,0x93, + 0x1e,0x68,0xb0,0x77,0x3e,0x70,0x75,0xb9,0xf3,0xbd,0xb,0x7d,0xdf,0x75,0x97,0x41, + 0xe6,0xec,0x4b,0x72,0xe4,0x53,0x25,0xc4,0xc6,0x84,0x41,0x46,0x2c,0x9a,0x84,0x53, + 0x4e,0x92,0xea,0x3d,0xba,0xf3,0xfc,0xf9,0x95,0xf5,0xfd,0x95,0x42,0x49,0xde,0xdb, + 0xee,0xaa,0x57,0xe1,0x2e,0x67,0x91,0xd0,0x4a,0x19,0x45,0x1c,0xf6,0x64,0x56,0x20, + 0x53,0xfe,0xb8,0xc7,0x75,0x3f,0xb,0x22,0x41,0x73,0xfc,0xae,0xcb,0x57,0x3b,0x8a, + 0xfe,0x8d,0x17,0x2f,0xac,0x49,0x9d,0x32,0x9c,0x13,0xe6,0xc1,0xe9,0xd3,0x2,0x87, + 0xdd,0xf4,0xf7,0x9d,0xac,0x53,0xf3,0x7b,0xef,0x9,0xdd,0x9d,0xe7,0x2f,0xae,0x8c, + 0x86,0x75,0xcb,0xd2,0x1c,0x51,0x6e,0x4a,0xcf,0x48,0x35,0xed,0x2,0xd4,0xa7,0x5b, + 0xf6,0x17,0x7b,0x85,0x5b,0xf8,0xb3,0xcd,0x78,0xfc,0xc3,0xe5,0x2c,0xea,0x3b,0xb4, + 0xcf,0xbf,0xeb,0xf2,0xd5,0xc5,0xcc,0xec,0xce,0xb,0x7b,0xe0,0x93,0x1d,0x86,0xb0, + 0xee,0x52,0x93,0x3d,0x97,0x88,0x77,0x9e,0xbf,0xb0,0xc6,0xc0,0x13,0xe4,0xb5,0xb4, + 0x8b,0xd9,0xee,0x45,0x21,0x17,0xbf,0x29,0xcc,0xd3,0x53,0x9b,0x40,0x38,0xeb,0x21, + 0x6e,0x78,0x60,0x2d,0x88,0x1d,0xb7,0x4b,0x2f,0xa5,0xbf,0xcf,0x49,0xf1,0xb0,0x6e, + 0x80,0xd,0x57,0xb5,0x24,0x9f,0x71,0xfc,0xdc,0x26,0x3a,0xc2,0x8,0x15,0x3a,0x3, + 0xb3,0x59,0xb7,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xec,0xce,0xf3,0xe7,0xd7, + 0xbb,0x2e,0x5f,0xab,0x37,0xbc,0xce,0x67,0x7c,0x0,0x21,0xac,0x3,0xc,0x40,0x6d, + 0x41,0x45,0x10,0x20,0x76,0x55,0xb9,0x85,0xea,0x5c,0xc9,0xc4,0x43,0xb,0x52,0xb5, + 0x3a,0x90,0xfc,0x80,0x79,0xfe,0xed,0xf5,0x1a,0xef,0xba,0x7c,0x6d,0xa0,0x71,0xe9, + 0x34,0x16,0xa4,0x7b,0xcf,0xb4,0x28,0x43,0x8b,0xda,0xed,0x3e,0x3,0xf3,0x42,0xb8, + 0xcd,0x6f,0xd0,0xe7,0xf1,0xb5,0xb1,0xe4,0x62,0x82,0x55,0x5,0x93,0x96,0xb8,0x74, + 0xf8,0x67,0x8e,0x60,0x7e,0x81,0x99,0x89,0x26,0x13,0xf6,0x2c,0xb5,0xde,0x61,0x46, + 0xbf,0xe7,0x1,0xf1,0x3f,0x0,0x85,0x1e,0xe,0x6b,0x45,0xf9,0xba,0x24,0xc,0x30, + 0xb3,0x77,0x3c,0x70,0x6d,0x79,0xe3,0xa5,0xba,0x79,0xdc,0x15,0x69,0x4e,0x8,0x8, + 0xae,0xc6,0x1a,0xc2,0xf6,0xfb,0x2f,0x9d,0x5f,0xef,0x7a,0xe0,0xda,0xc2,0x94,0xe, + 0x18,0x12,0x80,0xcc,0x24,0x38,0xe6,0xf7,0x63,0x2f,0xf9,0x56,0xc5,0xc2,0xe9,0x1e, + 0xb9,0x1b,0x83,0x90,0xfa,0xba,0x89,0x95,0x46,0x58,0x47,0xb0,0x3,0x11,0xdc,0x7, + 0x2d,0x92,0xf2,0xaa,0x9e,0x18,0x8e,0x69,0xd3,0x78,0x97,0x37,0x5e,0x3c,0xbf,0xbe, + 0xe3,0x81,0x6b,0xcb,0xf7,0x5f,0xba,0xb0,0xf3,0xa9,0x39,0x21,0x73,0xe,0x9e,0xd, + 0xf8,0x9,0x15,0x3e,0xe2,0x3d,0xd2,0x6c,0x77,0xe1,0x16,0xad,0x8f,0x64,0x1f,0xbb, + 0x2a,0xfc,0x21,0x38,0x85,0xd,0xbf,0x74,0xad,0x68,0xef,0xba,0xff,0xea,0x72,0xe7, + 0xc5,0xb,0x53,0x2f,0x68,0xa9,0x18,0x2d,0x69,0x4d,0x75,0x60,0x64,0x92,0xe6,0x9, + 0xa3,0x34,0xcc,0xc,0x72,0x22,0x69,0x91,0x68,0x6f,0xac,0x15,0x21,0x7e,0xd8,0x13, + 0xb0,0x7d,0xd4,0xe4,0x86,0x8f,0x4,0x2a,0x75,0x1e,0x5d,0xf5,0xe7,0x67,0x74,0x26, + 0x4c,0xe9,0x69,0xfb,0x1f,0xde,0xe0,0xfb,0x64,0x66,0xef,0xb8,0xff,0xea,0x32,0x63, + 0xc7,0xf0,0x1a,0xdf,0x83,0x6,0xf1,0xa7,0x7c,0x28,0xd6,0xb9,0x67,0xad,0x8f,0xb8, + 0x1f,0xdf,0x71,0x7f,0xd,0x7e,0x2f,0x5e,0x58,0x83,0xdf,0x1e,0xed,0xa3,0x59,0x46, + 0x1b,0x6c,0xb2,0x82,0x66,0xba,0x4d,0x54,0xf1,0xb8,0x33,0x8b,0xc4,0xd9,0x46,0xfa, + 0x6e,0xb0,0x3d,0xa9,0x69,0xd7,0x38,0xee,0x8f,0x6,0xe1,0xf6,0x9f,0x37,0x5e,0xba, + 0xb8,0xde,0x75,0xff,0x95,0xe5,0x8d,0x17,0x2f,0xae,0x6c,0xba,0xc3,0x85,0x5f,0x52, + 0x15,0xc,0x49,0x66,0x2f,0x10,0x29,0x70,0x89,0x51,0x98,0x43,0x3b,0x93,0x68,0x63, + 0x0,0xef,0xcc,0x92,0xfe,0x7d,0x1d,0xf6,0x8e,0xfb,0xaf,0x2c,0x6f,0xbc,0x74,0x71, + 0xed,0x14,0x61,0x36,0x94,0x62,0x60,0xa4,0xab,0x4b,0x61,0x8c,0x1b,0xef,0xb8,0xff, + 0xea,0xf2,0xc6,0x4b,0x17,0x57,0xc5,0xde,0xaa,0x37,0x47,0x1b,0x47,0xb0,0xf2,0xe5, + 0xc9,0xa8,0x9a,0xc4,0x59,0x52,0xbc,0xd,0xc3,0xf7,0x36,0x54,0x28,0x94,0xb9,0xfe, + 0xf2,0x7d,0xd7,0x96,0x37,0x5e,0x6c,0x73,0x1b,0x1f,0x3e,0xdf,0x13,0x5a,0x58,0x2, + 0x5,0x21,0xe6,0x51,0x31,0x3b,0xb3,0xc0,0x5f,0xa5,0xac,0xa8,0xde,0x25,0x6e,0xed, + 0x72,0xa5,0x2b,0x10,0xc3,0x8e,0xd4,0x9c,0x64,0xd4,0xa9,0xea,0x2b,0xbd,0xa5,0xa7, + 0xfe,0xcd,0xda,0x76,0x9e,0x65,0xe8,0xea,0xe8,0xe6,0x9d,0xc6,0xe7,0x9b,0xd9,0x3b, + 0xda,0x7d,0x2a,0xfa,0xbe,0xa8,0x4f,0x1a,0x95,0xd6,0x31,0xb2,0x31,0x6d,0xdd,0xd, + 0xa1,0x1a,0xa7,0xb6,0x24,0x5,0x1f,0x73,0x49,0x3a,0x42,0x36,0x62,0xce,0x22,0x94, + 0xb4,0x5a,0xd1,0xe9,0x24,0x84,0xe4,0x24,0x85,0xf,0x18,0xec,0xfb,0x2f,0x5e,0x58, + 0x77,0x93,0x82,0xc1,0x6d,0xef,0xa0,0x1e,0x4e,0xa0,0xb6,0xc9,0xd8,0x83,0x2a,0x59, + 0xdf,0xcc,0xde,0x71,0xef,0xd5,0xe5,0xfb,0x2f,0x9f,0x5f,0xfb,0xb8,0x62,0x63,0x4a, + 0x96,0x56,0xd4,0x5d,0xf4,0x66,0x33,0x55,0x91,0xa,0x15,0x9f,0x85,0xb6,0xb5,0x89, + 0xa7,0xc0,0xfe,0xbf,0xdf,0x7f,0xe9,0xc2,0xfa,0x8e,0xfb,0xae,0x2e,0x3f,0x78,0x79, + 0xaf,0x8a,0x1c,0x79,0xee,0x2e,0xf3,0xe2,0x49,0x47,0xca,0x89,0x9b,0x8e,0xc9,0x3a, + 0xc2,0x44,0x67,0x21,0x6,0xa3,0xa0,0xdf,0x34,0xe1,0x66,0x31,0x56,0x40,0x15,0xa9, + 0x62,0x96,0xd7,0x9f,0x20,0x32,0x12,0x51,0x1a,0xff,0x92,0x40,0x5b,0xf7,0xac,0x8d, + 0x73,0x46,0xee,0x84,0x68,0x2a,0x1c,0xce,0x82,0x49,0x77,0x25,0x66,0x31,0xe2,0xc1, + 0x80,0x59,0xfa,0x69,0x6f,0x19,0xa0,0x67,0xf6,0x4e,0x93,0xf6,0x9d,0x3c,0xf4,0xa8, + 0xc0,0xbb,0xab,0xc5,0x29,0x66,0x20,0xbe,0x2d,0x2b,0x2e,0x46,0xbd,0xff,0xef,0xbf, + 0x74,0x61,0x4d,0x58,0x8f,0xe4,0xa,0x37,0xab,0x5c,0xed,0x40,0x8b,0x86,0x5,0xa0, + 0xcc,0xbe,0xff,0x12,0x55,0xca,0x16,0xbd,0xce,0x83,0x47,0x2c,0x74,0xad,0x22,0xa8, + 0x30,0xfe,0xf2,0xbd,0x57,0x16,0xbe,0xde,0x7d,0xcd,0x8f,0xf7,0xef,0x3e,0x16,0x3c, + 0x5a,0x50,0xb5,0xa9,0x14,0xa4,0xe3,0x81,0xca,0xe,0x7a,0xd2,0x2a,0x74,0x76,0xf, + 0xc,0xea,0x77,0x30,0xfb,0xfe,0xcb,0x17,0xd7,0x5f,0xbe,0xf7,0xca,0xf2,0x83,0x57, + 0x2e,0xae,0x3c,0x6b,0x4f,0x78,0x24,0x1c,0x96,0xa0,0x6e,0x98,0x97,0x37,0x5e,0xba, + 0xd8,0xd9,0x52,0x82,0xfe,0xaf,0x9d,0x18,0xed,0x14,0x6a,0x4d,0xbe,0x7f,0xff,0xd1, + 0x21,0x1b,0x42,0x4e,0xa,0x42,0xf6,0xc6,0xba,0x18,0xda,0x5c,0x15,0x3f,0xa1,0x5e, + 0x16,0xda,0x75,0xd,0x1d,0x55,0x68,0x61,0xea,0xf5,0xc6,0x8b,0x47,0xca,0x24,0x9e, + 0x1a,0x3f,0xa7,0x28,0xeb,0xdb,0xe3,0xdd,0xf8,0x9d,0x93,0x5a,0x7d,0x98,0x6a,0x1c, + 0xbb,0x92,0x54,0x78,0x36,0x34,0x66,0x52,0x48,0xba,0xe5,0x60,0xad,0xef,0xe4,0xda, + 0x86,0x8e,0x83,0x23,0x22,0x48,0x82,0xf5,0xf7,0x2a,0x1b,0x71,0x2e,0xac,0xd2,0x1c, + 0x70,0x6d,0x20,0x8e,0x80,0xc5,0x95,0xa5,0xb6,0xab,0xa2,0xbf,0xb2,0x87,0x59,0x34, + 0x57,0x83,0x70,0x17,0x57,0x35,0xe1,0x26,0x62,0xa8,0xaa,0x45,0x65,0xb4,0xa8,0x4c, + 0x84,0xa4,0x7f,0x9d,0xdd,0xa9,0x74,0xc0,0x69,0x42,0x13,0x4,0xfd,0x79,0xc6,0x37, + 0xef,0x73,0x5b,0xd3,0x16,0x6b,0xb,0xbc,0xa9,0xc2,0x69,0x9b,0x92,0x2,0x92,0xfe, + 0xae,0x8b,0x9b,0x5a,0x3e,0x9f,0xa2,0xb,0x95,0x8e,0xd5,0x13,0x96,0x22,0xa8,0x1d, + 0xfd,0xf2,0xbd,0x57,0x97,0x1f,0xbc,0x72,0x61,0xfd,0xa5,0x7b,0xae,0x2e,0x20,0x77, + 0x27,0x9f,0xb5,0x23,0x26,0xca,0x6e,0x1e,0x3a,0x43,0x1e,0x2a,0x8b,0x6e,0xc4,0x41, + 0xb,0x3f,0x66,0xfb,0xca,0xa3,0x9d,0x9c,0xc1,0xa4,0xde,0xd2,0xae,0xad,0x5d,0xb7, + 0xfc,0x5e,0x70,0x1e,0x93,0x6f,0xb,0x9f,0x20,0xdc,0xf9,0xf9,0x4d,0xdc,0xb1,0x5, + 0xee,0x11,0xf4,0x9b,0x99,0x8f,0x6f,0xb9,0x2a,0x11,0xba,0x5c,0x5c,0x2c,0x6e,0xd3, + 0xf6,0x9d,0x7c,0x6,0x1,0x17,0xd4,0xbf,0x7e,0xfc,0xf9,0x97,0xee,0xd9,0xf,0x63, + 0xbd,0x51,0x11,0xa1,0x1f,0x80,0x10,0x36,0xe7,0x55,0x27,0x8b,0xae,0xe0,0xa4,0xa7, + 0xc5,0x1f,0x72,0xcb,0x33,0x7e,0x8e,0x67,0x1c,0x8a,0x85,0x2a,0x26,0xe3,0x40,0x2, + 0x8f,0x1c,0x79,0xcd,0x5,0x21,0x8b,0x70,0xaf,0x4c,0x28,0x64,0x3f,0x78,0xe5,0xe2, + 0x9a,0xf2,0x92,0x99,0xf,0x34,0x7d,0x7f,0x75,0x30,0x1f,0xd7,0xf3,0x4b,0x97,0xae, + 0x2e,0x3f,0x78,0xf5,0xe2,0x9a,0xf6,0x1a,0x8f,0x20,0x3,0x63,0x66,0xac,0x6d,0x58, + 0xe0,0xd7,0xa9,0xd8,0x96,0x45,0x3e,0x37,0x9d,0x8f,0xb0,0xf9,0xa6,0xb0,0x5c,0x51, + 0x92,0x36,0xac,0x62,0x8a,0xc2,0x73,0x17,0x91,0x96,0xc0,0x4,0x4a,0x58,0x25,0x9b, + 0x3d,0x7b,0x22,0xf5,0x62,0x74,0xde,0x58,0x89,0x2f,0xab,0x4f,0x7a,0xc2,0x32,0xf5, + 0xd3,0x42,0xa,0x16,0x2a,0xba,0x46,0x88,0x1f,0x33,0x76,0x1d,0x52,0xa5,0x74,0xf2, + 0x7,0xaf,0x5e,0x5a,0x7f,0xe9,0xd2,0x6b,0x8b,0xc6,0xc8,0xb4,0x6c,0xb4,0xe9,0x51, + 0x20,0x1a,0xf,0xd1,0xbd,0x8e,0x15,0xef,0xcc,0x75,0x9d,0x20,0xfe,0xac,0xde,0xc7, + 0x12,0xb5,0x91,0xd9,0x85,0xa8,0xa1,0xfb,0x30,0x71,0xff,0x89,0x59,0x49,0xf4,0x10, + 0xe7,0x3,0xe3,0x87,0xaf,0x5c,0x58,0x7f,0xf0,0xca,0x3e,0xef,0xe2,0x3d,0x8,0x71, + 0x93,0x19,0xe0,0x1b,0x50,0xb0,0x69,0x60,0x1f,0xb8,0xa,0x74,0x80,0x8d,0x54,0xd2, + 0xdf,0x9,0x7d,0xcc,0xb4,0x2,0xb8,0xfc,0xbb,0x6f,0x66,0xbf,0x78,0xf1,0xea,0xf2, + 0xc3,0x57,0x7,0x7a,0x10,0x30,0xfb,0xe1,0xab,0x17,0xd6,0x1f,0xbc,0x5a,0x1,0x2e, + 0x50,0x8f,0xdc,0xa4,0xe3,0x1e,0x74,0x97,0x3b,0x2a,0xd9,0x2d,0xf9,0xdb,0xba,0x2b, + 0xa,0xd6,0x91,0x5d,0x76,0x38,0x93,0x83,0x29,0xc2,0x7f,0x50,0x95,0x62,0x72,0x63, + 0x41,0x6e,0x57,0x41,0x18,0xaa,0xd7,0xa9,0x62,0x3b,0xb0,0x19,0x62,0x36,0x78,0xdf, + 0x46,0x7b,0xca,0x74,0x56,0x5,0x9e,0x58,0xc9,0xa8,0x77,0x8e,0x67,0x3f,0x7c,0xf5, + 0xc2,0xfa,0xc3,0x7a,0x48,0x4d,0xbd,0x94,0x2d,0x63,0xf,0x7e,0xf0,0xea,0x85,0xf5, + 0x17,0x2f,0x5e,0x5d,0x2c,0xac,0xbb,0x69,0x95,0x1e,0xa4,0x7e,0x93,0xc0,0x50,0x74, + 0xd7,0xa,0xee,0x6e,0xc3,0xeb,0x19,0x16,0x75,0x97,0xa7,0x98,0x90,0x30,0x7f,0x8d, + 0xa7,0x1f,0x98,0xcd,0x91,0xda,0xaf,0xe2,0x76,0x34,0xf,0x76,0x6,0xfb,0xe1,0xab, + 0x17,0xd7,0x5f,0xbc,0x78,0x65,0x49,0x55,0x30,0x58,0x9b,0x9a,0x87,0x91,0x81,0xf1, + 0x60,0x93,0x43,0x3a,0x74,0xae,0xf4,0x7e,0xa2,0xef,0xf,0x44,0x11,0xa2,0x2d,0xde, + 0xcb,0xa1,0xbb,0xcd,0x33,0xe8,0x18,0xc0,0xa2,0xd6,0xb9,0x76,0x2b,0x30,0xe5,0x6d, + 0x38,0x6c,0x2a,0xca,0x23,0x32,0x57,0x80,0x14,0xe8,0x39,0xe6,0xeb,0xbc,0xf2,0xed, + 0xf5,0x3e,0x26,0xde,0x8,0xea,0x7d,0xbe,0x70,0x65,0x31,0x2f,0xf2,0x5d,0xd8,0xa5, + 0xd3,0xc2,0x99,0xd7,0x7d,0xc,0x78,0x24,0xc6,0x67,0x1a,0x20,0x5,0x3,0x26,0x36, + 0xe5,0x2c,0x87,0xca,0xf7,0x59,0x1c,0xda,0xa2,0x24,0xb2,0x91,0xbf,0x3b,0xcc,0x7e, + 0xf8,0xda,0xa5,0xfd,0xda,0xc3,0x6c,0x7a,0xac,0x41,0x17,0x31,0xab,0xc1,0x1a,0xf2, + 0xe4,0x96,0xcc,0xfb,0x20,0x59,0x88,0x4e,0x58,0xb,0x20,0xa0,0x23,0x63,0xa,0x3c, + 0x5e,0x8b,0x91,0xf7,0xb7,0x31,0x92,0xdf,0xe7,0x6c,0x88,0x20,0x23,0xc6,0xdd,0xd7, + 0xd1,0xc5,0x85,0xae,0xa5,0xc2,0x6b,0x2c,0xa2,0xf4,0x23,0xab,0x42,0x25,0xa5,0xd9, + 0xc,0x7,0x16,0x9d,0x3a,0x33,0x85,0x98,0xa9,0xc3,0x91,0xe5,0x43,0xac,0x50,0x3d, + 0x67,0x89,0x5e,0x18,0xcf,0x13,0x66,0x15,0xe0,0x40,0xd3,0x4a,0x74,0x5b,0x28,0xe6, + 0x18,0x60,0x27,0x45,0x6f,0x3b,0xcc,0x38,0x10,0x2a,0x46,0x51,0x9d,0xa2,0xa4,0xfa, + 0x47,0x57,0x2e,0xac,0x6f,0xbf,0x70,0x75,0x79,0xf3,0xda,0x85,0x55,0xe7,0xa6,0x9c, + 0x91,0x14,0xa9,0x96,0x95,0x49,0x17,0xc0,0x71,0x36,0xc9,0x46,0x7e,0x36,0xdc,0x7d, + 0x54,0xed,0x22,0xee,0xc1,0x1,0xb2,0xd8,0xd4,0xdd,0x6c,0x82,0x5a,0x41,0xac,0x64, + 0xe0,0x21,0x73,0x72,0xd9,0x1,0x9e,0xb2,0xa5,0x3c,0xbb,0x89,0x33,0x36,0xcc,0xbc, + 0x9d,0xd3,0xf4,0xd7,0xa7,0x0,0xb,0x71,0xe1,0xb2,0x89,0x21,0x8e,0x0,0x8d,0xfc, + 0x0,0xbb,0xc0,0x42,0xfb,0xce,0x14,0x49,0x3f,0x5d,0x4e,0x9e,0x5a,0x89,0x8,0x9d, + 0x88,0xcc,0x14,0x98,0x5f,0x7f,0x67,0x3e,0x84,0xee,0x88,0x80,0xbc,0xa8,0xbe,0x97, + 0x99,0xa2,0x1f,0x60,0x6,0x48,0x2b,0x32,0xb7,0x26,0xa5,0xc7,0x12,0xd1,0xc1,0x61, + 0xfe,0x68,0x1,0x8b,0x10,0xdd,0xb8,0xf8,0xf7,0xde,0x7e,0xfe,0xca,0xf2,0xa3,0x2b, + 0x7b,0x92,0xc2,0xb3,0x2d,0x41,0x3b,0x37,0xe2,0x2b,0xaf,0x4b,0x82,0x3e,0x23,0x34, + 0x68,0x70,0x0,0x1,0x6c,0x98,0x54,0x1c,0xe0,0x79,0x6f,0xc0,0x2c,0x4e,0xd6,0x61, + 0x28,0x30,0xf5,0xfd,0xeb,0x75,0xfc,0xe8,0xea,0xa5,0x15,0xe6,0xf6,0xb6,0xf3,0x57, + 0x16,0x5e,0x42,0x3f,0xba,0x7a,0x71,0xd5,0x8a,0xc9,0xa6,0xee,0x62,0x16,0x40,0x40, + 0x1e,0xf0,0xaf,0x16,0x6a,0x1f,0xf,0x2,0x48,0xbd,0xf2,0x4f,0xa1,0xcf,0x7b,0x57, + 0xc6,0xa6,0x58,0x1c,0x5,0xd5,0xf1,0xb9,0xf6,0xf6,0xf3,0x57,0x96,0x1f,0x5d,0xbd, + 0xb4,0xc6,0x13,0x23,0x34,0x27,0xec,0xed,0x17,0x5e,0x5b,0x7e,0x74,0xf5,0xe2,0xa, + 0xaa,0xe4,0x18,0x9,0xe2,0xae,0x23,0x42,0x3f,0x58,0x41,0x91,0x10,0x56,0x57,0xbc, + 0xf0,0x9,0xcc,0xca,0xa9,0x76,0xc4,0xb4,0xb,0x30,0x1c,0xb6,0x4c,0x24,0x45,0x59, + 0x30,0xeb,0xcd,0x6b,0x97,0xd6,0xb7,0x9f,0x1f,0x95,0xe2,0xb8,0xe6,0xac,0x87,0xe, + 0x4e,0xe6,0x26,0xe4,0xa0,0xce,0x36,0x60,0x1a,0x18,0x72,0xa7,0x91,0x3,0xb5,0xf9, + 0x1,0x44,0xbd,0x88,0x5a,0x99,0xbd,0x79,0x75,0x5c,0xa7,0xa3,0x10,0x16,0xc0,0xec, + 0x47,0xd7,0x2e,0xad,0xf0,0x3,0x41,0xcc,0x14,0x6b,0x84,0x7a,0xe,0x7b,0x90,0x6d, + 0x66,0xe9,0xe5,0x99,0xca,0x20,0xb7,0xe6,0x3c,0x22,0x76,0xa0,0xf8,0x91,0x34,0xc2, + 0x7,0xc4,0x83,0xac,0x8f,0xe5,0x5c,0x41,0xc0,0x8c,0xd9,0x19,0x5d,0x1,0x4d,0xa0, + 0x98,0x21,0x16,0x75,0xf2,0x59,0x2a,0x3d,0x6,0x43,0x4,0x51,0xb0,0x37,0xaf,0xde, + 0xb3,0xbe,0xfd,0xfc,0xab,0xcb,0x49,0x93,0x79,0x59,0x70,0x80,0xe1,0x94,0x37,0xa0, + 0x60,0xdf,0x7e,0xee,0xea,0xf2,0xe6,0xd5,0xb,0x5d,0x73,0xfd,0xcd,0x6b,0x17,0xd6, + 0xb7,0x9d,0x6f,0xbc,0xc4,0x3,0x6d,0x2f,0xe1,0x1b,0xc,0x2a,0x91,0x45,0x75,0xb9, + 0xd8,0xf6,0x94,0x56,0x91,0x4f,0x1e,0xef,0x8,0xba,0xc5,0x43,0xdb,0xc8,0x43,0x7b, + 0x53,0xd4,0xb1,0xe6,0x15,0x95,0xae,0x90,0xec,0xf3,0x3b,0xde,0x2a,0xf0,0x2e,0xeb, + 0x77,0xcb,0xe8,0x54,0x1d,0x3d,0xc4,0xcf,0x7d,0xf3,0xea,0xc5,0xf5,0xf0,0xd4,0x30, + 0xb7,0xd8,0x74,0x8d,0x5,0x15,0xb7,0xd0,0x82,0x99,0xa0,0xdc,0x94,0xfd,0xc6,0x6d, + 0x7c,0xd7,0x54,0x62,0xa,0xce,0x45,0xee,0x21,0xd,0x1a,0x8b,0xcb,0xc1,0xf0,0xe6, + 0x55,0x6a,0x15,0x62,0xd2,0x6d,0xc4,0x7e,0x0,0xbd,0xed,0xec,0x6b,0xcb,0x8f,0xaf, + 0x5f,0x5c,0xdf,0x76,0xf6,0xca,0xf2,0xe6,0xb5,0xfa,0x3b,0x82,0x9c,0x2a,0xb4,0x2e, + 0x47,0x36,0xfa,0xe6,0xd5,0xa,0x3e,0x9,0x46,0x31,0x62,0x74,0xe3,0x8,0xf4,0x3a, + 0xb,0xcf,0x2c,0xb0,0x11,0x8,0x18,0x98,0xc0,0x86,0x5b,0x98,0x8a,0x90,0x3e,0xb8, + 0x78,0xbe,0x13,0xa0,0x51,0xb,0x62,0x17,0xf7,0x25,0x8f,0xb3,0xdf,0xd0,0x99,0x18, + 0xa3,0x96,0x3c,0x9b,0x25,0x6c,0x7c,0x70,0x83,0xe2,0x51,0x4d,0x6c,0xf7,0xc7,0x46, + 0x3d,0x8d,0x93,0x10,0xaa,0x73,0x2a,0x27,0x7f,0x7c,0xed,0xd2,0xea,0x14,0x0,0x15, + 0x46,0x49,0x2d,0xfa,0x2d,0x7,0x11,0xfe,0xe8,0x37,0xaf,0x5d,0xc,0x20,0x27,0xa7, + 0x71,0xc6,0xa8,0x1e,0x7d,0x8e,0xab,0x56,0x6c,0x32,0xc6,0x68,0x8,0x4e,0x26,0x29, + 0xa1,0x3f,0xc8,0xc9,0xc3,0x8f,0xaf,0xd5,0x40,0xde,0xc6,0x50,0x50,0x20,0x6d,0x6f, + 0xb3,0x6e,0xa1,0x73,0x21,0xd5,0xf5,0xe8,0x66,0x20,0xac,0x85,0x69,0xe4,0x71,0xb5, + 0xe9,0xdc,0x2f,0xa5,0x8c,0x44,0x3d,0x60,0x62,0x3a,0xef,0xda,0xd4,0xe7,0xba,0xaf, + 0x6d,0xca,0xbe,0xe,0x51,0xd8,0xde,0x7c,0xfd,0x92,0x88,0x7,0xf1,0x7b,0x76,0x84, + 0xba,0x0,0x5e,0x4d,0x30,0x3b,0xfd,0x1e,0x8b,0xc2,0x5d,0x3b,0x57,0xc6,0x5a,0xfd, + 0x71,0xfd,0x9c,0x8c,0x88,0x67,0x8c,0x5,0xa4,0x2b,0x23,0xc0,0xb9,0xcd,0x12,0xda, + 0x5c,0x4d,0xc0,0xdc,0xa6,0xf8,0x74,0x2,0xe8,0x1a,0xb5,0xc5,0x3d,0x74,0x26,0x61, + 0x2e,0x58,0x1b,0x5,0xb5,0xb8,0x30,0x80,0x83,0x60,0x4,0xbd,0x34,0x80,0xe8,0x48, + 0x85,0x93,0xd0,0x51,0x69,0x7e,0x9e,0xca,0x52,0x64,0x4e,0x8f,0x30,0xc5,0x48,0x77, + 0xe0,0xcd,0xd7,0x2f,0xad,0x60,0xaa,0xb1,0x4d,0xa7,0x51,0x19,0x8f,0xb3,0xd9,0x4e, + 0x5b,0x3,0x21,0x22,0x9d,0xfc,0xbb,0xa7,0x5e,0xd8,0x52,0x55,0x32,0xcc,0x16,0xf6, + 0xe3,0x6b,0x17,0x57,0x99,0xf5,0xf6,0x3d,0x31,0xb4,0xad,0xdd,0xe3,0x9a,0xaf,0xe0, + 0x5,0xa9,0xa6,0x7c,0x72,0xa2,0x86,0x4a,0x4b,0x10,0x83,0xe8,0x92,0xb3,0x9e,0x7, + 0x54,0x69,0x7e,0x9c,0x79,0xe2,0x8,0x15,0xa,0xa6,0x1,0x48,0x79,0xb7,0x20,0xb4, + 0xe3,0x8,0xd6,0xbf,0x70,0xf6,0xea,0xf2,0xe3,0xd7,0x2f,0xae,0xb1,0x32,0x72,0xca, + 0x2c,0x62,0x65,0x9,0xb,0x5c,0x54,0x53,0xf5,0x27,0x6,0x3a,0x39,0x22,0x62,0xa5, + 0xd4,0x77,0x1f,0x20,0xd,0xe7,0x43,0x97,0x50,0xf2,0x31,0x51,0xe7,0x83,0x1b,0x29, + 0x87,0x19,0x46,0x18,0xce,0x20,0xc4,0x3e,0x6b,0xe2,0xc,0x36,0x1c,0xce,0x50,0x99, + 0xc9,0xe,0x1c,0x8c,0x33,0xec,0xd0,0xa1,0xe0,0xb5,0x1,0x84,0xa0,0x90,0x30,0xf, + 0x71,0xa1,0x43,0xc1,0x5b,0x72,0xd,0x16,0x18,0xde,0x23,0x3b,0xfe,0x85,0xa3,0xd7, + 0x96,0x1f,0xdf,0xb8,0xb8,0x72,0x75,0x34,0xf0,0x23,0x3e,0xa9,0xe8,0xc7,0x7b,0xfd, + 0xc5,0xf5,0x4b,0xeb,0xcf,0x1f,0xbd,0xb6,0xfc,0xe4,0xc6,0xa5,0x35,0xcf,0xe9,0xb4, + 0xbf,0x12,0x84,0x5,0xc6,0xa7,0x41,0xf9,0xca,0x3d,0xcc,0x52,0x90,0x6a,0xbf,0xf3, + 0x17,0xd7,0xe9,0x0,0xe5,0xa0,0xda,0xf6,0x80,0xb0,0xd9,0x15,0x5c,0x38,0xe6,0x97, + 0x3c,0x62,0xd7,0x2e,0xc6,0x8f,0x6f,0xd4,0xca,0x88,0x5e,0x6b,0x81,0xc9,0xc1,0x4e, + 0x69,0x2e,0xaa,0x63,0x8,0x28,0x76,0xed,0xec,0x21,0x8e,0x3e,0xa8,0xb2,0x36,0x55, + 0x46,0x1d,0x18,0xe,0x5a,0xb3,0x82,0xdb,0x12,0x7c,0x58,0xb1,0x24,0xb3,0x1b,0xab, + 0xab,0x6,0xda,0xec,0x46,0x3a,0x54,0xbd,0x3,0xa4,0xcb,0x1f,0x3a,0x68,0x4e,0xf4, + 0x40,0x58,0x62,0x49,0xb4,0xc3,0xf6,0xe7,0xcf,0xbc,0xb6,0xfc,0xc5,0xf5,0x4b,0x1d, + 0x8,0xc,0x3e,0x71,0x31,0xeb,0x38,0xb8,0x24,0xfa,0x5c,0x40,0x38,0x89,0x9e,0xfc, + 0xf8,0xc6,0xa5,0x15,0x74,0xf3,0x5b,0x1b,0xbf,0x3,0x61,0xfb,0xb9,0x6a,0xa3,0x8b, + 0x20,0x81,0x3f,0xa3,0xbb,0xdb,0x99,0xc0,0x50,0x7e,0x74,0x1c,0xd,0x3a,0x32,0x1b, + 0x10,0xca,0x85,0x98,0x56,0xb9,0xf9,0x81,0x26,0x30,0x44,0x3b,0x41,0x7c,0xe7,0x15, + 0xe7,0x9e,0x31,0x49,0x53,0x79,0x7f,0x4c,0xda,0xcd,0x9e,0xd0,0xf4,0x48,0x7e,0xf5, + 0xfe,0x16,0xd8,0x8d,0x6c,0x5b,0x9b,0x19,0x8,0x36,0x5a,0xf7,0xb1,0x5b,0x89,0xd8, + 0xfd,0x9c,0x38,0xa1,0x5,0x7e,0xcd,0x60,0x6b,0xe5,0xb1,0x67,0xea,0xec,0xb6,0xf6, + 0xbf,0xe7,0xee,0x67,0x1c,0xf,0x85,0x4a,0xcc,0xdc,0x2b,0x6d,0xcd,0xcc,0xec,0x2f, + 0x6e,0x5c,0x5c,0x7f,0xfe,0xcc,0x95,0xe5,0x27,0xb7,0x2e,0xae,0x8c,0x96,0xe4,0xf6, + 0x5c,0x9c,0xaf,0xf5,0xd,0x5,0xed,0xa5,0x71,0xd2,0xeb,0xe,0x51,0xc8,0x61,0xac, + 0x4e,0x3b,0xb4,0xe2,0x40,0xa9,0x7,0x23,0x2,0xa7,0xa5,0x80,0xef,0x83,0x36,0xe5, + 0x98,0x88,0xa2,0x20,0x42,0xf4,0x83,0xfe,0xae,0xc1,0x7e,0x72,0xe3,0xe2,0xea,0xb4, + 0x90,0x19,0xf1,0xc8,0xc0,0x23,0x37,0xad,0xd0,0xc7,0x5b,0x8e,0xa0,0xa1,0xc8,0xe7, + 0x76,0x4f,0x2f,0xad,0xdc,0x72,0x6b,0x3f,0xff,0xc9,0x8d,0x8b,0xab,0x4f,0xbb,0xc, + 0x44,0x7d,0x6b,0x4d,0x3a,0xca,0x54,0x95,0xda,0x17,0x2,0x23,0xe9,0x66,0x3b,0xa2, + 0x99,0x4e,0x4c,0xae,0x22,0x59,0x4d,0x5b,0xdc,0xde,0xab,0x98,0x31,0x34,0xf4,0x90, + 0xe0,0x81,0x10,0x34,0x1e,0xb3,0xda,0x8e,0xde,0x86,0x64,0x92,0x7c,0x10,0x8f,0xcd, + 0xbe,0xdf,0xb3,0x9f,0x3f,0x7d,0x65,0xf,0x8c,0x16,0x44,0x4d,0x66,0x15,0xf2,0xf6, + 0x16,0xe2,0x16,0x24,0xf8,0x21,0x88,0x5c,0xcb,0x74,0x25,0x5e,0xcf,0x51,0x2e,0x94, + 0x87,0xce,0xce,0xdc,0xda,0xd0,0xa9,0x10,0x5f,0xea,0x34,0x8e,0x99,0xf9,0xce,0x7, + 0x40,0x9f,0xd,0x73,0x86,0xc1,0x34,0xe0,0xea,0x9a,0xf,0xcb,0x11,0x90,0x98,0xa5, + 0x20,0x15,0x71,0x1c,0x41,0x61,0xf8,0x13,0x8c,0xbd,0xe9,0x2a,0x4d,0xc9,0x35,0x3b, + 0x8d,0x72,0xfb,0xed,0x73,0x48,0x87,0x6b,0x50,0x45,0x79,0x94,0x84,0xe0,0xff,0x3d, + 0x2a,0x3c,0xb8,0x4f,0xb8,0x4d,0xba,0x57,0x99,0x1e,0x86,0x28,0xa0,0x64,0x79,0xac, + 0x23,0x9d,0x16,0x2e,0x21,0x62,0x29,0xda,0xf1,0x10,0x9e,0xe6,0x77,0x48,0x4d,0x27, + 0x4c,0x7d,0xcc,0x53,0xab,0x1a,0x9e,0x71,0x43,0xa4,0x15,0x81,0xf4,0xf9,0xb9,0xc0, + 0x40,0x1c,0x61,0x61,0xd2,0x4e,0x8e,0xed,0x6f,0xb3,0xd4,0xf6,0xee,0xda,0x1f,0xd1, + 0x89,0x0,0xd4,0xb2,0x2d,0x3,0x30,0x8b,0x8,0xce,0x44,0x2e,0x9c,0x80,0x3,0x1, + 0xd0,0x73,0xa2,0x18,0x6f,0x22,0x3c,0xec,0xd1,0xc9,0xc,0xbd,0xfd,0xed,0x27,0x37, + 0xef,0x59,0xa3,0x34,0xf5,0x74,0x32,0x18,0xc1,0x77,0xc6,0x4e,0x8c,0x3e,0xe9,0xc7, + 0x2b,0x18,0x50,0xf5,0x40,0x5c,0x5b,0xe7,0x12,0x4b,0x2c,0x77,0xcc,0x30,0xab,0xc2, + 0x3c,0x77,0x75,0xa9,0x43,0x25,0x9a,0x27,0x50,0x30,0x22,0x42,0x17,0x73,0xb0,0x2d, + 0x5c,0x98,0x66,0x71,0x5c,0x65,0xd1,0xe4,0x6c,0x64,0x9d,0x72,0x3e,0x9e,0x14,0x81, + 0x12,0xae,0x94,0x10,0x17,0xa0,0x4f,0x39,0x73,0xd1,0x19,0xcc,0xd8,0xa2,0x13,0x16, + 0x9b,0x73,0xfd,0x26,0xba,0xf0,0xdc,0x3d,0xcd,0xc1,0x8d,0x2b,0x3c,0x6,0x5b,0x14, + 0x45,0xeb,0xc6,0x7e,0x8f,0x8e,0xb,0x3d,0x65,0xd6,0x96,0x2,0x53,0x6c,0x5e,0x47, + 0xec,0x7d,0xf6,0xbc,0xed,0x47,0x28,0xcf,0xb6,0xa6,0xa,0x73,0xa1,0x45,0x68,0x99, + 0xbf,0xbb,0xb7,0x6f,0xe8,0x61,0x4f,0xe,0x2d,0x17,0x5e,0xa4,0x27,0xbd,0xf1,0xd8, + 0x61,0x69,0x3c,0x6a,0xf,0xd3,0x8f,0x8,0xbb,0xc4,0x81,0x8c,0x55,0xe,0x7f,0xf, + 0x89,0xda,0xa4,0xc2,0x89,0x6a,0x4a,0xb1,0x8d,0x9f,0xfc,0xb1,0x1d,0x59,0x9,0x6d, + 0x32,0x99,0x31,0x6a,0xe5,0xb7,0x7b,0xfc,0xcf,0x4f,0xbd,0xb6,0xfc,0xe4,0xd6,0xa5, + 0xb5,0x3,0x4,0x5b,0x87,0x64,0x82,0x83,0xc8,0x15,0xac,0x1a,0xca,0x6a,0x7,0xc5, + 0xfa,0x33,0x1d,0xd5,0x33,0x37,0x72,0x7d,0xaa,0xfc,0x97,0xd1,0xba,0x79,0xa3,0x7, + 0xa1,0xc9,0x61,0x62,0xa4,0xcd,0x28,0x85,0x85,0xf5,0xaf,0xa5,0xa2,0xa1,0xd3,0xf1, + 0x81,0xbb,0x50,0xc1,0xa4,0xb1,0xee,0x8a,0xc6,0x49,0xd5,0xbd,0x71,0x7,0x48,0x2b, + 0xb1,0xbe,0xfa,0xa0,0x58,0x82,0x91,0xe6,0x68,0xdb,0x37,0xa1,0xe2,0x31,0xb8,0xd3, + 0x9e,0x12,0x11,0xde,0x49,0x66,0x56,0xd8,0xc7,0xc0,0x6c,0xcc,0xce,0x26,0xb3,0xf, + 0x4c,0xc6,0x69,0xe9,0x75,0xe1,0xbe,0xc7,0x99,0xba,0xc2,0x69,0x12,0xb,0x23,0x63, + 0x33,0xf4,0x70,0x89,0xb3,0xcf,0x4,0x1d,0x10,0xb9,0x43,0x8d,0x59,0x88,0x80,0x88, + 0x9,0xf2,0x1d,0x9e,0x13,0xfd,0xd6,0x35,0xd0,0xb9,0x1f,0xb5,0xef,0x13,0x9e,0xc5, + 0xd4,0x93,0xc1,0xf1,0x16,0x62,0x5d,0x2e,0xe3,0x13,0xcd,0xce,0xa5,0xe7,0x3e,0x19, + 0xc,0x22,0xb5,0x72,0x5a,0x6e,0x4a,0x71,0x85,0xb3,0x7e,0xe7,0x80,0xec,0xdc,0x22, + 0x4,0x25,0xa8,0x3e,0x19,0xf3,0x51,0x4c,0xf1,0x48,0x4f,0x89,0xf,0x30,0x56,0xe8, + 0x30,0xed,0x86,0x86,0x39,0xb7,0xb4,0xd5,0x7d,0x28,0x10,0xee,0xd2,0xcc,0xa1,0x7, + 0x0,0x1d,0x3d,0x25,0xcc,0x54,0x33,0x19,0x8a,0xb8,0x1d,0xe4,0x98,0x6a,0xe6,0xf6, + 0xcf,0xee,0x7e,0x75,0xf9,0xf,0xb7,0xef,0x5d,0xfb,0x68,0x2e,0x26,0x9e,0x50,0xd5, + 0x80,0x2c,0xb2,0xd6,0x2a,0x74,0xda,0xa4,0xa2,0x31,0x2e,0x99,0xd9,0x98,0x2d,0x39, + 0x57,0xe8,0x71,0x1e,0xc0,0x80,0xf,0x4,0x7,0xb5,0x9e,0xd,0x71,0x6d,0xe1,0xc9, + 0xe2,0x12,0xac,0x2f,0xdd,0xe7,0x8,0xd0,0xf5,0x12,0x1b,0xa8,0x88,0x89,0xc8,0xa8, + 0x84,0xc6,0x3a,0x41,0xa2,0x13,0xf8,0xc,0xf8,0x67,0x98,0x68,0x30,0xef,0xb,0xec, + 0x3f,0x1c,0x5f,0x5a,0x59,0xb6,0x92,0xf,0x94,0xbf,0x3c,0xbe,0x67,0xfd,0x67,0xef, + 0x7c,0x75,0x68,0x3d,0x3,0x39,0x99,0xe1,0x6a,0x2d,0x8a,0x78,0x84,0x43,0xb0,0xcd, + 0xb0,0xc0,0xe3,0xc6,0x99,0xb9,0x7,0xcf,0x66,0xc8,0x89,0xce,0xa8,0x75,0xd9,0x8f, + 0x6a,0x4e,0x70,0xfa,0xbe,0xf5,0x84,0xc,0x66,0xe0,0x4d,0x97,0x2f,0x45,0x44,0x34, + 0xd1,0xb5,0x45,0x3,0x18,0x1,0x44,0xba,0x1c,0x4e,0xa3,0x2,0x1f,0xf7,0xf9,0x2f, + 0x6f,0xf3,0x2c,0x6e,0x54,0xc4,0x31,0x1e,0xa9,0xbe,0xbe,0xa7,0x7a,0xc6,0x15,0x71, + 0x15,0x78,0xc8,0xae,0x32,0x9f,0xa6,0x3c,0x6b,0xd,0x45,0x50,0x74,0x6b,0xe8,0xd0, + 0x38,0xa2,0xaa,0xe2,0x44,0xdf,0xbf,0x85,0xe7,0x92,0xe2,0xa2,0xb6,0xe4,0xa2,0x77, + 0xba,0x22,0xf3,0x11,0x2b,0x67,0x6a,0xb2,0x9a,0xa8,0x2a,0xa5,0x8a,0x50,0x79,0xf7, + 0x87,0x2a,0xc4,0x69,0xf5,0xc8,0x33,0xe3,0x19,0x90,0x2a,0x8c,0xbc,0x84,0x2b,0x9f, + 0xe6,0xc8,0xa,0x86,0x12,0xa,0xa5,0x97,0x4,0xf0,0xc9,0xc,0x87,0x1c,0x33,0xcc, + 0xa6,0x8,0xa9,0xc9,0x78,0x2e,0x8f,0x3f,0x61,0x93,0x2a,0xcc,0xa9,0xe3,0xc4,0xca, + 0x91,0x1e,0xd8,0x9,0xdc,0xde,0x8c,0x3c,0x6b,0xb,0xb8,0xa3,0x28,0x1f,0xa,0x11, + 0x91,0xd5,0xbd,0x15,0x3,0x68,0x7,0x2e,0x46,0xed,0x56,0x93,0xa,0x13,0xc6,0xdd, + 0x49,0x1e,0x5d,0x68,0x72,0x36,0x89,0xf0,0x69,0xcf,0x38,0x41,0x51,0x9d,0x85,0x8a, + 0xb2,0xb4,0x61,0x86,0x3c,0xf1,0xa4,0xd4,0x54,0xe5,0x8d,0xbd,0x8,0x68,0xbc,0x87, + 0x6e,0x51,0x2c,0x38,0xd6,0xfd,0xb,0xa,0x50,0x16,0x33,0x28,0x90,0x8a,0x7,0x65, + 0x45,0xbe,0xac,0x4c,0x39,0xeb,0x38,0xc4,0x24,0xd5,0x2d,0xe3,0x8d,0xc,0x39,0x1, + 0xb6,0x90,0x14,0xdb,0xe4,0x73,0x18,0xa3,0x90,0x96,0x2f,0x7d,0x77,0x8d,0xb9,0x3, + 0x40,0xae,0x48,0x97,0x9,0x8,0x96,0x63,0x2c,0x57,0xe8,0x9c,0xf0,0xbb,0x9b,0xfd, + 0xd3,0xbb,0x5e,0x5b,0xfe,0xea,0xe,0x81,0x2a,0x5c,0x11,0xc9,0x8c,0xc0,0x44,0xe8, + 0x30,0x4a,0xa6,0xe2,0xb9,0xcd,0x31,0xc0,0x2c,0x9c,0x26,0xc7,0x6a,0x42,0x37,0xab, + 0xa7,0x99,0xc4,0x1c,0x95,0xee,0xce,0x52,0x92,0xa3,0xe2,0x9d,0x81,0x8,0xd0,0xab, + 0x9a,0x7c,0xba,0x8d,0xec,0x90,0x84,0x6a,0x68,0x26,0xc5,0xf,0xa,0x22,0xe6,0xe2, + 0x59,0x31,0xcf,0x46,0x4b,0xc7,0xa1,0x47,0xf4,0x44,0x99,0x36,0x67,0x6f,0x98,0xb4, + 0xc0,0x82,0xa3,0x9a,0x3e,0x6b,0xf,0xc1,0x22,0xda,0x79,0x5a,0x76,0xb,0x32,0x6d, + 0xe9,0xea,0xc8,0x22,0x58,0xb,0xfa,0xc4,0xbe,0xc,0x93,0x60,0x68,0x3a,0x36,0xf4, + 0x82,0xc0,0xd8,0x82,0xce,0x4c,0x6d,0x62,0x7e,0x10,0xda,0xd5,0xea,0x70,0x86,0x8, + 0xc5,0x9d,0xb6,0x50,0xed,0x40,0x67,0x22,0x66,0xee,0x7,0x49,0x14,0x98,0x73,0x8f, + 0xc1,0xa,0x86,0x99,0xcf,0xb,0x6d,0x23,0xe5,0x6a,0x20,0xd,0xef,0x30,0x14,0xdd, + 0xc4,0xa1,0x2c,0x82,0xa1,0x2c,0xb0,0x95,0x1c,0x5a,0x92,0x1e,0x24,0x3d,0x20,0x8c, + 0xa9,0xe6,0xc1,0x50,0x71,0x14,0x34,0x63,0x95,0x4e,0xc9,0x18,0x4d,0xa8,0xc,0xdb, + 0x84,0x19,0x30,0x7a,0xf6,0x84,0xd0,0xa2,0xd4,0xe,0x6e,0x6f,0x8d,0xc0,0x1c,0xe7, + 0xc7,0xf0,0x20,0x30,0x5,0x0,0x76,0x65,0x9e,0xc9,0x93,0x4c,0xdc,0x6d,0xf,0x87, + 0x2c,0x28,0x90,0x8c,0x4,0x69,0xce,0x26,0xd0,0x64,0x91,0xfd,0xbe,0x5d,0x88,0x22, + 0x48,0x78,0x60,0xcf,0x78,0xc7,0xf1,0x5d,0x64,0xc,0x90,0xb8,0x35,0x4,0xb2,0x74, + 0xa5,0xeb,0xc1,0xd4,0x31,0x51,0xaa,0x3a,0x25,0x93,0x47,0x97,0x2,0xd1,0xcc,0x8f, + 0x0,0x5c,0xae,0x26,0x29,0x68,0xee,0x94,0xad,0x19,0x23,0xa7,0x8c,0x74,0x94,0x46, + 0x17,0x33,0xdd,0x7b,0xe3,0x2,0xed,0xc0,0xb3,0x46,0x30,0xdd,0x9c,0x28,0xd2,0x79, + 0x62,0xb0,0x8,0x8b,0x22,0x4,0x42,0x98,0xfd,0xd5,0xf,0xee,0x5d,0x99,0xaf,0xf, + 0x8b,0xf8,0x6a,0xc8,0x28,0xb2,0xe1,0x15,0x86,0x6,0xfd,0x88,0x25,0x88,0xc0,0xd9, + 0xa9,0xc7,0xc4,0xe0,0xb4,0x9b,0x58,0x78,0xcb,0x0,0x37,0x39,0xab,0x19,0x69,0xa7, + 0xb8,0x1c,0xc1,0xaa,0x87,0xc2,0x20,0x6b,0x10,0x8,0xd7,0xbd,0xda,0x6f,0x35,0x23, + 0x85,0xc4,0x13,0xd5,0x31,0x8d,0xfd,0xef,0xdf,0xbf,0x67,0xfd,0x27,0xbf,0xfc,0xda, + 0xe2,0x89,0x77,0x39,0x40,0x14,0x3d,0x68,0x13,0xf7,0x31,0x81,0x7,0xc4,0x9c,0x3d, + 0x6a,0x30,0x92,0x13,0x13,0x5b,0x85,0xc2,0x83,0xf9,0x4,0xa4,0xa9,0x3c,0xa8,0xda, + 0x4e,0xbf,0x3,0xa,0x8a,0xc8,0x15,0x46,0x40,0x43,0x8,0xdf,0x12,0xea,0x8e,0xa4, + 0x3c,0x70,0xef,0x1b,0xd,0x65,0xb0,0x19,0x85,0x87,0xc8,0xd9,0x64,0x9,0xa8,0xe4, + 0x59,0xd0,0x11,0xda,0x77,0xb6,0xea,0x9b,0xb0,0x4e,0x32,0x97,0x77,0xda,0x97,0xe4, + 0x19,0x2e,0xe,0x44,0x2f,0x48,0xb0,0x87,0xcd,0xfc,0x58,0xb,0x7d,0x56,0x70,0xd2, + 0x8a,0x96,0x42,0xa2,0xcb,0x8f,0x80,0xb4,0x1e,0xcf,0xb8,0xc0,0xe,0x88,0x6d,0x94, + 0xf4,0x75,0x8a,0x1d,0x72,0x79,0x6b,0x37,0xcf,0xd4,0xf6,0x75,0xf2,0x45,0x67,0x5a, + 0xd4,0x52,0x5d,0x41,0x1d,0xde,0xe2,0xfa,0x18,0xfc,0x50,0x74,0x41,0x80,0xba,0x5f, + 0x50,0xe7,0x84,0xe3,0x48,0x5,0x72,0xe2,0x3,0xd7,0xca,0x19,0x48,0x9a,0x6,0xe9, + 0xbe,0x52,0x20,0x6,0x3,0xdb,0xfa,0x65,0x3a,0x31,0x59,0xc4,0x9a,0xb0,0x9e,0xf3, + 0x98,0xcc,0x17,0x99,0xbf,0xae,0x3f,0x43,0x40,0xd1,0xef,0x7b,0x28,0x63,0x5d,0x5c, + 0x78,0xcc,0xe9,0xfe,0x54,0xd,0xb,0xa8,0xb5,0xb2,0x13,0x86,0x46,0xfc,0x6a,0x67, + 0x2e,0x74,0x8,0x2d,0xce,0x3,0x9d,0x6,0x68,0xe0,0x42,0x40,0xf6,0xf3,0x5e,0xd6, + 0xb6,0x7b,0x3e,0x3d,0x10,0xdd,0x1b,0xa5,0xdb,0xc1,0xe,0x64,0xc4,0x90,0x30,0xd6, + 0x45,0x9f,0xd3,0xab,0xf4,0xca,0x4b,0x77,0xda,0x32,0xa0,0xfe,0x1a,0xd2,0x24,0x81, + 0x41,0x95,0x60,0xab,0x66,0x4c,0x72,0x35,0xc4,0x62,0x0,0x66,0x56,0xfa,0x49,0xe8, + 0x7c,0x7b,0xb8,0xab,0x8a,0x5c,0xfd,0x49,0xce,0xc,0x8,0x48,0xaf,0xaf,0xc,0x3a, + 0x4b,0xa2,0x3b,0x63,0xbb,0x93,0xac,0xf8,0x38,0x53,0x1e,0x35,0x2,0xe2,0xf1,0x5a, + 0x72,0x3a,0x3f,0xd0,0x99,0xc,0xa3,0xa3,0xe8,0xbb,0xbb,0x49,0x5b,0xf5,0x0,0x8d, + 0xf0,0x50,0x5d,0xb,0xdb,0xb3,0x6,0xd9,0xd2,0x4a,0xf7,0x9,0x11,0x1f,0xe6,0x51, + 0xd2,0x41,0xf0,0x5b,0x6d,0x4e,0xef,0xa8,0x78,0xa9,0xce,0xbb,0x27,0x3,0x26,0xd6, + 0x17,0xa9,0x1d,0x16,0x88,0x15,0xee,0x70,0x15,0x45,0x70,0x20,0x64,0x4d,0x17,0x56, + 0xb5,0xec,0x7c,0xf8,0x96,0x88,0x62,0x10,0x77,0x4c,0x8e,0x89,0xa1,0xa0,0x59,0x8c, + 0x84,0x3,0xa2,0x7f,0x32,0x7,0xd8,0x96,0xc1,0xca,0xcc,0x16,0xd9,0xbf,0x1c,0x71, + 0x76,0x23,0xc4,0x9b,0xec,0xe5,0x9d,0x2d,0x3e,0x4d,0x2b,0xc9,0x4,0xd6,0x50,0x61, + 0x84,0x14,0x48,0xc2,0xa2,0x44,0x56,0x86,0xd6,0x52,0x6e,0x76,0xf0,0x5a,0x44,0xc9, + 0xc6,0x58,0x58,0x28,0x9b,0x53,0x14,0xbc,0xfb,0xa4,0x4a,0x12,0xfe,0x20,0xe6,0xad, + 0x59,0xa7,0xc3,0x55,0xcf,0xe5,0xac,0x42,0x31,0xf3,0x65,0xa4,0x83,0x33,0x1b,0x81, + 0x23,0x97,0x9,0xe1,0x4c,0xb5,0xb0,0x31,0x27,0x42,0xdb,0xa1,0x1a,0x1a,0x41,0x2a, + 0x2a,0xd1,0x8d,0x9e,0x3d,0x42,0xcf,0x18,0x61,0x8a,0xad,0x81,0x7f,0x7c,0x77,0xf, + 0xea,0x53,0x3,0x48,0xe6,0x11,0x18,0x20,0xde,0xc7,0xc1,0xae,0x14,0x13,0xd,0xe9, + 0xa0,0x14,0x18,0x3d,0x97,0x61,0x51,0xa4,0x64,0xa8,0xbf,0xb8,0x73,0xb5,0xb1,0x1f, + 0xcb,0x8c,0xbc,0x77,0x53,0x70,0x52,0xea,0xd,0xa3,0x0,0x65,0x3f,0x69,0x1c,0xfb, + 0x7f,0xf6,0x8c,0x10,0x70,0x94,0xfe,0xe7,0xf6,0xff,0xa8,0x3f,0x43,0x29,0x70,0x0, + 0x26,0x89,0x2a,0x7a,0xa0,0x73,0xd3,0x64,0xa6,0xe5,0x9e,0x1e,0xbd,0xed,0xad,0x24, + 0x4a,0x1e,0xb8,0x6a,0x86,0x1e,0x26,0x98,0xae,0xfd,0x91,0x24,0x5b,0x90,0xd2,0xf4, + 0xe0,0x84,0x7,0x84,0x1,0x0,0xb0,0x97,0x10,0x90,0x97,0xf4,0x45,0x2f,0x69,0x1e, + 0xf8,0xe4,0xeb,0x5f,0x5e,0x8c,0xa5,0xf7,0x1c,0xa1,0x74,0x5d,0x29,0x97,0x83,0xab, + 0x74,0x33,0x66,0xf3,0xfd,0x7e,0xfb,0x50,0x55,0x11,0xe3,0xe6,0x11,0x34,0xf7,0xbb, + 0x4e,0xdf,0x3,0x1e,0xf3,0xab,0x7a,0xbe,0xfc,0xf5,0x9b,0xf7,0xae,0xff,0xe3,0xdb, + 0x5e,0x59,0x46,0xf7,0xc8,0xf,0x27,0x4d,0xc9,0xf2,0x94,0x19,0x2d,0x2a,0x60,0xc2, + 0xf3,0x7e,0x40,0x3b,0x2b,0x29,0x93,0x7,0xdd,0xa6,0x1e,0x1c,0xf7,0xef,0x59,0xf1, + 0x25,0x30,0xb4,0x75,0xa,0x49,0xc4,0x78,0x7f,0x79,0x12,0xf8,0x2a,0x30,0x2b,0x35, + 0x36,0x17,0x78,0xa9,0x6b,0xd4,0x4a,0x5d,0x97,0x36,0x59,0xc7,0xfb,0x7a,0xf5,0xba, + 0x86,0xff,0xe3,0x8f,0xef,0xff,0xbb,0x7f,0xfc,0xb6,0x97,0x7f,0xe,0xa5,0xb4,0x3d, + 0x52,0xd7,0xf1,0xfe,0x7e,0xfb,0xcb,0xcb,0xfe,0x11,0x7d,0xdd,0x17,0x40,0xa8,0x8e, + 0x3,0xc4,0x39,0x1e,0x38,0x34,0x1d,0xab,0x9f,0xde,0x9f,0xbd,0x8f,0x89,0xb7,0x5b, + 0xd8,0x13,0x5d,0x7,0x60,0xa0,0xb4,0x11,0x97,0x9a,0xd,0xb1,0x27,0x30,0x3,0xc9, + 0xa3,0x8,0x4d,0xec,0x1e,0x8f,0xf3,0x44,0x4,0x67,0x2c,0x8,0xd7,0x84,0xf0,0xf0, + 0xd7,0x6f,0xde,0xb7,0xfe,0xe3,0xb7,0xbd,0xbc,0x30,0x5d,0x4f,0xca,0x39,0xd8,0x44, + 0x88,0x25,0xf8,0x15,0x50,0xc7,0xe1,0x24,0x7,0x85,0x6d,0x9b,0xfd,0x9e,0xfa,0x42, + 0xb6,0xd7,0x6c,0x9b,0x65,0x37,0x2,0xc2,0x4d,0x60,0x62,0xb2,0xa1,0xdd,0x5f,0xe4, + 0x4d,0x30,0x13,0x2d,0x8f,0xb3,0x34,0x72,0x5e,0x72,0x96,0xe1,0x89,0x1d,0xfe,0x24, + 0xd6,0xef,0x13,0x6d,0xc3,0x9,0xc5,0xad,0xb7,0x50,0x9c,0xe6,0x5b,0x36,0x93,0x65, + 0x4b,0x63,0x82,0x6d,0x9b,0x34,0x8d,0x93,0x2,0xa5,0x87,0x1a,0xc8,0x43,0xf5,0xa1, + 0x8d,0xb1,0xec,0xa6,0x6c,0x8a,0x56,0x80,0x25,0x4,0x7a,0x44,0xfb,0x8f,0x45,0x19, + 0xdf,0x9b,0x4,0x5b,0x70,0x80,0xfb,0x49,0xf4,0x31,0x83,0x8a,0x89,0x28,0x42,0x1e, + 0x61,0x36,0x68,0x9,0xb3,0xa0,0x9d,0x16,0x64,0x56,0x3,0x82,0xac,0xf,0xd4,0x30, + 0x73,0xdb,0x66,0x9d,0xd9,0xd0,0x26,0x2c,0xaa,0x3,0x2f,0xae,0xc4,0x9d,0xfa,0x47, + 0x6b,0x98,0x2b,0x4e,0x17,0x26,0x64,0xca,0x81,0xf4,0xf3,0xf7,0xb6,0xfa,0x5f,0xbf, + 0x79,0xef,0x4f,0xff,0x87,0x5f,0x78,0xe5,0xe7,0x36,0x46,0xcc,0x97,0x31,0xd8,0x93, + 0xf9,0x9f,0x33,0xa5,0x30,0xc3,0x2f,0x87,0x79,0x90,0x8a,0x46,0x74,0x50,0x60,0xd6, + 0x85,0x35,0xb8,0x7b,0x76,0x24,0xf3,0x5e,0xe1,0x98,0x3b,0x20,0xa5,0x88,0x25,0xcb, + 0x5c,0x90,0x77,0x2d,0xcf,0x25,0x79,0x62,0xdf,0x44,0x46,0xba,0x33,0x1a,0x14,0x44, + 0x5,0x8c,0xb3,0xc1,0x65,0xe,0x17,0x2c,0xd2,0xf6,0xd6,0x27,0x44,0xfe,0x3b,0x1c, + 0xb8,0xfd,0x6c,0x80,0x62,0x19,0xc6,0x88,0xc3,0x6d,0x26,0x5,0xca,0x89,0x85,0x98, + 0x75,0xf8,0xa0,0x2,0x8e,0x4a,0xf,0x23,0xfd,0xa,0xd4,0xcc,0x4d,0x5c,0x2,0xeb, + 0x53,0x71,0x42,0xf9,0xd7,0xcf,0xdc,0xb6,0xfd,0x9e,0x6c,0xac,0xdb,0xe1,0x61,0xe4, + 0x4,0xe5,0x8a,0x3a,0xb4,0xb1,0xee,0xdc,0x4a,0x87,0x5b,0x76,0x2e,0x23,0xef,0x5, + 0x24,0x8d,0x32,0xa2,0xc7,0x1f,0xf6,0xf7,0x8a,0x9d,0x3c,0x7,0x20,0x5b,0xde,0x90, + 0xc6,0x3,0xc,0x1e,0x4b,0x2a,0x8c,0x31,0xf9,0xb5,0xb9,0xca,0xdf,0x56,0xbb,0x1c, + 0x12,0x2b,0xa2,0x80,0x13,0x88,0x33,0xbe,0x83,0x23,0x61,0xa2,0x14,0x6a,0x6c,0xe, + 0xe1,0x3,0x63,0x53,0xec,0x90,0xf,0x40,0xd4,0x1e,0x44,0x57,0x6d,0xa,0x52,0x46, + 0x25,0xa1,0xcc,0x2,0xbf,0x3b,0x62,0x5b,0x26,0x67,0x31,0x8d,0x8d,0xb6,0x4d,0xe3, + 0xc3,0x5c,0x2,0xc3,0x13,0xe8,0x71,0xdb,0x66,0x60,0xda,0xf0,0x3b,0xb3,0xfe,0x94, + 0x83,0x30,0x0,0xfb,0xfb,0x9c,0x94,0x83,0xce,0x2d,0x36,0xdc,0xd2,0x40,0x4e,0xd5, + 0xba,0x78,0xae,0xe3,0x34,0xac,0x47,0xc0,0x19,0xe7,0xd8,0xe9,0x4,0x94,0x73,0x8f, + 0x8b,0x39,0x5c,0x43,0x3,0x7b,0xd1,0x67,0x31,0x58,0x8d,0xe7,0x6b,0x89,0x16,0x85, + 0x10,0x58,0x11,0x14,0xda,0x10,0x2a,0x2a,0xb8,0x74,0x25,0x54,0x18,0x60,0x32,0xfa, + 0x99,0xcc,0x7a,0x38,0x60,0x4a,0x5,0x83,0x19,0xaa,0x3c,0xda,0x5e,0xd8,0xbc,0x7d, + 0x2e,0x8c,0x8b,0x98,0xe9,0xe5,0xc5,0xe3,0xd3,0x31,0x22,0xb2,0xe,0x1e,0xe3,0x6, + 0x84,0x4a,0xa8,0xed,0x51,0xe,0xa0,0x3e,0x49,0x5a,0x5a,0xab,0xc8,0x79,0xb1,0xc2, + 0xb3,0x4f,0x92,0x63,0xe2,0xfd,0x10,0xe5,0x14,0x7d,0xac,0xa6,0xa4,0xbd,0x9f,0xc8, + 0x6c,0x63,0x25,0x60,0x30,0x5,0xd8,0xcd,0x6c,0xac,0x5b,0x8,0x50,0x4f,0xf2,0x49, + 0x8a,0x81,0x66,0xea,0x62,0xd5,0x3b,0xa,0x91,0xb9,0x52,0x0,0x9e,0x1d,0xef,0x15, + 0x87,0xb6,0x3,0x9c,0x93,0x43,0x12,0x41,0xd9,0x8f,0xd4,0x2,0xf5,0x37,0x20,0x7f, + 0x80,0x32,0x62,0x21,0x0,0xb3,0xad,0x1e,0xeb,0x6c,0x8b,0x5b,0xdb,0x64,0xe2,0x2c, + 0x56,0x54,0xa2,0xda,0x19,0x4b,0x2,0x3,0x63,0xf6,0x59,0x6b,0x60,0x80,0x17,0x33, + 0x75,0x8a,0xe7,0xea,0x3d,0x98,0x3b,0x57,0xf0,0xca,0x2,0x68,0xc5,0x2e,0x6f,0x7d, + 0x9e,0x9b,0x7a,0xc4,0x59,0xb4,0xdb,0x55,0xa0,0x23,0x8b,0x83,0xd3,0x21,0xe8,0x7c, + 0x5d,0xa3,0xb9,0x23,0x2,0x99,0xa0,0x6b,0x1d,0x91,0xc2,0x16,0x6d,0x8b,0xa3,0xf2, + 0xa1,0xa9,0x84,0x6c,0xf,0x41,0x5e,0x83,0xa3,0x13,0xa0,0xbb,0xc8,0xf6,0xcf,0x70, + 0xfa,0x19,0x46,0xa3,0xaf,0xe2,0x92,0x2d,0x36,0xb9,0x7f,0xe1,0xa1,0xc5,0xed,0x7e, + 0xe0,0x2e,0x69,0xba,0xbb,0xa7,0x74,0x90,0x84,0x24,0x25,0xf6,0x7e,0x60,0x9c,0xe1, + 0xd4,0xe6,0xec,0xc5,0x50,0xd1,0x8a,0x2d,0xd7,0x8e,0xe2,0xf7,0xd4,0x96,0xa9,0xcc, + 0x88,0x1d,0x66,0xb6,0xf9,0x48,0xa8,0x20,0x4c,0x2a,0x44,0xbc,0xe,0xed,0x17,0x78, + 0xe2,0x24,0xfb,0xd0,0x4c,0x98,0x14,0x61,0xe,0x16,0xaf,0xf0,0xdc,0xb1,0xe4,0xa3, + 0x1,0x22,0xd3,0x8,0x1a,0x7b,0xa9,0x10,0x42,0x3e,0x9f,0xa3,0x97,0xc1,0x4c,0xf8, + 0xd0,0x93,0xa3,0x11,0xa6,0x71,0x43,0x41,0x81,0x14,0x4f,0x3d,0xe5,0xf4,0xe3,0xfc, + 0xda,0x51,0xee,0xae,0x2e,0x6b,0x66,0x53,0xd5,0xaa,0x76,0x5f,0xff,0xe6,0x27,0xf7, + 0xae,0xff,0xfd,0x3f,0x7f,0x65,0x11,0x3f,0x60,0x98,0x54,0x1c,0x33,0x81,0x57,0x31, + 0x0,0x88,0xd5,0x17,0x6d,0x38,0x1,0x90,0x7,0x68,0xa0,0x80,0xb3,0xfa,0xef,0xb3, + 0xeb,0x8d,0x4f,0xb7,0x4e,0xac,0x75,0x95,0x26,0x13,0x90,0xd4,0xfc,0xde,0xce,0x82, + 0x1c,0xd0,0x2c,0x39,0x64,0x7b,0xe2,0x2e,0x56,0x37,0xb1,0x47,0xe,0x78,0x0,0x8a, + 0x20,0xd7,0x19,0x79,0xdc,0xe9,0x3a,0xc7,0x51,0x9e,0x37,0xf9,0x71,0x4,0x99,0xd0, + 0xee,0x6c,0xc6,0xb4,0x29,0x42,0x3d,0x75,0xd3,0x92,0xe0,0x52,0xe4,0x54,0x15,0x74, + 0x57,0xae,0x83,0xa6,0x34,0x1,0x9b,0x66,0x84,0x56,0x75,0xcd,0xde,0xa2,0xd0,0x4c, + 0xc5,0xb3,0x8a,0xea,0x97,0xf3,0x90,0xb5,0x49,0x3a,0xfa,0xdc,0x7,0x1d,0x41,0xea, + 0x94,0x35,0x3,0x10,0xaa,0x23,0xa5,0x61,0x8d,0x3,0x82,0xde,0xf,0x88,0x5a,0xe2, + 0x93,0x36,0xd7,0xdf,0xfe,0xe5,0x7d,0x3f,0xf5,0x36,0x40,0x2f,0xe3,0x33,0x58,0xf1, + 0xaa,0xad,0x21,0xe,0xee,0xe,0x4c,0x64,0x24,0x91,0x7c,0xad,0x7,0xde,0x60,0x52, + 0xcd,0x94,0x38,0x40,0xe8,0x22,0x23,0x9e,0xa8,0x89,0x2d,0xc8,0xbb,0x9a,0x6a,0x6a, + 0x4e,0x8d,0x80,0xc3,0x2c,0xa,0xc6,0xb1,0xb1,0xe6,0x90,0xdb,0x5f,0x13,0x39,0xe6, + 0xa2,0xf7,0x33,0x63,0x62,0x19,0xfd,0x1b,0x74,0xa,0x61,0x28,0x22,0x50,0x61,0xa1, + 0xbd,0x94,0xfa,0x31,0x4e,0x36,0xb7,0x5a,0x5d,0xd1,0x47,0x83,0xed,0x58,0x5d,0x19, + 0x26,0x25,0x98,0xf2,0xc,0xb0,0xaf,0xff,0xcd,0x5f,0xde,0xf7,0x53,0x81,0xce,0xc9, + 0xa1,0x6e,0x3a,0xff,0x64,0x17,0x39,0xe5,0xaf,0x7a,0xd4,0xe,0x8,0x3,0x41,0x9, + 0x3e,0x8,0x9d,0x87,0x34,0xae,0x63,0x61,0x7,0xb,0x3c,0x49,0xcc,0xa4,0x9f,0xbb, + 0xf3,0xc7,0x34,0x58,0x8f,0xe0,0x80,0x89,0x92,0xc9,0xc4,0xf7,0xc1,0x2,0x4f,0x79, + 0x18,0x37,0xc1,0xe,0xa8,0xaa,0xf9,0x66,0xb6,0xfc,0x93,0x17,0xff,0xdb,0xbf,0xfd, + 0xab,0xcb,0xff,0x29,0x76,0x7d,0x61,0xd6,0x3,0x74,0xef,0x44,0xf0,0xc8,0xac,0xa4, + 0xb1,0xa5,0x4f,0xe8,0xa,0x3,0x40,0xd0,0x96,0xc1,0xe6,0x9e,0x19,0x18,0xd2,0x51, + 0x45,0x12,0x6a,0x9c,0x51,0xdf,0xa2,0xba,0x26,0x66,0x26,0x41,0xfa,0xe7,0xa9,0x52, + 0x1c,0x54,0xda,0x78,0xa6,0x93,0xa6,0xa,0x90,0x2d,0x6,0x29,0x98,0x1c,0xe6,0x3a, + 0xe6,0x82,0xa7,0x4e,0x49,0xe7,0xa1,0x7b,0xca,0x4c,0x9b,0x72,0x9a,0xa7,0x4a,0x4d, + 0x94,0xbd,0x64,0xb6,0x4a,0x19,0x16,0x5,0xde,0x11,0x0,0x7d,0xa2,0x6a,0x15,0x9a, + 0xdf,0x9e,0xc1,0xb7,0x16,0x2a,0x40,0x26,0x35,0x3a,0xa9,0xea,0x38,0x57,0x68,0x84, + 0x7e,0x86,0x78,0x22,0x7,0xd2,0x30,0x3c,0x49,0x99,0xcf,0x4,0x16,0xba,0x7d,0x9e, + 0xe4,0xa0,0x4e,0x8,0x49,0xad,0xe0,0x54,0xab,0x9a,0xc1,0x7c,0x2e,0x49,0xa3,0xf9, + 0xe0,0xb2,0x23,0x88,0x4b,0xf8,0xa4,0xe,0x6f,0x95,0x1d,0x88,0xa2,0x2b,0x88,0x58, + 0x12,0x2f,0x6e,0xad,0xf8,0x81,0x86,0xd4,0x60,0x2a,0x15,0x7a,0xf0,0x37,0x37,0x7e, + 0x7e,0x36,0x3,0x89,0x4c,0xf6,0x7e,0xa4,0x56,0x40,0x67,0xe9,0xdc,0x49,0x98,0xd2, + 0x45,0xb8,0xf2,0xc4,0x1c,0xb4,0xec,0x87,0x4c,0xb6,0xb8,0x3d,0x38,0x6d,0x8d,0x61, + 0x7a,0x8d,0x82,0x5a,0x8f,0xc9,0x9f,0xa8,0x78,0xb0,0x68,0xab,0x6e,0x26,0x45,0xf4, + 0x16,0xc8,0xec,0x73,0xc4,0x56,0x7d,0xef,0x62,0x59,0xbb,0x42,0xb0,0xaf,0xf1,0x3c, + 0xf,0x7c,0x76,0xdf,0x46,0xc9,0x5d,0x3a,0x91,0x62,0x27,0xfc,0x30,0x6d,0xaf,0x55, + 0x35,0xb5,0x55,0x9,0xd7,0xce,0xb,0xba,0xb,0xf4,0x58,0x25,0x20,0x35,0x33,0x78, + 0x2c,0x5,0x3c,0x8,0x4c,0x2b,0xbc,0x7f,0xfd,0xab,0xfb,0x7e,0x9a,0x80,0x52,0xd, + 0x6c,0x23,0xc2,0x23,0x2a,0x29,0x1a,0xdb,0x9e,0x49,0xae,0x18,0x89,0xde,0x11,0xb8, + 0xe7,0xac,0x98,0xc6,0x3c,0x22,0x2a,0x24,0x3c,0x50,0xbc,0x4c,0xd,0x41,0x68,0x7b, + 0x40,0xf4,0xff,0x47,0xfb,0x80,0xe,0x31,0xea,0x68,0x7a,0x98,0xe6,0x45,0xfd,0xc2, + 0x21,0xd5,0xec,0x6e,0x39,0x48,0x43,0x46,0x61,0x76,0x0,0x5e,0x1f,0x9c,0xa0,0x42, + 0x74,0x80,0xc3,0xbc,0x20,0x73,0x7f,0x10,0xc1,0x12,0x76,0xd0,0x3d,0xe,0xa5,0xc0, + 0x52,0xc7,0x92,0xd7,0x3,0xb2,0x58,0xd7,0x21,0xcb,0xdf,0xa8,0x4b,0x50,0x80,0x19, + 0x79,0xa1,0x27,0x5,0xc5,0xc7,0xf9,0x5f,0x34,0x1a,0xba,0x6f,0xde,0xba,0xc,0x9c, + 0x64,0xd6,0x73,0xd9,0xd3,0x58,0xb0,0x8c,0x47,0xb8,0x67,0xbb,0x3e,0xe9,0xa8,0xb2, + 0x2a,0x52,0x10,0x82,0xe7,0x7c,0xaa,0x9f,0x81,0x91,0x2d,0xa4,0xe2,0xc6,0x29,0x7e, + 0xf2,0xe8,0x2b,0xc2,0xf4,0xdd,0x3,0x6a,0x3e,0xe8,0x37,0xc0,0x85,0x2a,0x3e,0xa6, + 0x61,0x3c,0x60,0x19,0x5d,0x69,0xa6,0x17,0x7a,0xf3,0x43,0x6f,0x87,0xfc,0xa8,0xd0, + 0x23,0x77,0x39,0x7c,0xa5,0xe8,0x57,0xb,0xe7,0xe9,0xd7,0x98,0x4f,0x4d,0x6c,0x3e, + 0x29,0x93,0x16,0x60,0x14,0x2,0xa9,0xbf,0x1f,0x97,0xe0,0x76,0xf0,0x98,0x37,0xfb, + 0xc,0x58,0x96,0xaa,0x1b,0xe8,0x48,0x5e,0x2a,0xa0,0x20,0x3c,0x11,0x32,0x3a,0xef, + 0xed,0x1f,0x4,0xb1,0xfd,0x40,0xf4,0x4f,0x9c,0x64,0x9b,0x4b,0xba,0x6,0xa0,0x11, + 0x2c,0x53,0xd9,0x74,0x4b,0x60,0x7a,0x98,0x79,0xad,0xa4,0x70,0xa0,0x98,0x54,0x3a, + 0xca,0x5c,0x1d,0xea,0xe0,0x3e,0x4c,0xe8,0xfb,0xac,0x7,0x8e,0x89,0xaa,0xd8,0xc, + 0xd1,0xeb,0x31,0xb0,0x4d,0x14,0x4,0x9a,0xc6,0xc4,0xcc,0xf5,0x2a,0x11,0x60,0xa5, + 0x12,0x9e,0x85,0xe9,0xcc,0x1f,0x89,0xc9,0x13,0xa0,0x43,0x7d,0xdf,0x2c,0x7d,0x97, + 0x3d,0x6,0x96,0xd1,0xaf,0x9f,0x16,0x41,0x35,0xc8,0x93,0xeb,0x60,0x1f,0x64,0xf6, + 0x4b,0x2e,0xdc,0xa6,0x3,0xcf,0x43,0xad,0x1e,0x62,0xc9,0x79,0xc8,0xb3,0x69,0x7, + 0x98,0xde,0xd5,0xf7,0x58,0x99,0x1c,0xcc,0xee,0x7b,0xc7,0x16,0xfb,0xa1,0xb8,0x51, + 0x79,0x86,0x7a,0x58,0xef,0x54,0x1,0xf,0xc6,0x1c,0x40,0xec,0x94,0xb9,0xa5,0x76, + 0xba,0x4,0x1d,0x4f,0x2,0xfa,0x81,0xd9,0x30,0xd9,0x98,0x9,0xcc,0x8,0xa4,0x45, + 0xec,0x93,0x4e,0x9e,0xcd,0xf4,0x14,0xa9,0xa9,0x40,0x5d,0xb5,0xb4,0x10,0xd3,0x25, + 0x23,0x19,0x5d,0x8c,0x25,0xb1,0xb9,0x8e,0x17,0x6c,0x42,0x29,0x29,0x60,0xfa,0x98, + 0x6f,0xfb,0x5a,0x19,0xce,0x89,0x9e,0x5a,0x83,0xbd,0xa0,0x35,0x5,0xb5,0x10,0xe6, + 0x6b,0xdf,0xd3,0x8a,0x38,0x22,0x50,0xd7,0xcc,0x40,0x74,0x4,0xe9,0xac,0x5d,0xe0, + 0xfc,0x9a,0xac,0xa6,0x0,0x55,0x71,0x70,0xd9,0xdc,0xaa,0x48,0x68,0x14,0x48,0x60, + 0x6a,0x15,0xe6,0x60,0x70,0x58,0x3a,0x3c,0xa3,0x2e,0x1,0x3c,0x6,0x38,0x40,0x64, + 0xa9,0xd3,0x77,0xf3,0x9a,0x2a,0xd7,0x44,0x63,0x40,0xab,0x4b,0xd,0xe4,0xde,0xd7, + 0x90,0x37,0x14,0xe0,0xd6,0x1c,0x1,0xea,0x3d,0xa8,0xf3,0xf8,0xfd,0x53,0x37,0x77, + 0xf,0xb2,0xd0,0xbe,0xe3,0x6,0x1b,0x53,0x6d,0xe0,0x45,0x54,0x98,0xcb,0x65,0x2f, + 0x92,0x38,0x18,0x20,0xff,0xf6,0xd3,0xff,0xf8,0xc0,0xda,0x35,0x4,0xda,0x78,0xd, + 0x3a,0x82,0x60,0xbd,0x11,0x4,0x1d,0x83,0xa1,0x97,0xe2,0x13,0x4c,0x98,0x5,0x96, + 0x97,0xa9,0x6e,0x8,0x60,0x7f,0xf7,0xd7,0xf,0xac,0x27,0x65,0x3,0xb9,0x4a,0x8c, + 0xa6,0x20,0xd6,0xb9,0x73,0x3e,0xdb,0xa5,0xbd,0x82,0x33,0x9b,0x88,0xbf,0x84,0x80, + 0x23,0x4b,0x10,0x73,0xb5,0x27,0x44,0xfa,0x91,0xb4,0x6b,0xc8,0x58,0x22,0x98,0x51, + 0xa4,0xd6,0xa9,0x4f,0xcc,0x2f,0x8,0x41,0xd8,0x67,0x97,0xb4,0x81,0x60,0x87,0xdc, + 0xe1,0x92,0x84,0x6e,0xba,0x7f,0x73,0xca,0x4a,0x6b,0x2b,0x86,0x20,0x57,0x3b,0x21, + 0x5a,0xcb,0x7,0xb4,0xab,0xc7,0x5c,0x70,0x2a,0x57,0xa0,0x80,0xb,0xc4,0x59,0x9e, + 0x85,0xf9,0x8c,0x67,0xc5,0x86,0xd0,0x26,0x81,0x7,0x4d,0xfd,0x80,0x12,0x47,0x9a, + 0x11,0x28,0x98,0x6b,0x48,0x7f,0xc6,0xb6,0xcb,0xc4,0xaf,0x3b,0x72,0x8b,0x63,0xb, + 0xc0,0x19,0x44,0xc9,0xc6,0x11,0x2e,0xec,0x9,0xd6,0x27,0xef,0x7a,0x3,0x1e,0x2a, + 0x14,0xee,0x8a,0xf6,0x4a,0x4,0xb0,0x83,0x2d,0x77,0x3a,0xbd,0x7a,0xcb,0x19,0x74, + 0x18,0x84,0x52,0x7f,0x56,0x59,0xb6,0xa0,0x4a,0x23,0x11,0xc7,0x1,0x10,0xaa,0x80, + 0x20,0x26,0x9e,0x6,0xd8,0x42,0x75,0x65,0x66,0x5b,0xa5,0xef,0x15,0xdf,0xf,0xbc, + 0xd2,0x79,0x75,0xce,0x55,0x83,0xef,0x41,0xc9,0xf3,0x56,0xd8,0x8f,0x57,0x1e,0xf3, + 0x71,0xc5,0x39,0x10,0xb5,0xa3,0x9d,0x24,0x9d,0x11,0x6,0xa2,0x36,0xd0,0x55,0x68, + 0xf5,0x3,0x80,0x87,0xe3,0x1b,0x0,0xa2,0xb0,0xda,0x80,0x1d,0xfa,0xb4,0x10,0x94, + 0x6b,0x61,0x34,0x7d,0x71,0x55,0xa4,0x83,0xf2,0x8b,0x77,0x1e,0xb2,0x3b,0x77,0x77, + 0x48,0xf5,0x31,0xc,0xee,0x28,0xf1,0x6c,0xc9,0x57,0xb7,0xb0,0x68,0xe,0x95,0x5e, + 0xe7,0xc1,0x7d,0x48,0xcc,0xdd,0x38,0xef,0x52,0x1,0xc,0x1a,0xa6,0x71,0x42,0x10, + 0x62,0xec,0x87,0x39,0xb,0x61,0x45,0x76,0x41,0xcd,0xcc,0x46,0xf0,0x35,0xa9,0x28, + 0xe1,0x3d,0x91,0x34,0xc9,0xd4,0x24,0xb1,0x38,0x78,0x72,0x14,0x53,0xc8,0x50,0x93, + 0x54,0xe0,0xce,0x5a,0x1,0x8a,0x6a,0x1a,0xf5,0xbb,0xdc,0x4,0x51,0x40,0x18,0xf, + 0x33,0x2b,0x38,0x51,0xbc,0x25,0x93,0xcd,0x5d,0x2d,0x60,0x20,0x64,0xd,0xc,0x21, + 0x38,0xa4,0xce,0x87,0xf,0x3e,0xc4,0x98,0xa0,0xef,0x4f,0x15,0x65,0x50,0x3e,0xe0, + 0xee,0x26,0x92,0xf5,0x5,0x49,0x42,0x3d,0x96,0x2,0xed,0x1f,0x7c,0x54,0x4c,0xec, + 0xd2,0xc9,0x8c,0x4,0x19,0x31,0x3b,0x59,0xa8,0x3a,0x48,0x82,0x9b,0x92,0x2c,0x2e, + 0x6e,0x88,0xc2,0xb6,0x2f,0xaa,0x50,0x24,0x89,0x33,0x69,0x3e,0x82,0xb5,0x79,0x54, + 0x64,0xc5,0x9e,0xe4,0xc6,0xa4,0x7a,0x2d,0x8f,0xc,0x24,0x9,0x57,0x4a,0xcf,0x5f, + 0x83,0xaa,0xc8,0x17,0xf8,0xa4,0xfd,0x66,0x41,0x95,0x29,0xcd,0xb1,0x7c,0x54,0x54, + 0x2,0x15,0x53,0x64,0xe1,0x68,0xed,0x13,0x29,0xce,0x27,0xa9,0x79,0x6c,0x93,0x26, + 0x70,0x3,0x9b,0xda,0xab,0xfd,0x1f,0x62,0x10,0xea,0x46,0xf,0x16,0x84,0x41,0x3c, + 0x74,0x2e,0x6c,0x2e,0xfb,0x38,0x5,0xae,0xa0,0x7b,0x0,0xc8,0xf7,0xf4,0xd9,0x20, + 0x26,0x2a,0x81,0x4c,0x3a,0xa2,0x9,0xb0,0x91,0xdb,0x79,0x59,0xfe,0xd0,0x6c,0x32, + 0xfd,0xc,0x41,0x9c,0x38,0x94,0x8,0xe8,0xf0,0x78,0x8f,0x1c,0x53,0xd8,0xa9,0x3a, + 0xc5,0xe5,0x68,0x6,0x8f,0x5a,0x29,0x41,0xb3,0x5b,0x14,0xbc,0x8a,0xa9,0x71,0xc4, + 0x68,0x81,0x52,0xe6,0x2c,0xc3,0xaf,0x1e,0x80,0xe3,0xf3,0x2a,0x40,0x1a,0x95,0x60, + 0x40,0xfa,0x40,0xe5,0xb7,0xb3,0x84,0x5a,0x5d,0x43,0xff,0xf0,0xd3,0x87,0xff,0xc1, + 0x7,0x8f,0x73,0x46,0x2f,0x41,0xe,0x8a,0xa0,0x34,0x21,0x2,0x28,0x83,0x3e,0xbb, + 0xbb,0xab,0x70,0x71,0xc1,0xe6,0x8c,0x64,0x6a,0xd5,0x79,0x6f,0xc3,0x93,0x86,0x3d, + 0xfb,0xb5,0xef,0x20,0x24,0xef,0x65,0xda,0x46,0xa9,0x79,0x1a,0x3a,0x39,0xeb,0x78, + 0xd4,0xf1,0xb,0xe4,0xbc,0xe0,0x6e,0x8,0x40,0x15,0xec,0x28,0x1b,0xdc,0x52,0x67, + 0x8e,0xf1,0xe5,0xd6,0x50,0x51,0x4e,0x87,0x60,0x4,0x10,0xa9,0x6b,0x1,0xeb,0xf1, + 0xf,0x97,0x41,0x4d,0xf0,0xf7,0x68,0x5e,0xc7,0xce,0x2e,0x79,0x24,0xa,0xe0,0x51, + 0xe8,0xe,0xa2,0x5f,0x3f,0x18,0x22,0x3b,0x46,0xa1,0xdf,0xcb,0x1e,0xaf,0x20,0x6a, + 0x71,0x3,0x4f,0xc4,0xb8,0x9c,0x8a,0xb3,0xd8,0xdc,0x19,0xc8,0xc5,0xdd,0x84,0x58, + 0x98,0x8c,0xa8,0xec,0x13,0x0,0xe1,0x8,0x56,0x81,0x2e,0x25,0x75,0xf,0x42,0xd5, + 0x6e,0xd3,0x52,0x66,0xb4,0xaf,0xbd,0x32,0xce,0x7a,0xc8,0x6a,0x53,0x1a,0x1f,0xad, + 0xf2,0x80,0xf3,0xcc,0xa3,0xfd,0x5e,0xdc,0x23,0x69,0x8b,0x5b,0x7,0xe5,0x99,0x59, + 0x39,0x89,0xb4,0xf3,0x9,0x3,0xe2,0xd8,0x93,0x38,0x6b,0x8d,0x23,0x67,0x41,0x6b, + 0xa3,0x21,0x39,0xa5,0xbe,0xbe,0x37,0xd4,0x44,0x61,0x6f,0x73,0x77,0xea,0x96,0x41, + 0x24,0x37,0x7,0x62,0xd3,0x6d,0xf3,0xd4,0x85,0x87,0x71,0x3f,0xc7,0x6c,0x2a,0x13, + 0x1b,0xd0,0xf2,0xc8,0x66,0x3b,0xc2,0x14,0x41,0x80,0x32,0x63,0x3e,0x7b,0x47,0x88, + 0x49,0x59,0x7e,0x4f,0x4d,0xa6,0x82,0xa0,0x9e,0x99,0xc1,0x4e,0x86,0x8e,0x9f,0x5, + 0x8,0x36,0xf3,0xfd,0x7a,0xdb,0xf2,0xef,0xff,0xe6,0x81,0x35,0x7d,0x55,0x4e,0xeb, + 0xe1,0x73,0x34,0x8c,0xa4,0x60,0x5a,0xe5,0xc5,0x18,0x18,0x65,0xa,0x15,0x34,0x8f, + 0x24,0x7a,0xe3,0x52,0xe1,0x21,0xa6,0x90,0x7,0xfa,0xc3,0xa9,0x77,0x30,0xe,0x91, + 0x83,0x96,0xae,0xc8,0xf6,0xe1,0x13,0x2d,0x6b,0x46,0x9d,0x32,0xf,0xff,0x16,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xfb,0x44,0x4a,0xd0,0x66,0x12,0xb7,0x1e,0xf8, + 0xe1,0x2c,0xab,0x9a,0x6d,0x80,0x42,0x1a,0x9e,0xf5,0xcc,0x59,0xe5,0x29,0x51,0x1f, + 0xa6,0x36,0xe1,0x59,0xb8,0x67,0xc4,0xe6,0x22,0x46,0x35,0xa9,0x11,0xca,0x98,0x81, + 0x30,0xef,0x53,0x5a,0x9a,0x7,0x8d,0xf5,0xb1,0x7d,0xfc,0x60,0x8d,0xa4,0xb3,0x6a, + 0x0,0xd2,0x95,0xc9,0xf3,0x7c,0x25,0xcf,0xf5,0x4d,0x6,0xea,0x54,0x2,0xf6,0xf7, + 0xeb,0xe5,0xbf,0x93,0x24,0xa7,0xa0,0xb7,0xf7,0xda,0x41,0x47,0x17,0x9,0xb6,0x14, + 0xad,0x3f,0xda,0x69,0xd3,0xee,0x15,0x4,0x47,0x6b,0x88,0xa4,0x9c,0xa0,0xd5,0x36, + 0xd8,0x8c,0x44,0x9c,0xb,0x67,0x92,0x24,0xed,0x34,0xdf,0xd1,0xb0,0x3,0x67,0x5c, + 0xb9,0x5d,0xc3,0x72,0x7b,0x6f,0x45,0xec,0xaf,0x19,0xcd,0x83,0xc6,0xab,0xde,0x3b, + 0xbb,0xa5,0x7a,0xdc,0x36,0x2c,0xd1,0x9e,0xc9,0xf8,0xb6,0x8d,0xa9,0x34,0x8,0x6d, + 0x12,0x30,0x5a,0x1e,0x93,0x7c,0xb9,0xa1,0x1,0x9b,0x50,0xd0,0x23,0x69,0xa1,0xca, + 0xc9,0x89,0xd9,0xe5,0x34,0xe2,0xf0,0x19,0xcd,0x2f,0x36,0x2b,0x68,0x3f,0x4f,0x45, + 0x6c,0x41,0xa,0xdf,0xde,0x45,0x38,0x10,0xf5,0x73,0x99,0x2a,0xe5,0x11,0xbf,0x40, + 0x6b,0x8b,0xaa,0x14,0x9a,0x16,0x70,0xc7,0xc8,0xec,0x1f,0xfd,0xdc,0xb,0xff,0xdd, + 0xdf,0xff,0xdd,0x43,0xff,0xa9,0xe6,0x80,0xca,0xa7,0xf0,0x96,0x4,0x94,0x9d,0x7d, + 0x60,0xde,0x2b,0x47,0x99,0x7f,0x23,0x4a,0x59,0x93,0x7e,0x22,0x2c,0x94,0xab,0xa3, + 0xdd,0x4e,0xaf,0xd7,0xd9,0x6,0x2,0xef,0xa9,0x26,0x5a,0xe8,0x9d,0x28,0x1a,0x6e, + 0xdb,0xc4,0x8b,0x3,0x89,0xfb,0xa3,0xa3,0x2,0x2,0x99,0x82,0x48,0xd,0x56,0x5d, + 0x1f,0x25,0xf1,0x6a,0x47,0x87,0x94,0x67,0xce,0x76,0xb1,0xe0,0xc0,0xde,0xb4,0x15, + 0x50,0x33,0xa,0x6b,0xd8,0x90,0x7e,0xcd,0x27,0xea,0xcd,0xf0,0xa0,0x8b,0x3f,0x2, + 0x41,0x4f,0x44,0xf6,0x31,0xdd,0xb8,0x58,0xef,0x83,0x75,0xc2,0xd,0xf8,0x20,0x8c, + 0x90,0x61,0xb1,0xa2,0x8b,0x38,0xfd,0xa,0x3c,0x79,0x8b,0x85,0x9f,0x82,0x3d,0xd, + 0x38,0x3c,0x33,0x22,0xe0,0x6f,0xca,0x92,0x3c,0xc8,0x9c,0x4b,0x81,0x49,0x3e,0x29, + 0xe,0x49,0x14,0x4e,0x4a,0x55,0xba,0x85,0x71,0x56,0x44,0xa4,0xcf,0x48,0x12,0xc8, + 0x5d,0x5d,0xa5,0x47,0x5,0x94,0x1,0xe2,0xe2,0x88,0x63,0xf3,0x20,0x54,0xe3,0x18, + 0xa8,0x3e,0xf9,0x42,0x63,0x6,0x99,0x58,0x7a,0x3d,0x98,0x53,0x68,0xa,0x49,0x86, + 0x36,0xbe,0x7d,0xcc,0xa7,0x29,0xff,0x43,0x0,0x3f,0xb1,0xfe,0xfc,0x30,0x98,0x71, + 0x8b,0xfe,0xea,0x49,0x44,0x7f,0x96,0xcb,0x94,0x9,0xfd,0xa1,0x78,0x32,0x9e,0x41, + 0x60,0xae,0x7b,0xd8,0x16,0x46,0x1d,0xb,0xb,0x57,0xdb,0x9c,0xb6,0x92,0xcc,0x25, + 0x4b,0x10,0x12,0x10,0xae,0x7f,0x27,0xfe,0x79,0xa4,0xa7,0x10,0xa7,0xbf,0x83,0x6e, + 0xa3,0x91,0x4c,0x18,0x20,0x7a,0x43,0xbd,0x7a,0x18,0xe5,0xf4,0x4,0x77,0xb4,0x19, + 0x1d,0xd9,0xbc,0xa5,0xbd,0xdd,0x3f,0xfc,0xf4,0xf2,0x6a,0xb2,0xf1,0x18,0xcb,0xe0, + 0xed,0xff,0x74,0xf4,0xcb,0x5e,0x2,0x4c,0xdb,0xea,0x3f,0x83,0x6a,0xd1,0x0,0x88, + 0x92,0x32,0x4e,0x33,0xd4,0x7e,0x3b,0xca,0x88,0x62,0xd,0x50,0xd4,0xc1,0x2b,0xc5, + 0x85,0x9b,0xd8,0xb,0x62,0xaf,0x8f,0x9d,0xf3,0xec,0x50,0x6,0x9,0xc6,0xd8,0x1b, + 0x86,0xa6,0xcb,0x66,0x74,0xb5,0x6b,0x6f,0x8d,0xd4,0x3a,0xf0,0x4,0xd7,0x1a,0x2d, + 0xf0,0xef,0x43,0x5e,0xab,0xfc,0x26,0xf8,0x56,0xf1,0x6f,0x80,0xd9,0x36,0x66,0xc6, + 0x40,0x41,0xff,0x1c,0x47,0xe0,0xb3,0x33,0xc8,0x5a,0xf1,0x4,0x28,0x10,0x14,0xa3, + 0x1b,0xb,0x2e,0xd6,0xe0,0x1,0xef,0x2c,0x2,0xa2,0x7f,0xc1,0x87,0xd6,0x7d,0x17, + 0x94,0xf4,0xa2,0xa3,0x2d,0x1b,0x53,0xd3,0x74,0xde,0xd8,0x6c,0x34,0xc5,0xf5,0x60, + 0xa7,0xe2,0x35,0x62,0xac,0x27,0x1c,0x88,0x8b,0xf4,0x34,0x57,0xce,0x45,0x56,0xb3, + 0x7,0xa8,0x75,0x8f,0xb1,0x5b,0xdb,0xca,0x5,0xd,0xa4,0xe5,0x0,0x3d,0x4,0x90, + 0x20,0x69,0x1f,0xeb,0x29,0x90,0x66,0xdb,0x74,0x87,0xd6,0xf7,0x92,0x7d,0x4a,0x64, + 0xc3,0x3d,0x3b,0xea,0xac,0x49,0xc,0x3b,0x54,0xce,0x76,0xc0,0xc5,0x3b,0xe9,0x2c, + 0x83,0x7b,0xc3,0x3,0xdb,0xd1,0xe5,0x55,0x26,0x8,0xe1,0x46,0xcd,0xac,0xd0,0x8c, + 0x50,0x47,0x4c,0x4c,0x65,0x90,0xdc,0xc7,0x50,0x4e,0x14,0x1d,0x37,0xa5,0xee,0x9f, + 0x5b,0x1,0xe2,0xb1,0x41,0x73,0x65,0x95,0xa5,0x2f,0x0,0x86,0x2f,0xb2,0x52,0x52, + 0xcd,0x64,0x9c,0x47,0x4c,0xe7,0x81,0x8a,0xea,0x18,0x13,0x93,0x74,0xc4,0xb8,0x2e, + 0x14,0x7e,0x68,0x92,0x3a,0xa0,0xf7,0xcf,0xe6,0x63,0x41,0xb,0x78,0x8a,0x45,0xec, + 0x94,0x46,0xc6,0x6,0xc5,0xf1,0xb0,0x5b,0xf0,0x96,0x8,0x37,0xd1,0x61,0xd1,0xf5, + 0x6b,0xca,0x43,0x8f,0x88,0x40,0x9f,0x60,0xf1,0xb9,0xd,0x16,0x47,0xb5,0x9e,0x44, + 0x50,0xb4,0xbd,0xee,0x82,0xf9,0x8e,0xb3,0x75,0xed,0x21,0x6b,0x55,0xe4,0x4,0xd9, + 0xcf,0x3e,0x8f,0xe0,0xd1,0x6c,0xb1,0xe4,0x84,0xa6,0x9e,0xb4,0x41,0xd3,0x4b,0xdc, + 0xd9,0x4c,0xdc,0xd4,0x10,0x38,0xf6,0xa3,0xaa,0x74,0xb9,0xf3,0x3e,0xf3,0xc8,0x5, + 0xb9,0xea,0x90,0x9e,0x70,0xb4,0xe7,0x92,0x81,0x4f,0x3d,0xc9,0xc1,0x7c,0x78,0x36, + 0x99,0x41,0x64,0xd,0x58,0x4e,0x3c,0xc2,0xb3,0xeb,0x89,0x80,0xab,0xcc,0x2b,0x3f, + 0x13,0xd1,0xca,0xe6,0x83,0xdd,0x54,0x45,0x6c,0xa,0x46,0x4e,0x92,0x3,0x8,0x5d, + 0x17,0x74,0xfd,0x7e,0x49,0x3,0x3c,0x9a,0xe8,0x98,0xf9,0x84,0x26,0x2a,0x6a,0xb3, + 0x86,0x9,0xe7,0x3e,0x6b,0x53,0x77,0x51,0x8e,0x82,0xd0,0xda,0x1e,0x6d,0x76,0x77, + 0x58,0x29,0xf4,0x76,0xdd,0x3a,0x9b,0xad,0xb1,0xc6,0xe1,0x59,0xcf,0xb8,0x2c,0x98, + 0x50,0xcc,0xa,0xcd,0x36,0xb9,0x95,0x4f,0x18,0xa,0x24,0x7d,0x6f,0xea,0x68,0xf9, + 0x84,0xd6,0xd4,0x27,0xa7,0xb4,0x39,0x5a,0x38,0x74,0xdf,0xbc,0x5e,0x17,0x29,0xd0, + 0x44,0x1e,0x39,0x71,0x74,0xea,0x17,0x75,0x3a,0x40,0x77,0x4a,0xb0,0x53,0x22,0xd3, + 0x6,0x9f,0x1e,0xcb,0x5b,0xed,0x16,0xa1,0x20,0x98,0x4d,0xec,0x32,0x5d,0x3d,0x20, + 0xb5,0xe9,0x14,0xa8,0x8a,0x1c,0xf,0xa5,0xa0,0x65,0xb5,0x4,0x70,0x6b,0x78,0x8, + 0x46,0xee,0x93,0xc5,0xa2,0x47,0xdd,0xbf,0x19,0x1a,0x19,0x85,0x44,0x62,0x1a,0x80, + 0xb4,0xa0,0x8d,0xf2,0x8a,0xb3,0x54,0x6c,0x8b,0xb5,0xb1,0xfa,0x72,0x63,0x3d,0x55, + 0x27,0xf6,0x40,0x6b,0xe9,0x76,0x68,0xb,0xc5,0x20,0x61,0x34,0xf4,0x46,0x55,0x19, + 0x2b,0xd6,0xe5,0x80,0xa9,0x6b,0xbf,0x40,0xfd,0x24,0xb5,0xb0,0xe9,0x53,0xdb,0x42, + 0x7a,0x5,0x4,0x46,0xc0,0x0,0x85,0x81,0xa,0xf2,0xa,0x8e,0x24,0x9,0xd0,0x13, + 0x85,0x3a,0xc0,0xc0,0x18,0x29,0x17,0x84,0x60,0x2,0xe9,0x60,0xee,0x2,0xe1,0x35, + 0x79,0xec,0x31,0x48,0x3b,0x89,0x8a,0x70,0x18,0xb4,0xb5,0xd1,0x99,0x2a,0xda,0x52, + 0xe5,0xfe,0xbe,0xf5,0xa4,0x61,0x8,0x93,0x7b,0x17,0xb9,0x45,0xcf,0xf8,0xd,0xd, + 0x1f,0x52,0xf1,0x12,0x64,0x10,0x27,0xce,0x2f,0x30,0xaf,0x6a,0x14,0x95,0xaa,0x51, + 0x8b,0x1b,0xa7,0xc4,0xba,0xae,0x7f,0x36,0xe3,0xf0,0xc9,0x5c,0x58,0x5a,0x43,0x2e, + 0xe0,0xd5,0xa8,0xa5,0xcf,0xb6,0xe1,0x48,0x88,0xfa,0xb0,0xeb,0x41,0x40,0xf2,0x30, + 0xd0,0x27,0x31,0xb7,0x68,0xf7,0x1c,0xcb,0x3a,0x6,0xe5,0xb5,0xdf,0x3b,0xc9,0xcf, + 0x51,0xfc,0xbe,0x63,0xac,0x53,0x7f,0x3,0x55,0x98,0xe2,0x56,0x6c,0x74,0xea,0x3, + 0x8b,0xf0,0xc6,0xee,0xae,0xfa,0x9e,0xb,0xad,0xd,0x1,0x34,0xe7,0x6c,0x43,0xa, + 0xe1,0x3d,0xf6,0x76,0x9,0xdb,0xef,0xa5,0xf1,0x46,0x16,0x78,0x1,0x45,0x24,0xf, + 0x8d,0x5a,0x31,0x98,0x89,0x22,0x25,0x51,0x9a,0xd6,0xc7,0x2c,0x2d,0x66,0xaf,0x48, + 0xc6,0x2c,0x38,0x60,0x10,0x45,0xde,0xdb,0xe4,0xe1,0x1d,0x49,0xbd,0x9e,0x44,0x17, + 0x4c,0x54,0x9c,0x34,0x2f,0xd1,0x56,0xb3,0x4d,0xa4,0x49,0x33,0x4c,0x69,0xb4,0x8a, + 0x98,0x22,0x12,0x7b,0x33,0x1e,0x67,0xe1,0x4d,0x1,0xce,0x4d,0xb2,0xc9,0x9c,0xe8, + 0x79,0x0,0xfa,0x50,0xfb,0x4d,0x78,0xcf,0xc1,0x6b,0x5d,0x12,0x47,0xae,0xe0,0x3d, + 0x89,0x31,0x52,0x2,0x1,0x91,0x47,0xec,0x1,0xa7,0x7d,0xaf,0x12,0x20,0x59,0x30, + 0x52,0x7d,0x34,0xc3,0x89,0xe1,0x34,0xdd,0x3,0x52,0x4f,0xd1,0x6a,0x71,0x39,0xa8, + 0x32,0x6a,0x58,0xcd,0xf3,0x81,0xf1,0x7c,0xf6,0xf6,0x73,0x10,0x90,0x90,0xa4,0xc5, + 0x67,0x1c,0xca,0xbd,0xa8,0xb6,0xcd,0x87,0x73,0x85,0x7b,0xd,0x9e,0x8e,0x1,0xe3, + 0xdf,0xd3,0xc5,0x6d,0x7f,0x1e,0xc5,0xb,0xd3,0xfa,0x3b,0xf9,0xb2,0xd4,0xb5,0xb6, + 0xb9,0x3b,0x8a,0x61,0x17,0xad,0xe1,0x13,0x63,0x7f,0x29,0xef,0x9,0x38,0x82,0x4e, + 0x2c,0x45,0xb1,0x1e,0x58,0x4b,0x74,0x19,0x19,0x1a,0x70,0x60,0x24,0x81,0x66,0xd7, + 0x5c,0xbe,0x7b,0x72,0x44,0x46,0x50,0x81,0xe,0xb2,0x94,0xed,0xf0,0x2b,0x31,0x8, + 0xb6,0x9e,0x50,0xe1,0xa3,0xc3,0x32,0x25,0xad,0xc6,0xfb,0x1e,0xa1,0x6b,0x4,0xa3, + 0xb6,0x68,0xe9,0x43,0xe5,0xfa,0x9b,0x5,0x70,0x77,0x1f,0x15,0x68,0x17,0x71,0x18, + 0x5d,0x41,0xa6,0x42,0xb6,0x84,0x40,0x47,0x38,0x66,0xd8,0x1c,0xa9,0xe2,0x6d,0x95, + 0x38,0xe1,0x3a,0x6a,0xc0,0x6,0x3c,0x2,0x61,0x46,0x4f,0xa9,0xd3,0xce,0xaa,0x7c, + 0xd0,0xc0,0x66,0xd,0x4d,0x4,0xc,0xf1,0x8d,0xda,0xb0,0xaa,0xbb,0xaa,0xb0,0x55, + 0x9b,0x95,0x52,0x30,0xd4,0x7,0x89,0xad,0x71,0x82,0x51,0x20,0x7,0x9d,0x80,0x3a, + 0xff,0x8c,0xee,0x4f,0xa1,0xef,0x42,0xd1,0x28,0x5,0x13,0x73,0x42,0xf6,0x8e,0x39, + 0x77,0xef,0x4,0xb9,0x20,0x51,0x3b,0xfe,0x82,0x39,0x96,0xa2,0xe5,0x0,0xf7,0xad, + 0x6a,0xd8,0x60,0x82,0x77,0xf5,0x21,0x1f,0x35,0x0,0x8f,0xad,0xdd,0xea,0x59,0x91, + 0xa1,0x4d,0x7,0x61,0xda,0x85,0xb1,0xc1,0x78,0xa1,0xab,0xe0,0x89,0xa9,0x76,0x49, + 0x4d,0x0,0x8d,0x73,0x37,0xb8,0xa8,0x9e,0xc9,0xc7,0xa,0x2c,0xb9,0xf4,0xd6,0xb5, + 0x7f,0x92,0x41,0x44,0xe2,0xf7,0xed,0x1a,0xe4,0x84,0x10,0x1f,0xfd,0x7f,0x6d,0x62, + 0xf7,0x16,0xe6,0x6e,0x19,0x69,0x65,0x53,0x3a,0xaa,0x99,0xae,0x79,0x91,0xe4,0x84, + 0x25,0xa1,0x9a,0x88,0xc,0xd8,0xd1,0x41,0xd6,0x29,0x11,0xd3,0xd1,0x1,0xcd,0x38, + 0x1a,0xa0,0x51,0x67,0xf2,0x10,0x91,0xd,0x67,0x9f,0x5f,0x44,0xcf,0x68,0xef,0xf4, + 0x2e,0x2e,0xd8,0xbb,0xe1,0x0,0xb,0x5a,0xa4,0xbe,0xd3,0x84,0x8a,0x30,0x21,0x78, + 0x77,0xb1,0xff,0x89,0xf5,0xeb,0xa4,0x19,0x18,0x86,0x9f,0x91,0x47,0x19,0x1b,0xe3, + 0xec,0x52,0x9d,0x67,0xb8,0x6a,0x76,0x8b,0x38,0x49,0x4a,0xd4,0xb1,0x91,0xa8,0x81, + 0x13,0x6e,0x53,0xaa,0xd4,0x90,0xad,0xc5,0x4c,0x63,0xde,0x66,0x9d,0xe,0x64,0xb3, + 0x3d,0x4b,0xe4,0x7d,0x4e,0x62,0x20,0xcc,0x81,0xaa,0xc9,0xda,0x5a,0xe4,0x6e,0xa6, + 0x42,0xa,0xb5,0xf5,0x8d,0xb4,0x58,0xb,0x79,0x7c,0x20,0xd8,0x7c,0x34,0x64,0x31, + 0xcd,0x2,0xb,0x74,0x4,0x59,0xc,0xa9,0x3f,0x8c,0xe8,0xae,0xe0,0xed,0xc,0xaf, + 0x71,0x77,0x8e,0x9f,0x2c,0x9d,0xb0,0x4b,0x69,0xd3,0xe6,0xbe,0x97,0x9d,0x80,0x6d, + 0xd5,0x42,0x7,0xee,0xbd,0x7e,0xc1,0x48,0x48,0xf6,0x1b,0xb3,0xf5,0x96,0x59,0x31, + 0xc0,0x7d,0xf3,0x1a,0x90,0xbc,0x83,0xd,0xd1,0xb0,0xbd,0x1e,0xd6,0x64,0x40,0xdf, + 0xd7,0x8e,0x23,0xb5,0xde,0xc1,0x6,0x5f,0x3d,0x52,0x16,0x6,0x8d,0x34,0x6c,0x82, + 0xd3,0xc8,0x63,0xe0,0x8c,0xc1,0x23,0x3b,0x9f,0x61,0xb2,0xb9,0x1c,0xe3,0x43,0x89, + 0xf9,0x95,0xaa,0x7a,0xb0,0xdf,0x82,0x32,0x1,0x88,0x9a,0x99,0x6d,0x9e,0xbd,0x34, + 0x35,0xb8,0xc0,0x9c,0x24,0x85,0x3b,0x38,0xb4,0x57,0xe8,0x5,0x5,0x9b,0x6d,0xe3, + 0xca,0x14,0xd0,0x53,0xf3,0x1c,0x41,0xfb,0xd5,0x86,0x4b,0x1,0xa3,0xbc,0xd5,0x51, + 0x6d,0xc,0x30,0xca,0x90,0xd9,0x25,0x2d,0x63,0xd0,0x6c,0xda,0x69,0x9d,0x55,0x60, + 0x47,0xeb,0x4c,0x74,0xe4,0x18,0x86,0xf1,0x3c,0x5,0xf4,0x51,0x80,0x21,0x59,0x79, + 0x1,0x85,0x4e,0xa9,0x13,0x50,0xea,0xe4,0x8c,0xdd,0xa2,0x74,0xcb,0x31,0x43,0xa7, + 0x96,0x7b,0xe9,0xd0,0x36,0x9,0x98,0x6c,0x4a,0x49,0x63,0x40,0x87,0x9f,0xa0,0xfa, + 0xb6,0x95,0xc6,0x5e,0xd7,0x2c,0x6f,0x74,0xef,0x8a,0xe3,0x7b,0x86,0xdb,0x3a,0x38, + 0x27,0xfa,0xd8,0xa2,0xe6,0x50,0x54,0x43,0x96,0xf6,0x76,0xfb,0xa8,0x84,0x4c,0xd8, + 0xf7,0x31,0x94,0x3b,0xd3,0x5e,0x19,0xab,0xe9,0x7d,0xe3,0x13,0x4b,0xa9,0x7,0xf3, + 0xb1,0x73,0x32,0xc1,0x2a,0x14,0x28,0x41,0x61,0xae,0x39,0x78,0x8e,0xae,0xa9,0x36, + 0xc7,0xd2,0x7e,0x34,0xb2,0xd1,0xb5,0xa6,0xe5,0xde,0x16,0xed,0xa6,0xd5,0x73,0x6c, + 0x7c,0xba,0xb7,0x1d,0x1c,0xe5,0x47,0x27,0x5c,0xe3,0x24,0x7f,0xea,0xa1,0x46,0xb4, + 0xe8,0xeb,0xa2,0xc8,0x4f,0x46,0xb1,0x4e,0x6,0x2f,0xb4,0xae,0x93,0x7e,0xb8,0x25, + 0xca,0xbf,0xce,0xf7,0x19,0xd1,0x16,0xab,0xc1,0x1,0x7d,0x82,0x28,0x81,0xf,0xa0, + 0x8e,0xcb,0x1c,0x71,0x38,0xfd,0x40,0x66,0x21,0x98,0x79,0x3b,0xbb,0x22,0xf9,0xa4, + 0x55,0xce,0x1a,0xf4,0x3e,0x3,0x25,0xea,0xc8,0x1d,0xd3,0xd9,0x55,0x2c,0x9f,0xf, + 0xb9,0x5e,0x23,0xd1,0x53,0xe0,0x39,0x54,0xa,0xbe,0x46,0xae,0x17,0x13,0xde,0xb, + 0x72,0xce,0x62,0x33,0x93,0x1d,0x9e,0x9,0x4d,0x3e,0x33,0x80,0x1f,0x59,0x48,0xc8, + 0x54,0x60,0x5,0x92,0xb8,0x70,0x8b,0xd1,0x46,0xcf,0x76,0x37,0x7e,0x18,0x94,0x9b, + 0xf6,0x45,0x21,0xe2,0x4,0xe0,0x8e,0xb0,0x8,0xe3,0xd,0x91,0xec,0xce,0xe5,0xee, + 0x7d,0xfc,0xbd,0x12,0xea,0x48,0x3a,0xfe,0xb2,0x90,0x32,0xa8,0x7d,0xa7,0x13,0x81, + 0x38,0xc3,0xb3,0xb0,0x62,0x83,0x77,0xe3,0x41,0xa5,0x68,0x7c,0x77,0xef,0x9c,0xd9, + 0xba,0xf3,0x71,0x62,0xdf,0xcd,0x30,0xb3,0xad,0x78,0x3d,0xcf,0x6a,0x41,0x54,0x36, + 0x27,0x99,0xf2,0x7a,0x20,0x94,0xda,0xfa,0xdd,0xeb,0xb7,0x32,0xc2,0x45,0x3b,0xb8, + 0xdc,0x4,0x7d,0xed,0x99,0xf2,0x8,0x12,0x77,0x5,0x97,0x8a,0xd,0x91,0x14,0x9c, + 0x88,0x0,0x94,0x1a,0x48,0x6,0xe2,0xd9,0xc8,0xb7,0xb0,0x60,0x78,0x11,0x95,0xe1, + 0xab,0x28,0xe,0x66,0x2e,0x53,0x75,0x5e,0xe,0x7b,0x5,0xec,0x48,0x48,0xcf,0xa0, + 0x68,0xa8,0xb3,0xb5,0x5e,0x81,0xe,0x37,0xf0,0x31,0x33,0xf2,0x96,0x96,0xf5,0x82, + 0xb9,0xf7,0x7a,0x7,0x21,0x8b,0xf8,0xc3,0xfb,0x32,0xd8,0xaa,0x93,0x75,0x23,0x26, + 0xec,0xc,0xc3,0x91,0x96,0xa0,0x47,0x1b,0x64,0x9c,0x0,0xe1,0x41,0x42,0xf5,0xc1, + 0xed,0x5,0x14,0x42,0xf7,0xf4,0x44,0xb3,0xa0,0x2b,0xe7,0xf6,0xb9,0x3a,0x4b,0xd2, + 0x62,0xf,0x5d,0xc3,0x84,0xa5,0x1e,0x2b,0x6d,0xed,0x8e,0xf9,0xb,0x8,0xf,0x86, + 0xa1,0xbd,0xbf,0x3f,0x5d,0xe7,0x13,0x84,0x11,0xdf,0xa5,0x16,0x30,0xea,0xd,0xc0, + 0x15,0x7a,0xb4,0x5d,0x2d,0x6,0xc2,0x0,0xd3,0xd8,0x74,0xa8,0x0,0xdb,0xb6,0xb9, + 0x77,0x3d,0x1f,0xc6,0x19,0x6f,0x7b,0xe6,0xb7,0x35,0xc1,0x24,0xdb,0xbc,0x65,0xc3, + 0x3b,0xdb,0x76,0xef,0xf1,0x6e,0x6d,0x80,0xd6,0x9f,0xe7,0xfe,0x53,0xd2,0x1d,0x68, + 0xa3,0x89,0x26,0xd6,0xb4,0x27,0x7e,0x75,0xdb,0x58,0xeb,0x6c,0x6c,0x9b,0x58,0x1a, + 0x72,0xdf,0x1d,0x1e,0x83,0xb4,0xe2,0xaa,0x2c,0xc6,0x10,0x57,0x69,0x71,0x41,0xb9, + 0x9b,0x65,0xa1,0x36,0x8a,0xa5,0x5d,0xd9,0x93,0x35,0x56,0x48,0xa2,0x1a,0xd6,0x66, + 0xe8,0xf5,0x3f,0xff,0xe7,0xff,0xf1,0xe0,0x6a,0xd4,0x46,0x90,0x16,0x90,0xb8,0x9d, + 0x99,0x98,0xac,0x73,0x30,0xf0,0xf4,0x3a,0x48,0x47,0x93,0x55,0xcd,0x52,0x8d,0x2a, + 0x65,0x8f,0xf2,0x31,0xe3,0x42,0xca,0x75,0x27,0xd3,0x4,0xd4,0xbb,0x7d,0x3a,0xc6, + 0xe0,0x76,0xaf,0xf0,0xaa,0xe5,0x8c,0xa,0xc2,0x22,0xea,0x13,0x1c,0x93,0x11,0xd5, + 0xfa,0xe,0x6,0x3,0x16,0x69,0x5d,0x13,0x91,0x5c,0xc4,0x60,0xab,0xa6,0xca,0xb0, + 0x43,0x68,0xe8,0x3,0x7e,0xd0,0x11,0x1d,0x1f,0x87,0xd4,0x98,0x18,0x58,0x23,0xcc, + 0x5a,0xe2,0xbf,0xb9,0x1f,0x50,0xf0,0x9a,0x91,0xdf,0xa3,0x2a,0x8b,0x2b,0x6e,0x71, + 0xfa,0xfa,0xfc,0x5a,0x99,0x1c,0x21,0x7e,0x32,0xcf,0xc4,0xf9,0x66,0xb1,0xac,0x64, + 0xc1,0x40,0x9,0x8c,0x98,0xbf,0xd7,0x3e,0x10,0xd1,0x74,0xa9,0xe1,0x86,0x90,0x48, + 0xb5,0xe9,0x28,0x43,0x39,0xbd,0x10,0x1e,0xbc,0x5,0xa1,0x16,0x1c,0xa4,0x39,0x8a, + 0x90,0xe7,0x40,0x62,0x4e,0x41,0x68,0x52,0xd0,0xa2,0x72,0xd7,0x58,0xe4,0xed,0x48, + 0xed,0xed,0xc0,0x1a,0xc8,0xf7,0xf2,0x7a,0xaf,0x5a,0x36,0xf3,0xbd,0xea,0xec,0x65, + 0x5b,0x8d,0xd2,0x3e,0x46,0xed,0xdb,0x48,0x2a,0xba,0xc6,0x5a,0x87,0xa8,0x80,0xcb, + 0x8e,0x51,0x98,0x33,0x0,0x4e,0xe9,0x51,0xbb,0x78,0x47,0x41,0xf,0x2a,0xc3,0x9f, + 0x4,0xc3,0xf7,0xcb,0x46,0xb7,0xc2,0x2b,0x6a,0x9f,0x26,0x1e,0x30,0x39,0x2e,0x8b, + 0x9c,0x6d,0x1e,0xf6,0x1e,0x17,0x86,0x28,0x7b,0xdb,0x4c,0xe6,0x8d,0x4c,0xff,0x6a, + 0xdc,0xef,0xad,0x2a,0x9f,0xbb,0x52,0xc0,0xb8,0xb,0x50,0xdc,0xf7,0xca,0xb1,0xd4, + 0x60,0xd8,0x15,0xb9,0x84,0x6,0xd5,0x43,0xf2,0x68,0xfe,0x97,0x1d,0x71,0x50,0xbc, + 0xab,0x94,0xb7,0x8e,0x49,0xef,0x7e,0xd0,0x45,0xb3,0xbe,0xbe,0x5b,0x98,0x23,0x10, + 0xee,0x87,0x5a,0xba,0x74,0x6f,0xc7,0x7a,0xad,0x9d,0x87,0xaa,0xbf,0x32,0xea,0xf8, + 0xb6,0x6e,0x4b,0x75,0x3a,0xab,0x13,0x6c,0x10,0x7c,0xdd,0x50,0x8,0x6a,0x7,0x72, + 0x6b,0xf1,0x86,0x9,0x2c,0x84,0x50,0x37,0x41,0xa6,0x33,0x87,0xad,0xf7,0xac,0x7c, + 0xd8,0xa0,0xee,0x23,0x10,0xc8,0xc,0x1d,0x1,0x77,0x45,0xe3,0x41,0x57,0x2a,0xd8, + 0xd6,0x7,0x27,0x3b,0xcb,0x8d,0x5c,0xce,0xbd,0xe,0xce,0xf7,0x8e,0x94,0x95,0x13, + 0x15,0x11,0xe1,0xc5,0x5b,0x90,0xb6,0x21,0xa0,0x56,0x61,0x1d,0x3b,0x6f,0xb0,0xe5, + 0xa,0x38,0x51,0x6a,0x65,0x5f,0x48,0xa8,0xb9,0xb6,0x3b,0xd0,0x92,0x43,0xe8,0xd4, + 0x39,0x28,0x52,0x4e,0x4c,0x34,0xc7,0x1d,0x2a,0xa3,0xc8,0xe3,0xe8,0xc6,0x22,0x57, + 0x49,0x84,0x2b,0x78,0x92,0x71,0x23,0xa6,0x61,0x48,0x3c,0xdc,0x7f,0x11,0xcd,0xa2, + 0xf7,0x3a,0x99,0xe,0x66,0x87,0xf0,0x31,0x1b,0x90,0x89,0x45,0x43,0x46,0xf6,0x9b, + 0x11,0x7d,0x29,0x18,0x6,0x31,0x90,0xa4,0x6c,0x84,0x59,0x5f,0xdc,0x95,0x9a,0x96, + 0x76,0x72,0xe0,0x6a,0x4f,0xee,0x70,0x61,0xce,0xef,0x44,0x9e,0x98,0x0,0x27,0x13, + 0x5a,0xdc,0x4,0x8e,0x9,0x95,0xda,0x81,0x43,0xbc,0x74,0xa3,0xf2,0x58,0x9f,0xa5, + 0x39,0x32,0xad,0xe,0x71,0x35,0x44,0x66,0xa3,0xbe,0x56,0x5a,0x72,0x36,0xd0,0x95, + 0x4e,0xf4,0x10,0xa6,0xca,0x79,0x44,0xa9,0x49,0xab,0x11,0x73,0x66,0xaa,0x5,0x7a, + 0xdd,0x4,0x94,0x16,0x79,0xdf,0x16,0x68,0x8b,0xd1,0xfd,0x4c,0xc7,0x8,0xb9,0x43, + 0xa1,0xcc,0x58,0x88,0xa1,0x49,0x4c,0x5f,0x9c,0xa8,0x16,0xc2,0x36,0x40,0xee,0x7, + 0x38,0x55,0xdb,0x4a,0xab,0x18,0xd5,0xb,0xd9,0x31,0x57,0x84,0xc,0x24,0x52,0xf9, + 0x30,0xf5,0xd6,0xe0,0xd5,0x3,0x7d,0xf7,0xe0,0x44,0x2b,0xdc,0x7d,0xa0,0x88,0xb1, + 0x77,0x39,0x83,0x32,0x76,0xa6,0x8,0xc3,0x93,0x76,0x37,0x68,0x74,0x31,0xc0,0x5f, + 0x6,0x32,0x5d,0xb1,0x13,0xe6,0x1b,0xdc,0xb0,0x79,0x87,0x2f,0xb4,0x71,0x61,0x31, + 0xb8,0x97,0x7d,0x67,0x6e,0xee,0xa8,0x8d,0xc3,0xd2,0xad,0x5f,0xdd,0xca,0x89,0xb2, + 0x23,0xde,0x2b,0xb0,0xae,0xc6,0x86,0xe,0xea,0xda,0xab,0x95,0xd1,0x65,0x10,0x21, + 0xa8,0x71,0x34,0x93,0x2d,0x66,0xbf,0x6d,0x35,0xff,0xde,0x4f,0xf0,0x3e,0x28,0x62, + 0xb,0xf7,0x66,0x77,0x59,0x6b,0x26,0x2f,0x4,0xc8,0xdb,0x83,0x28,0x3c,0xa0,0x87, + 0x19,0xbb,0xe3,0x41,0xe2,0xb5,0x1f,0x74,0xdb,0xb0,0x60,0xb7,0x38,0xd0,0x2,0xcc, + 0x4f,0xc,0x8a,0x80,0x80,0x58,0xb,0x11,0xd8,0x76,0x40,0x81,0x37,0xc4,0x7d,0xd, + 0x9a,0x3e,0x1a,0x9a,0xf5,0x7e,0x95,0xbd,0x2a,0x64,0x1d,0x83,0x62,0x7b,0x49,0xb9, + 0x57,0xb2,0x1d,0xb8,0x35,0xd2,0x52,0x6f,0x65,0xf,0xb9,0xd4,0x55,0x1a,0x1b,0x1b, + 0xe2,0x39,0x6,0xde,0xc0,0xfb,0xda,0x63,0x8d,0x3,0x5a,0x93,0xa5,0x1f,0x76,0x95, + 0xb9,0x5c,0x58,0xe0,0xa6,0x12,0xcc,0x41,0x4d,0x38,0x42,0xd1,0xd3,0xd8,0xa8,0x60, + 0x20,0x43,0xac,0x25,0x1,0x35,0x41,0xe5,0x91,0x1b,0x83,0x22,0x5d,0x11,0x9f,0x73, + 0x9c,0x4d,0xef,0x58,0xa,0x22,0xcf,0x50,0x83,0x29,0x86,0x78,0x95,0xa3,0x2b,0x19, + 0x9e,0x30,0x91,0xe8,0xaa,0x2d,0x53,0x50,0xcb,0xbd,0x74,0x5,0xb4,0x9e,0x6e,0x36, + 0x0,0x62,0xb3,0xaf,0xb3,0xd,0x9b,0xef,0x74,0xb7,0x42,0x78,0x6a,0x17,0xe0,0xa8, + 0xf8,0x68,0x34,0xe9,0x7d,0x3,0xb6,0x66,0x51,0xb8,0x55,0x24,0xc9,0xbe,0xdf,0xcd, + 0x7c,0x73,0x88,0xae,0xae,0x9a,0xc,0xc0,0xd5,0x71,0x92,0x79,0xe3,0x98,0x30,0xd7, + 0x30,0xad,0xd0,0xfb,0x3e,0x20,0x20,0x9a,0xfa,0x6b,0x88,0x56,0x41,0xe8,0x9e,0x9d, + 0x4c,0xc3,0xf1,0x18,0x45,0x69,0xe,0x97,0x5b,0x9,0x16,0x2,0x4f,0x60,0x9e,0x45, + 0x73,0x18,0x64,0x4a,0x93,0xcd,0xf8,0x0,0x81,0x13,0x1,0x6a,0x37,0x48,0x60,0x9b, + 0x71,0xc5,0x7d,0xcc,0xb4,0xf3,0xcc,0xec,0x80,0xf8,0x38,0x66,0x0,0x8f,0x59,0x16, + 0x30,0xa3,0xab,0x8d,0xf7,0xfb,0xcf,0xff,0xf9,0xa1,0x35,0x5f,0x77,0x80,0x87,0xc5, + 0x7,0x13,0xe7,0xd8,0xa2,0xdb,0xb,0x53,0x9,0xc2,0x51,0xa9,0x3a,0xb3,0x0,0xe8, + 0x14,0x73,0xba,0x2f,0x6a,0x80,0xa3,0xc2,0x39,0x46,0x59,0x35,0xe3,0x25,0x7c,0x32, + 0x6d,0x11,0xb5,0x26,0xf,0xda,0xee,0xc2,0xe1,0xb5,0xe0,0x61,0x81,0xae,0xdd,0xad, + 0xf8,0x6b,0xa1,0x77,0xf7,0x32,0xcc,0xc3,0x6c,0xae,0x3,0x82,0x8,0xdf,0x4d,0xe8, + 0x95,0x2e,0x40,0x1,0x16,0x32,0x81,0x2a,0xc3,0x69,0xfb,0x17,0x18,0x44,0x5,0x8a, + 0x2f,0x3,0x9,0x4f,0x41,0x9d,0x82,0xf8,0x3e,0x4f,0x23,0xf4,0xb0,0xf7,0xcc,0x80, + 0xa2,0x74,0xfd,0x59,0x85,0x9c,0x95,0x36,0x98,0xac,0xf7,0xa6,0xb5,0x98,0x39,0xb2, + 0x89,0xe6,0x70,0x90,0xa5,0xac,0xe7,0xdb,0xd6,0x6f,0x3d,0x8,0x60,0x5,0x43,0xd9, + 0x7c,0x3f,0x8,0x1b,0xf9,0xda,0xbd,0x9c,0xa8,0x95,0xfb,0x56,0xd,0x19,0x5b,0xa1, + 0xeb,0xff,0x65,0x33,0x14,0xb3,0x13,0xd6,0xd0,0x5c,0x8e,0x4a,0x49,0xc7,0x86,0x21, + 0xab,0x4c,0x87,0x9a,0x95,0xf9,0xf1,0xc3,0x9a,0x61,0x28,0x9d,0x9b,0xd6,0x79,0x6a, + 0x5,0xad,0x42,0xac,0x73,0xd,0x6f,0x41,0xa5,0x95,0x4c,0x68,0xaf,0x1b,0x6d,0xb1, + 0x70,0xb,0x67,0xff,0x41,0xd2,0x28,0x72,0xb5,0xdd,0x3c,0xb1,0x2f,0x21,0x17,0xd8, + 0x1d,0xb8,0x98,0x64,0x6e,0xaf,0x8f,0x1a,0x54,0xfb,0x7b,0xb0,0x13,0x7d,0xe2,0xb7, + 0xef,0xb3,0xad,0xf,0xa8,0xdd,0xdc,0x4b,0x8f,0x4d,0x27,0x9c,0x2b,0x74,0x33,0xf7, + 0x8a,0x24,0xdf,0x75,0xbe,0x36,0x6f,0x7d,0xea,0x61,0xd2,0xd2,0x12,0xa2,0xad,0xd7, + 0xdf,0xdd,0x61,0xa7,0x39,0xbb,0xb7,0x25,0xa1,0x75,0xb,0xc6,0x28,0xa2,0xd9,0xbf, + 0x77,0xa0,0x7e,0x8b,0xec,0xd,0xa1,0xde,0x92,0xc9,0x3e,0x8d,0x6e,0xbc,0x88,0x56, + 0xeb,0x57,0x84,0x5a,0x43,0xad,0xb7,0x79,0xf9,0xd0,0x40,0xdb,0x61,0x23,0x75,0x1d, + 0x7b,0x9,0x14,0xd4,0x2,0x98,0x72,0xe2,0x93,0x74,0x76,0x80,0x2f,0x96,0x82,0x13, + 0xa3,0xf3,0x6a,0x2e,0xb8,0x1e,0x78,0x4f,0xd,0x59,0x4d,0x18,0x5d,0xba,0xb8,0xe, + 0xdc,0x1,0x2b,0xd,0xe0,0xe6,0xc5,0x87,0xbb,0x53,0x75,0x54,0xad,0x22,0x40,0xbb, + 0x7c,0xfb,0xe,0x18,0x85,0xbb,0x6f,0x35,0xa9,0x6d,0xd4,0x37,0x67,0x68,0x1a,0xda, + 0x47,0x57,0x16,0x49,0x23,0x78,0x14,0xec,0xda,0xc,0xd2,0xad,0x6a,0x12,0xca,0xad, + 0xd3,0x65,0x3a,0xee,0x23,0xcf,0x70,0x87,0x4d,0xbb,0xce,0x71,0x14,0x2c,0x14,0x5a, + 0x29,0xd1,0xc3,0x3c,0xda,0x27,0x19,0x53,0x64,0xfb,0xd4,0xd,0x72,0x12,0xe4,0xc4, + 0x35,0x13,0x5e,0x6e,0xdd,0x61,0x57,0x25,0x95,0xec,0xb0,0x25,0xdc,0x60,0x27,0xb9, + 0xc0,0xcc,0x2c,0xf5,0x58,0xf5,0x1d,0x74,0xd,0xd2,0xc0,0xee,0x13,0xff,0xde,0x84, + 0x6f,0x6,0x2,0xbb,0x3c,0xa0,0xe7,0xe3,0x31,0x25,0x2a,0xa8,0xf9,0xb3,0x19,0xb4, + 0x90,0x73,0x2d,0x6d,0x44,0x44,0x99,0x42,0x77,0xe,0xae,0xa3,0xd5,0xed,0x44,0xc5, + 0x19,0x1f,0x50,0x14,0x7a,0x16,0xa8,0x61,0x1d,0xbf,0x50,0xb9,0xf2,0x90,0x79,0x9b, + 0x36,0x4a,0x64,0xbe,0x1f,0x24,0x22,0xb3,0x65,0xad,0xc0,0x58,0x68,0x96,0xe5,0xda, + 0x73,0xf2,0x80,0x40,0x87,0x93,0x29,0x1a,0x4b,0xbd,0x9a,0x64,0x90,0x2d,0x11,0x53, + 0x53,0x85,0xac,0x4,0x16,0xf9,0x95,0xe8,0x9f,0x87,0x8e,0x7c,0x11,0xca,0x47,0xaf, + 0x34,0xfa,0xc,0x9a,0x6a,0x43,0xe2,0x22,0x75,0x1d,0xf5,0x82,0xee,0xd5,0x58,0x8f, + 0xbb,0x16,0x78,0xbc,0xf8,0xe,0x24,0xf2,0xf1,0xba,0x1e,0xa7,0x80,0xe1,0x47,0x85, + 0xa6,0x24,0x63,0x2,0x42,0xea,0x19,0xc4,0xc0,0x6c,0xe9,0xec,0x9e,0x7b,0x65,0x25, + 0x5a,0xc1,0x94,0xa4,0xde,0x2e,0xb3,0x46,0x6f,0x14,0xb2,0xfe,0xc8,0x6a,0xf3,0xa0, + 0x78,0xf,0xf0,0x7b,0x67,0x76,0xef,0x45,0xba,0x39,0x4a,0x29,0x15,0xa7,0xbe,0xcf, + 0xd4,0xcb,0x89,0x3a,0x2,0x6e,0xbd,0x9c,0x32,0x4c,0xa9,0x4a,0x75,0x6c,0xe3,0xa6, + 0x35,0x44,0xc4,0x57,0x34,0xf0,0x9d,0x62,0x78,0xd,0x2c,0xe8,0xee,0x19,0x2d,0x88, + 0xa0,0x96,0xfb,0xed,0xcb,0xa2,0x91,0xfd,0xfa,0x6f,0x12,0xf8,0x9d,0x21,0x20,0x41, + 0x6a,0xaf,0x4f,0x3b,0x46,0x0,0x1c,0x58,0x32,0x56,0xb0,0xab,0x17,0x58,0x4,0x21, + 0x3a,0x30,0x30,0x83,0x43,0x46,0xd8,0xa,0x33,0xdf,0xa4,0x9b,0xcf,0x88,0xde,0xd1, + 0xbd,0x2f,0x27,0xfa,0xa0,0xb2,0x2a,0x31,0x7a,0xff,0xdd,0x5e,0xa1,0x97,0xd2,0xba, + 0xb5,0xbd,0x2,0x2c,0x55,0x13,0xb6,0x0,0xbe,0xb9,0x17,0x14,0x6c,0x55,0xfa,0xd4, + 0x5a,0x8f,0xc2,0x3b,0x68,0xe,0x6c,0x95,0x19,0x7d,0x33,0xc7,0x5d,0x2b,0x20,0xb9, + 0x19,0x5a,0x99,0x35,0x53,0xe8,0x71,0xb8,0xee,0xc8,0x5a,0xc6,0x57,0x99,0x7f,0x78, + 0x4f,0x5,0xea,0x28,0xa9,0xd0,0x60,0xbe,0xef,0x97,0x22,0x4,0x83,0xd8,0x16,0x95, + 0x51,0x6c,0xc9,0xad,0x78,0x9e,0xf3,0xf2,0xfd,0xd1,0xfb,0xcb,0x2d,0xa8,0x21,0xd1, + 0x2c,0x94,0xb1,0x42,0x2e,0x81,0x65,0xdb,0x9b,0x5f,0x5b,0xf1,0x21,0x5a,0xb0,0xb7, + 0x5a,0x8a,0xb5,0xae,0x3a,0x6a,0x58,0xde,0x23,0x7a,0xcb,0x85,0xca,0x9,0x77,0x11, + 0x7f,0xdf,0x17,0x83,0xef,0x73,0xf2,0x6d,0xa6,0x46,0x58,0xa7,0x67,0x85,0x13,0x68, + 0x4,0x14,0xbc,0x6b,0xd5,0xc2,0x12,0x87,0x99,0x73,0x8e,0xa4,0x79,0xaa,0xe8,0xac, + 0xe8,0x8d,0x12,0x5b,0xfd,0x73,0xd3,0x1e,0x4c,0x21,0x5a,0x27,0x3d,0xcd,0x7c,0x47, + 0x25,0x16,0x98,0xa9,0xc6,0xf2,0x9c,0xb1,0xef,0xef,0xd5,0xc6,0x14,0x33,0xde,0xba, + 0x40,0xf5,0x5d,0xde,0xbf,0xcd,0x7,0x4,0x28,0x15,0x6c,0x4d,0x9b,0x5e,0xad,0x6, + 0xf5,0x31,0xbb,0x1f,0x42,0xf8,0x72,0x9b,0xd4,0x5e,0x96,0x1a,0x67,0x82,0xc2,0xf7, + 0x70,0xe3,0x9d,0x38,0xc,0x33,0x43,0x28,0xd9,0x78,0x9c,0xfb,0xb8,0xe2,0xd,0x7c, + 0x50,0xea,0xba,0xd,0x29,0xdb,0x53,0x82,0x51,0x90,0x8,0x15,0xbb,0xc9,0x7c,0x6a, + 0xf0,0xc0,0xf7,0xa4,0x54,0x84,0x34,0x90,0x25,0x0,0x7,0x15,0xac,0x65,0x8c,0x2e, + 0x4a,0x72,0xce,0x5a,0x13,0x61,0xe,0xe3,0xb1,0xb2,0xa7,0x1a,0xc1,0xa8,0x9d,0xf, + 0xe2,0xec,0x2a,0x16,0xcc,0x95,0x76,0x11,0x3a,0x3b,0x88,0x28,0x7c,0xf6,0xa9,0x26, + 0xf9,0x48,0xa2,0xc3,0x65,0x9c,0x3e,0x71,0xa0,0xbd,0x6,0x4e,0x44,0x40,0x5b,0x3d, + 0x5,0xab,0xe4,0x3a,0x29,0xb0,0x17,0x2,0xe,0xb5,0x63,0xb2,0xa2,0xde,0xf7,0x33, + 0xb1,0x75,0x95,0xfb,0xef,0x38,0x81,0xc0,0x80,0x80,0x9e,0xe8,0x27,0x2c,0xea,0x48, + 0xb3,0x25,0xfd,0x5,0x62,0xe9,0xc9,0xe7,0xa5,0x47,0xf3,0x1c,0x84,0x95,0x5b,0x41, + 0x58,0x7d,0xda,0x45,0x3a,0x82,0x50,0x2a,0x7b,0xf1,0xbd,0xe6,0x6e,0x50,0xde,0x8a, + 0x5b,0xaf,0x1,0x7e,0xdb,0xed,0xa6,0x6c,0xdb,0x60,0x65,0x8f,0x40,0x8d,0x5f,0xee, + 0x7b,0xf9,0x8f,0xd0,0x29,0xf2,0xda,0x6,0x6,0x1f,0x4d,0x4e,0x72,0x9c,0xf5,0xe, + 0x99,0x7b,0x3d,0x4d,0x6b,0x92,0x73,0xc2,0xa8,0xd3,0x51,0xb1,0x5b,0xa5,0x29,0x93, + 0xa0,0xfe,0xb9,0x85,0x77,0x40,0x44,0x54,0x5a,0xac,0x22,0x43,0x24,0x73,0x8a,0x64, + 0x55,0xa3,0xbd,0x58,0x21,0x8c,0x8c,0xbb,0x98,0x14,0x79,0xac,0x68,0xba,0xcd,0xaf, + 0xbb,0x45,0xc0,0x66,0xfd,0xb6,0x27,0x5a,0x1f,0x3a,0x14,0x12,0xc5,0x65,0x9,0x3a, + 0x23,0xb2,0x51,0x83,0xfd,0x89,0x21,0xd3,0x57,0xa,0x8a,0x6f,0x6d,0x29,0xee,0x83, + 0x78,0x3,0xb0,0x2b,0xf0,0x35,0x6a,0x3c,0xbc,0x94,0x13,0x5d,0x4,0x7e,0x67,0xe2, + 0x33,0xc2,0x1e,0x92,0xe4,0xd5,0x8,0xbc,0x3,0x29,0x9d,0x35,0xd,0x7a,0x5a,0x44, + 0x68,0xd5,0x66,0x53,0x52,0xe7,0x7,0x56,0x6,0xc1,0xb0,0xf5,0x9a,0x50,0xc7,0x2, + 0x9d,0x7a,0x59,0x88,0xa2,0x15,0xa8,0x48,0x60,0xca,0x9c,0x49,0xc2,0x31,0x6d,0x62, + 0x6,0x7b,0x88,0x3e,0xa1,0x1d,0x4e,0x6e,0x45,0x15,0x81,0x87,0x6,0x7b,0x1a,0xd9, + 0x31,0xb2,0xbc,0xc7,0xb5,0x9a,0x54,0x9d,0x0,0xf9,0x79,0x55,0x58,0xc3,0xe6,0xbe, + 0x63,0x2,0x61,0xbe,0xb,0x22,0xfb,0xbe,0x5,0xbd,0x42,0x15,0xe0,0xfb,0x7f,0xef, + 0x7b,0xa4,0x17,0x3e,0xc5,0xcd,0xac,0xaa,0xce,0xf5,0xb5,0x24,0x82,0x72,0x1d,0xc3, + 0xb9,0xb7,0xbf,0x80,0x61,0x78,0x94,0x54,0x47,0xe0,0x18,0xb2,0x90,0xac,0x7e,0x19, + 0xe1,0x9c,0x21,0x1b,0x98,0x99,0xb1,0x4d,0xfc,0x28,0x8c,0x3a,0xce,0x23,0x36,0x38, + 0x53,0xb7,0x6b,0xc,0x3c,0xa9,0x73,0x11,0x65,0x4e,0xb4,0xa,0x6f,0x24,0xc9,0x98, + 0xf2,0xd4,0x99,0x2a,0xe5,0x91,0x63,0xc6,0xdc,0x5a,0x4c,0x60,0xf7,0x33,0x19,0xc7, + 0x80,0x96,0x94,0x6b,0x71,0x55,0x7d,0x53,0xa7,0x85,0xac,0xdf,0xee,0xc1,0xcf,0x98, + 0x84,0x30,0xfa,0x77,0xc2,0xac,0x4b,0x80,0x44,0x1c,0x1b,0x34,0x2c,0x6e,0xb5,0xc0, + 0x53,0xe,0xcb,0xed,0x73,0xcc,0xd1,0x65,0x93,0x44,0x2b,0x0,0x21,0x66,0xd0,0x1, + 0x31,0x68,0x80,0x74,0x11,0xd4,0x28,0x26,0x0,0x12,0x2d,0xc7,0x5b,0x7d,0x9d,0xa6, + 0x7a,0xa4,0x30,0xcf,0x6e,0x18,0x33,0xf8,0xa1,0x2c,0xae,0x68,0x56,0x1a,0x6d,0x9c, + 0xa3,0x23,0x5e,0x45,0x63,0xcb,0x8,0xa5,0x7f,0x36,0x5a,0x37,0xd,0x2a,0xa8,0x50, + 0xc0,0x7a,0xda,0x34,0xf8,0xb6,0xde,0x7f,0xaf,0xd4,0xdb,0x8e,0x4a,0xdf,0xd1,0xed, + 0x14,0x88,0xcb,0xae,0xac,0x81,0x32,0x88,0xfd,0x18,0xe1,0xba,0xbe,0xb6,0xbe,0x41, + 0xb1,0x8e,0xd0,0x66,0x5c,0xf1,0xc8,0x41,0x58,0xa0,0xb3,0x16,0x49,0x65,0x60,0x8c, + 0xa8,0x55,0x3a,0x24,0xad,0xa,0xeb,0xb4,0x77,0xf6,0x4c,0xb8,0xbb,0x65,0x3f,0xac, + 0x6,0x76,0xc1,0x79,0xaa,0xde,0xad,0x52,0xf7,0x76,0xa2,0xef,0xa0,0xaf,0xbd,0x44, + 0xdc,0x1b,0x92,0xee,0xee,0xc5,0xb1,0xf9,0xe6,0x28,0x7b,0x48,0xd9,0x87,0xba,0xee, + 0xf6,0x5f,0xb6,0xc6,0xe2,0x1b,0x5d,0x1c,0x6b,0x41,0xde,0x5b,0x1b,0xd6,0x2,0xa0, + 0xb3,0xe8,0xe3,0xa8,0x46,0x1d,0xa3,0x2a,0xe7,0x64,0x68,0x4,0x9a,0xe6,0xa4,0x41, + 0xd5,0x79,0x87,0x76,0xb3,0xaf,0x2a,0xb1,0xd6,0x93,0x9f,0x2d,0xcf,0xcd,0xc1,0xf, + 0x62,0x14,0xd4,0x89,0xbd,0x8,0x85,0x8c,0xc,0xa1,0x72,0x9d,0xfa,0xb5,0xae,0xee, + 0x10,0x5e,0x96,0x48,0x4e,0x4d,0x1e,0x57,0xaf,0x19,0x66,0xb5,0x94,0x82,0x13,0x4d, + 0x43,0xd4,0xdc,0x76,0x8c,0x9c,0xe1,0x44,0x45,0xc9,0xd,0x71,0xbf,0xae,0x33,0xdf, + 0x66,0x38,0x26,0x9c,0x2c,0x23,0x0,0x27,0x31,0x24,0x6b,0x12,0x38,0x0,0x87,0x6d, + 0x52,0xe4,0xad,0x30,0x1f,0xf7,0xbb,0x4f,0xc4,0xdb,0xb6,0x28,0xc3,0xa7,0x75,0x32, + 0x87,0x1f,0xb5,0x3c,0xd9,0x53,0x43,0x1a,0x71,0x3,0x57,0x42,0xc1,0x3a,0x62,0x7c, + 0xbb,0xc1,0x20,0x75,0xf7,0x48,0xa3,0xbc,0x74,0xdb,0x72,0xd6,0x72,0xc1,0x80,0xc5, + 0x8d,0xdc,0x15,0x4e,0x55,0x3b,0xf9,0x6e,0x6e,0xac,0x1f,0xd5,0x13,0x35,0x2b,0x2d, + 0x99,0x75,0xc3,0xe,0x9a,0xf3,0x6,0x9a,0xdb,0x69,0x9c,0xbd,0x3a,0xdf,0xa9,0x1d, + 0xd8,0xf6,0xfd,0xd2,0xe4,0xf5,0xb6,0x26,0x2b,0xbd,0x8d,0xeb,0x77,0xb2,0x73,0x35, + 0xf7,0x3a,0x25,0xa9,0x48,0xbf,0x4d,0xb,0x75,0x17,0xb8,0xae,0xf7,0xd3,0xdf,0x83, + 0x94,0xaf,0x67,0x8,0x51,0x23,0x67,0xb0,0xc2,0xe8,0xb0,0xec,0x26,0xa7,0x53,0x2, + 0x49,0xf,0x54,0x7b,0x0,0xeb,0xd5,0x8e,0xf8,0x49,0x75,0x7c,0x37,0x55,0xfb,0x82, + 0x6a,0xd7,0x32,0x9,0x4d,0xb4,0xc3,0xa1,0x9c,0xe5,0xe,0xca,0x82,0xf2,0xb8,0x91, + 0xda,0xf,0x6e,0xea,0xca,0x34,0xd8,0xd5,0x82,0xce,0x87,0x6,0x77,0x46,0xce,0x47, + 0xca,0x5a,0xc4,0x8e,0x23,0xba,0x83,0x99,0x52,0x4e,0xdb,0x52,0xf2,0xe0,0x80,0x16, + 0x55,0xc8,0x24,0x58,0xd5,0xae,0x1,0x57,0xd5,0x33,0x34,0xfc,0x8c,0x4c,0xac,0x48, + 0xd1,0x20,0x3c,0x40,0xbe,0xef,0x59,0x54,0x15,0x1,0x1c,0x41,0x48,0x65,0x86,0xa, + 0x78,0x4,0x59,0xb1,0xce,0xbe,0x49,0x12,0xc4,0x62,0x2d,0xea,0x33,0x13,0x2a,0xed, + 0xa1,0xa9,0x21,0xb3,0x33,0x38,0x32,0xc8,0x3e,0xba,0xa0,0xb1,0x9e,0x39,0xc8,0x7b, + 0x90,0x69,0x18,0x36,0xe3,0xe2,0xf1,0xb9,0x3e,0xb8,0xa1,0xc3,0xd6,0x94,0x66,0xe4, + 0xae,0xe2,0x52,0xa5,0x1d,0x6a,0xfd,0x15,0x85,0xe4,0x62,0x6a,0x10,0x39,0x51,0xf9, + 0x2a,0x2d,0xb0,0xcc,0x2,0x4f,0x6f,0x1d,0x34,0x78,0x71,0x7d,0xdc,0xa3,0x62,0x21, + 0x60,0xdc,0xde,0x60,0x76,0x8f,0xac,0xbc,0xe1,0x57,0xd9,0x4,0x3e,0x7c,0xb0,0xb6, + 0x60,0xd3,0xa7,0x3c,0x72,0xbc,0xa1,0x67,0x40,0x67,0x42,0xb7,0xf9,0x6a,0xa7,0x9e, + 0xbb,0x9d,0x30,0xaf,0x90,0x8a,0x76,0xc6,0x38,0x76,0xc8,0x70,0x29,0xad,0x44,0xd9, + 0x6c,0xdb,0xaf,0xf4,0x44,0x71,0xdb,0xb6,0x48,0xe2,0x32,0x8c,0x18,0x23,0x2a,0x54, + 0x83,0x2f,0x4f,0x80,0xab,0x42,0x18,0x83,0x1a,0xcc,0xb,0xe0,0x7b,0x2a,0x35,0xee, + 0x75,0x4b,0x91,0xac,0x6,0xa3,0xa,0xd5,0xee,0xdb,0x77,0xb0,0x0,0x8,0x70,0x48, + 0x43,0xb5,0x20,0xe6,0x24,0x6e,0x2,0x3c,0x82,0xdb,0xdc,0xe3,0x19,0x96,0xb0,0xad, + 0x1,0x4a,0xe4,0x33,0xec,0x72,0x6d,0xa9,0x47,0xef,0xd2,0xde,0x48,0x6c,0x7a,0xec, + 0x2c,0xc4,0x75,0x2,0xc5,0xb6,0xea,0x10,0x5a,0x67,0xb6,0x6,0xd8,0xe6,0xe6,0xbe, + 0x91,0x42,0x71,0x9b,0x1d,0x79,0x97,0xcb,0xa8,0x7e,0xdf,0xa0,0xa1,0x52,0xbb,0x96, + 0xa2,0x59,0xf9,0x9,0x87,0xd7,0x75,0x5d,0x7a,0xf9,0x54,0xe8,0x1e,0x87,0xf5,0xdd, + 0xd2,0xa3,0x1d,0x24,0xb9,0x9f,0x76,0x63,0xd4,0x3e,0x28,0x84,0x34,0xf,0x1a,0x73, + 0xf4,0x36,0x65,0x60,0x19,0x59,0x57,0xb5,0x11,0x72,0x67,0x64,0x5a,0x71,0x61,0xf2, + 0xf1,0x0,0xd,0x16,0x2e,0xb2,0x40,0xb3,0xdf,0xcd,0xeb,0x50,0x9f,0x6c,0x4b,0xfb, + 0xc8,0x64,0x63,0xc1,0x92,0xd2,0x3,0xfd,0x66,0x4e,0x16,0x65,0x3b,0xa0,0xae,0xf2, + 0xce,0xdd,0x6d,0xbf,0x9f,0x95,0x6e,0xe0,0x5e,0x46,0x75,0xde,0x92,0xdc,0x3a,0x81, + 0x71,0x73,0xf3,0xd,0xb6,0xa1,0xb,0xe8,0x54,0x99,0xdd,0xa,0xf8,0x6e,0xec,0x35, + 0xef,0x7d,0xcb,0x36,0xa7,0x70,0x8e,0xd9,0xaa,0x4a,0xb1,0x43,0x45,0x86,0x68,0x4c, + 0x4c,0x2c,0x63,0xbe,0x8a,0x0,0x8a,0x13,0xdf,0xb,0x48,0x52,0xa0,0x8d,0x14,0x24, + 0xa9,0xee,0x7d,0x86,0xe,0xa4,0x92,0x7f,0x5a,0xcd,0x1,0x2,0xc7,0x17,0x4,0xb2, + 0x71,0xb0,0x46,0x2,0x70,0x25,0x5d,0xa,0x31,0x70,0x67,0x29,0xbb,0x32,0x40,0xbd, + 0x5c,0xf5,0x91,0xd2,0x4e,0xea,0xf9,0x23,0x8c,0xe3,0x2d,0x3a,0x65,0xbb,0xf8,0xa1, + 0xf3,0xb0,0x39,0x29,0xa1,0xb9,0x5,0x31,0x0,0x4a,0x8,0x10,0x9c,0x7b,0x23,0xc4, + 0xde,0x7,0x8a,0x80,0x34,0xab,0x35,0xa3,0x8a,0xda,0xa4,0x36,0xb0,0x6,0x60,0xff, + 0x75,0xb,0x80,0x8b,0xa8,0x22,0x65,0x91,0xcf,0xee,0x91,0xcc,0x6e,0xea,0xe7,0xcd, + 0xf,0xb5,0x5,0xd9,0x20,0x10,0xe1,0x36,0xd,0xaa,0x23,0x89,0x88,0xb3,0x8e,0xf8, + 0x59,0xd4,0x4f,0xb3,0xc0,0xeb,0xf3,0x60,0x6f,0x35,0xed,0x20,0x90,0x9a,0x20,0xe2, + 0xa0,0x63,0x28,0xbe,0x38,0x2b,0x42,0xe,0xcd,0x6a,0x48,0x80,0xa7,0x99,0x6d,0x6b, + 0xe7,0x7a,0x6c,0x57,0x7a,0xd9,0x4b,0xce,0x32,0x2,0x79,0xb,0x3c,0x5c,0xcd,0xf4, + 0xbf,0x8f,0xd9,0xf7,0x1e,0x8f,0x8a,0x88,0x72,0x77,0x5a,0x9b,0x81,0xd2,0x51,0x88, + 0xcb,0x51,0x98,0x4a,0xf6,0x4e,0x53,0x30,0x3,0x24,0xcb,0xd3,0x42,0x50,0x25,0x6f, + 0x36,0x1e,0xb5,0x9b,0xd9,0xe0,0x2a,0x5b,0xb3,0x3c,0xeb,0x68,0x9d,0xbd,0x4a,0xd9, + 0x6c,0x77,0xeb,0x2e,0x3b,0x19,0xb,0x6e,0x9b,0x15,0x2b,0x12,0xd4,0xe1,0x6e,0xdb, + 0xb6,0x9,0xbe,0x27,0xf0,0x29,0x4c,0x6c,0x3d,0x51,0x55,0xe1,0x6d,0x4,0x91,0x2a, + 0xc9,0xe3,0x4d,0x9f,0x6c,0x0,0xe5,0x8a,0x8d,0x9,0x3a,0xbc,0x94,0x5e,0x16,0xd6, + 0x19,0xfb,0x28,0x15,0x79,0x25,0x74,0x1,0x14,0xf4,0x2a,0xc6,0xaa,0xb,0x57,0x25, + 0x2b,0x8d,0xe4,0x83,0x5b,0xbe,0x27,0x2a,0xbf,0x3e,0x24,0xd4,0xf0,0x2a,0xa,0x43, + 0xa9,0xbb,0x55,0xb0,0xa1,0x91,0x8b,0xb,0x5,0xf4,0x5a,0x65,0x87,0xe0,0xe2,0x3e, + 0x66,0xbf,0xdb,0x7e,0x9c,0xff,0xdf,0xff,0xdf,0x53,0xff,0xd7,0xfe,0x25,0xb6,0x52, + 0x99,0x7b,0x3b,0x56,0x6e,0x38,0x88,0xf9,0x68,0xcd,0x57,0xdf,0xb6,0x46,0x2e,0xa8, + 0x3f,0x2a,0xe5,0x4,0x5a,0x7c,0x77,0xb7,0xe0,0x67,0xc7,0x14,0x10,0x74,0x68,0x7b, + 0xd7,0x6f,0x6d,0x89,0xaa,0x39,0x7a,0x97,0x9d,0x6,0xeb,0x55,0x73,0x5,0xad,0x63, + 0xd4,0xdb,0xf4,0x28,0x90,0x3a,0x24,0xa8,0x29,0xb9,0x60,0x49,0x6d,0xb0,0x37,0xda, + 0x36,0x2f,0xb3,0xa9,0x3a,0x26,0x55,0x23,0x75,0x30,0x2c,0xcb,0xdb,0x7a,0x5d,0x4d, + 0x61,0xe4,0x38,0xa6,0x2e,0x27,0xa,0x2b,0xb6,0xf5,0x4,0xb6,0x39,0x22,0x75,0xf3, + 0xd1,0xb1,0x3f,0x7c,0x27,0x1f,0xd6,0xd1,0xc7,0x9,0xf7,0xce,0x0,0xd9,0xcb,0x6e, + 0x2f,0x66,0xdb,0x46,0xe7,0x6a,0x29,0x56,0xf6,0x9a,0x7d,0x7,0x99,0x60,0xc3,0xe6, + 0xb6,0xed,0x50,0xc3,0x5d,0xa9,0x8e,0x4,0x49,0x1d,0xc,0xb0,0xe0,0xde,0xa4,0xf3, + 0x34,0x4c,0x3a,0x4a,0x7e,0x60,0x4a,0x41,0xf8,0x26,0x8f,0x8c,0x23,0x37,0x1d,0x52, + 0x6a,0xf,0x57,0x4b,0x56,0xad,0xfc,0x4f,0x9a,0xc7,0xf1,0x89,0x67,0x44,0x76,0x2f, + 0x47,0x7c,0x72,0x28,0x9b,0xb4,0x9f,0x59,0xe5,0x50,0x51,0x78,0x1,0x6e,0x3f,0x8e, + 0x26,0x63,0x86,0xe,0x17,0x2e,0xaa,0x6c,0xea,0x61,0x56,0x66,0xca,0xa7,0xf6,0xe8, + 0xda,0x10,0xed,0x96,0x7c,0x2,0x97,0xc5,0x54,0xe,0x6f,0x6,0xe6,0x97,0x36,0x5d, + 0xfc,0x2c,0xb9,0x4e,0x88,0x8f,0x38,0x66,0xbc,0xee,0x80,0x4c,0xc7,0xa4,0x3d,0x2e, + 0xb3,0x92,0x80,0x43,0xc8,0xa8,0xb,0xd5,0x6f,0x9f,0x3,0xfc,0x22,0x1b,0x3a,0xd1, + 0xf2,0x2d,0x93,0xcf,0x2d,0x0,0x2f,0xba,0x54,0x64,0x0,0x33,0xe2,0x20,0xdb,0x6d, + 0x76,0xcf,0x93,0xc3,0x53,0x7b,0xaf,0xc2,0x74,0x8,0xe6,0xe3,0xef,0x6d,0x6b,0xaf, + 0xe1,0xa3,0x33,0x8c,0x7c,0x54,0x75,0xa5,0x29,0x8e,0x15,0xae,0x52,0x7a,0x85,0x2, + 0xa9,0x1a,0x9b,0xf6,0x69,0x3d,0xd8,0xd0,0x28,0x6a,0x0,0x87,0xaa,0xbd,0x22,0xea, + 0x87,0x27,0x5a,0x3c,0xad,0x94,0x55,0xaa,0xaa,0x9c,0xc0,0x49,0x3d,0xf9,0xe8,0xc8, + 0x2c,0xb4,0x2e,0x44,0xb5,0x5a,0x26,0xc9,0x88,0x62,0xca,0x4f,0x6e,0x33,0xc8,0x2, + 0xf1,0x6c,0x7,0xaa,0x40,0x9,0xba,0xe,0x7b,0xa9,0x35,0xc2,0x86,0x36,0x3d,0xaa, + 0x73,0xf3,0x9d,0x4e,0xb5,0xa1,0x66,0xc7,0x5e,0xcc,0xb1,0x95,0xcd,0xe1,0x5,0x9b, + 0x6f,0x28,0x5b,0xd9,0x36,0x6c,0x23,0x20,0x56,0xab,0xa,0xaa,0x52,0xc6,0x9a,0xf3, + 0x2e,0xb6,0xc9,0xf9,0x10,0xd1,0xd0,0xd1,0xbc,0x2b,0x1,0x2b,0xbb,0xae,0xed,0x48, + 0x88,0x0,0x14,0x6f,0xb3,0xdb,0x1a,0xf0,0xd1,0x1,0x73,0xa6,0x70,0xb8,0xe1,0x10, + 0x7,0x5,0xcb,0xe,0x7d,0x8,0x1a,0xa1,0x13,0x28,0x4b,0xb7,0xb1,0xf,0xe8,0x42, + 0x14,0x7e,0xeb,0xba,0x10,0x15,0xc8,0xdd,0xa3,0x2b,0x22,0x4f,0xd8,0x9b,0x67,0x1d, + 0xc6,0x11,0x5e,0xc8,0xdc,0xee,0xc4,0x2e,0xe5,0x33,0x8c,0x57,0x8a,0xa3,0x8c,0xa6, + 0x23,0xa9,0x17,0xf9,0x48,0x8,0x76,0x7c,0x83,0x77,0x10,0xd7,0xb0,0x76,0x55,0x80, + 0xad,0x48,0xee,0x12,0xdc,0x12,0x4,0x7a,0xeb,0xe3,0xf,0x78,0x13,0xed,0xa1,0x31, + 0x7,0x97,0xda,0xe8,0xd,0x91,0xba,0xc8,0xa5,0x4b,0xd4,0x2f,0x14,0x11,0x64,0x9e, + 0xd8,0xae,0xed,0x77,0x44,0x88,0x27,0x50,0xb,0x43,0xc7,0xe3,0xff,0xc1,0x27,0xff, + 0xdf,0x1a,0xdc,0x4a,0xec,0x82,0x98,0x5,0x61,0x22,0x2f,0xd,0x38,0xec,0xcd,0x7f, + 0xbe,0xcd,0x14,0x6a,0xc2,0xe3,0x32,0x50,0x1e,0x58,0x6e,0xb6,0x3c,0x77,0xdb,0xbc, + 0x63,0xb1,0x6b,0x5b,0xbe,0x16,0xb1,0x9b,0x63,0xdb,0x29,0xb,0x95,0xc,0xb3,0xa7, + 0x6e,0xdb,0xb6,0xd,0x98,0xa,0xc,0x27,0xbc,0xd8,0x56,0xbc,0x65,0x12,0xb0,0xb2, + 0x4b,0x3b,0x78,0x6f,0xcc,0x77,0x8c,0x9c,0x77,0x98,0xdd,0xb0,0xb7,0x6a,0xd4,0x38, + 0xe2,0xf8,0x5b,0x32,0x8b,0x89,0x78,0xa5,0x2d,0xb3,0xbc,0x10,0x63,0x4f,0xb4,0xcc, + 0x96,0xb0,0x32,0xa,0x2c,0xfc,0x37,0xff,0xe8,0xd1,0xbf,0x15,0xb8,0x3a,0x26,0x6f, + 0x32,0x99,0xe6,0xda,0xa1,0x97,0xd9,0xcf,0xa0,0x88,0x1d,0xfc,0xf9,0x1,0x24,0xfc, + 0xcf,0xf8,0xcf,0x5b,0xbd,0xf6,0x67,0xbd,0xcf,0xe4,0xde,0xfc,0x57,0xbf,0x47,0xd4, + 0xd2,0x85,0x5b,0x50,0xd6,0x9a,0xfc,0x46,0x74,0x2e,0xb3,0x9,0x35,0xcc,0x7f,0xd6, + 0x5,0xaa,0x2d,0x69,0x7,0x0,0x5,0xed,0x26,0x34,0xfc,0x80,0x33,0xf8,0xc2,0x63, + 0xf,0x52,0xbd,0xa6,0x5d,0xd5,0x14,0x20,0xa2,0x8b,0xa1,0x23,0x80,0x6c,0x30,0x2, + 0x12,0x2b,0x99,0xad,0x15,0xc8,0x7e,0x46,0x66,0x4d,0xf4,0xb4,0xd7,0x7b,0xd2,0x34, + 0x0,0x63,0xde,0xa0,0xc3,0xd,0x64,0xd6,0x51,0xe5,0xad,0x32,0x71,0xaa,0xd6,0x4b, + 0xaf,0x6,0x4b,0xab,0x19,0xe1,0xf0,0x1d,0x0,0xe7,0x90,0x0,0xdf,0x18,0x3a,0x52, + 0xdd,0xf,0xe6,0x4e,0xb,0x36,0xac,0xd2,0x2d,0x82,0xd1,0x46,0x28,0xf8,0x19,0x19, + 0x92,0x51,0xee,0x2e,0x55,0x8f,0x49,0x26,0x3f,0x4c,0x42,0x9c,0xee,0x15,0x93,0x48, + 0x9c,0x1c,0xa2,0x6d,0xc0,0xe1,0xba,0x4d,0xb4,0x6f,0xd6,0x7e,0xd6,0x2a,0xf6,0x6d, + 0xdb,0x6a,0x65,0xb8,0xd5,0x8e,0xe4,0x66,0xe6,0xbe,0x6d,0xbe,0xb5,0x36,0xe5,0xd6, + 0x10,0xf0,0xed,0x37,0x6d,0x22,0xb1,0x68,0xd,0xe8,0xdd,0xee,0xfb,0x1e,0xbd,0x5b, + 0x90,0xae,0x8e,0x6d,0xc0,0x89,0xee,0x23,0xdb,0x12,0xa4,0x32,0x2,0xd,0x55,0xe9, + 0xc6,0x4e,0xde,0xb0,0xcc,0x58,0x84,0x26,0x39,0x6e,0x41,0xd,0xf2,0x2d,0x78,0xbd, + 0x62,0xc4,0x8a,0xe4,0x34,0xcf,0xaf,0xdd,0x7c,0xf3,0x43,0xc2,0x98,0xf9,0xbf,0x87, + 0x6d,0x67,0xbd,0xc1,0xcd,0xcb,0xad,0x8f,0x69,0xf7,0xc4,0xab,0xcd,0xb6,0x36,0x6f, + 0xda,0xc7,0x9b,0x99,0xa3,0x75,0x5e,0x88,0x3f,0xed,0xdc,0x6d,0xe0,0xeb,0x6b,0x3e, + 0x6a,0xcd,0xc,0x97,0x1,0x84,0x3d,0x68,0x43,0xfe,0xcc,0x63,0xe,0x1f,0xa6,0x34, + 0x0,0x71,0x9,0x82,0x91,0xb,0xdd,0xa6,0xa1,0x68,0x42,0x96,0x40,0x63,0xdd,0x4e, + 0xe8,0xad,0x9,0x67,0xd,0x8b,0x34,0x9b,0x4e,0xe2,0x4f,0xd6,0x3a,0x54,0xc,0xba, + 0x8f,0x9c,0xb1,0xb7,0xdd,0x37,0x8f,0x39,0xbf,0x6a,0xf0,0xf4,0x1,0x48,0x4d,0xaa, + 0xf6,0x40,0xee,0xbd,0x4d,0x53,0x81,0x71,0xa8,0x50,0xb8,0x5d,0x79,0xbf,0x22,0xde, + 0x6b,0x30,0x87,0xfb,0x56,0x47,0x35,0x6e,0xbe,0x6d,0xde,0x22,0x77,0x87,0x99,0x56, + 0x2b,0xbc,0x7d,0x6f,0x39,0x41,0x24,0xab,0x54,0xe0,0xc0,0x5d,0x30,0x8e,0x23,0x58, + 0x62,0xea,0x29,0x8b,0x9f,0x15,0xfd,0xec,0xb0,0x3c,0x3e,0xe,0xd8,0x89,0xd3,0xeb, + 0x4f,0x6a,0x73,0xdf,0x26,0xcd,0x81,0xb9,0x7c,0x0,0xfa,0xc2,0xc6,0xb0,0xfd,0x94, + 0x0,0x54,0x2c,0x9a,0xb3,0xab,0xcc,0x17,0x68,0xc,0x62,0xa2,0xfd,0x1e,0xb7,0x6a, + 0x34,0xe,0x61,0x7a,0x57,0x6a,0x67,0x90,0x95,0x68,0xa4,0xa6,0x25,0x85,0xb2,0x4e, + 0xa7,0x1a,0x5e,0xef,0xc3,0xba,0xd3,0x6d,0xb8,0x2b,0x77,0x51,0x8a,0xa4,0xcd,0xdb, + 0x25,0xb6,0xe4,0x43,0x6c,0xfe,0xb3,0xe0,0xb2,0xcb,0xdc,0x7a,0xe1,0xf8,0xcb,0x9c, + 0x1,0x42,0x53,0xeb,0x78,0x67,0xfc,0xff,0xdc,0xbd,0x57,0x93,0x65,0x57,0x76,0x26, + 0xf6,0xad,0x7d,0x6d,0x7a,0x6f,0x2b,0xb3,0xbc,0x41,0xa1,0x50,0x28,0xb8,0x46,0x77, + 0xb3,0xd9,0x6c,0xb2,0x87,0x43,0xce,0xc,0x29,0xf2,0x41,0x13,0x13,0xa,0xc5,0x88, + 0x8a,0xd0,0x1f,0xd3,0x8b,0xa4,0x27,0x29,0x82,0x31,0x33,0x9a,0xa1,0x46,0x24,0x41, + 0xb6,0x41,0x37,0xba,0xe1,0xb,0x28,0xa0,0x50,0xde,0x64,0x65,0x56,0x7a,0x9f,0x37, + 0x6f,0xde,0xbb,0x97,0x1e,0xb6,0x5b,0x6b,0x9f,0x73,0xab,0x6a,0x28,0x2a,0x44,0xa9, + 0x9a,0x20,0x50,0x69,0xaf,0x39,0x67,0xaf,0xb5,0xbe,0xf5,0x19,0xb9,0x77,0xca,0x2f, + 0x4,0x2e,0xa6,0x9f,0x49,0x7,0x22,0x96,0x8c,0xf7,0x0,0x50,0x65,0x47,0x5e,0x26, + 0x29,0x94,0x31,0xab,0x9c,0x67,0x97,0x9,0x84,0x84,0xb3,0x2e,0x92,0x4a,0x2e,0x50, + 0x12,0x21,0x50,0xc9,0x5b,0x40,0x1e,0x20,0x1,0x99,0x10,0x6c,0x5b,0x32,0xb2,0x7e, + 0x53,0x8,0x6,0xf1,0xda,0xdd,0x50,0x53,0xa4,0x2c,0x8a,0xa2,0x5d,0xbc,0x43,0x2a, + 0xd,0xe0,0x25,0x69,0x26,0x1d,0x86,0x52,0x1b,0x1d,0x89,0x6e,0xfe,0x63,0xb2,0x88, + 0x23,0x70,0xc0,0x14,0xf5,0x21,0xce,0xa9,0x24,0x24,0x82,0x84,0xac,0x68,0xeb,0xe0, + 0x5e,0x7d,0x55,0xe7,0x69,0x74,0x25,0xb1,0xc3,0x69,0x7b,0x93,0xf2,0xe3,0x52,0x7a, + 0xb7,0x97,0xdf,0x92,0x31,0x6e,0x1e,0x8f,0x8c,0x5e,0x62,0xb0,0xb5,0x30,0xc6,0x90, + 0x65,0x47,0x73,0xb7,0xe,0x76,0x87,0x25,0x4b,0xc6,0x1a,0x37,0xc9,0xfb,0xad,0xa0, + 0x85,0x38,0xbb,0x93,0x5e,0x85,0xf5,0x1e,0x2e,0x41,0xba,0x62,0xd2,0xf6,0x53,0xa0, + 0xf1,0x20,0xbb,0x2e,0xe2,0x20,0x22,0x27,0xeb,0xa,0xce,0x35,0x8a,0xad,0xcd,0x5a, + 0xbc,0x40,0xf9,0xe9,0xa5,0x73,0xd7,0x19,0x65,0x9e,0x49,0x62,0x85,0xc9,0x85,0x8, + 0x7a,0x81,0xf7,0xc9,0x38,0xe1,0x60,0x14,0x12,0xdc,0xd7,0xc8,0x67,0xdb,0xca,0xdb, + 0x3c,0xd1,0x54,0x7c,0xb,0x1a,0x93,0x44,0xd9,0x73,0xbc,0xe2,0x94,0xc6,0x89,0x79, + 0x1f,0x62,0x68,0xc1,0xc,0xc3,0x61,0xaf,0xe7,0x49,0x70,0x4c,0x4c,0xb0,0xc6,0xb7, + 0xc7,0x36,0x1a,0x47,0xab,0xa0,0xb2,0xc0,0x9d,0xe4,0xa4,0xfa,0x4b,0x45,0x5b,0x15, + 0x75,0x7f,0x3d,0xeb,0xe9,0x3d,0xd,0xd9,0x46,0x70,0x3f,0xbc,0x87,0x42,0x72,0x8a, + 0x8b,0x7c,0x8f,0xa4,0x54,0x4b,0xd6,0x9,0x5,0x57,0x34,0x12,0xef,0x91,0x5a,0x23, + 0x96,0x8e,0x3d,0x2,0x39,0x4c,0xf6,0xb4,0xe9,0x5c,0x62,0x41,0x5f,0xca,0x56,0x53, + 0x2e,0x56,0xce,0x72,0x4a,0x48,0x4c,0x9e,0x74,0x2a,0xa8,0x85,0xa2,0xa5,0xb1,0x3, + 0xef,0x2a,0x14,0xb4,0xff,0xae,0x39,0xd,0xc1,0x96,0xe,0x35,0xb7,0x3e,0x68,0xcf, + 0xad,0xa4,0x9c,0x9b,0xa2,0xf5,0x80,0x83,0x2f,0xf6,0xc6,0x90,0xb1,0xd6,0xf1,0xd, + 0xac,0xfb,0x66,0x1b,0x6d,0x8a,0x3d,0x49,0xcd,0xb2,0x32,0x90,0x88,0xfc,0x3f,0xce, + 0x82,0xad,0x38,0x1b,0xbe,0xf2,0x11,0xa7,0xc4,0x25,0x54,0x22,0x1e,0x85,0xf5,0x2e, + 0x65,0x2c,0x77,0x14,0xb8,0x6a,0xe1,0xa3,0x55,0xc5,0x20,0x16,0x1d,0x96,0xb6,0xa5, + 0xcb,0x8b,0x9d,0x88,0x2b,0x14,0x93,0x45,0x64,0x30,0xb2,0x94,0xe8,0x72,0x26,0x5f, + 0x82,0x28,0x94,0x50,0x52,0x2f,0xd9,0xa9,0x92,0x0,0x76,0x24,0x43,0x2e,0xad,0x71, + 0x29,0x8b,0xeb,0x2c,0x81,0xa9,0x59,0x13,0x36,0x62,0xfc,0x6a,0xee,0x8f,0xce,0x89, + 0xb5,0x42,0x99,0x8c,0x4f,0x5a,0x4a,0x32,0x93,0x2e,0x76,0x4c,0x2a,0x66,0xb5,0x90, + 0xf1,0xa0,0x62,0x9e,0x50,0x94,0x2a,0xb0,0x8e,0x17,0x55,0xb7,0x4,0x4b,0xd2,0xa1, + 0x8e,0x41,0x95,0xae,0x52,0x4a,0x2,0x58,0x6,0x69,0x53,0x81,0xc3,0x22,0x1a,0x3, + 0x48,0x43,0xb0,0xe0,0xab,0x5d,0x70,0x9a,0xcb,0xed,0x4a,0xb,0x6b,0x1,0x59,0xb9, + 0xb,0x96,0xb8,0x8a,0x66,0x9c,0x41,0x4b,0xc8,0xa8,0x86,0x5a,0xbc,0x29,0x5d,0xc2, + 0x3,0xf1,0x9b,0x38,0x4d,0xe2,0x9a,0x51,0x1d,0x90,0x34,0x23,0xd,0x4e,0x8c,0x9b, + 0xca,0x3d,0x6b,0xdd,0x90,0x98,0x1e,0xd,0x9,0xca,0x9b,0x82,0x2b,0x4d,0x74,0xaf, + 0x8e,0x9,0xea,0x59,0xcc,0xb7,0x1c,0xa2,0x4c,0x6c,0x3d,0x48,0xb8,0x70,0x15,0xf6, + 0x5c,0x52,0x7e,0xa7,0x1a,0x5c,0x22,0xa8,0x0,0x9b,0x78,0x73,0x73,0x16,0xbd,0xe3, + 0xea,0x87,0xf1,0x66,0x6a,0x41,0x9e,0x61,0x39,0x1c,0xce,0x7e,0x42,0x71,0x8b,0xf1, + 0x60,0x78,0xc2,0xd6,0x5a,0x97,0x46,0x63,0x63,0x31,0x67,0xc3,0x86,0xac,0xb1,0x54, + 0x61,0xc3,0x5d,0xb6,0xfe,0x50,0x7,0xdb,0x24,0xc9,0x11,0xeb,0xfd,0x94,0xd1,0x96, + 0xd2,0xeb,0x5c,0xc0,0x97,0x13,0xeb,0x6,0x35,0xa0,0x49,0x6b,0x8e,0xf0,0xdf,0x10, + 0x53,0xa4,0x27,0xcb,0xb1,0xe0,0x39,0x8,0xd,0x60,0xb8,0x2e,0x83,0x5e,0x5a,0x25, + 0x56,0x19,0xa9,0x81,0xf7,0xa8,0x5,0x17,0xc5,0x23,0xa4,0x5d,0xa7,0x75,0x39,0x12, + 0x93,0x76,0xa,0x14,0x37,0x24,0x82,0xf7,0x14,0xbf,0x37,0x5e,0xa9,0x96,0x39,0xba, + 0xe3,0x31,0x87,0x2c,0x4e,0x4,0x21,0x9d,0x9f,0xba,0x39,0xaa,0xe9,0x4c,0x1c,0xb9, + 0x1d,0x9b,0xda,0x23,0x2b,0xde,0x7e,0xcc,0x6f,0x85,0x82,0x31,0x5d,0x85,0x51,0xda, + 0xf0,0x42,0x48,0x36,0xa2,0xc7,0x82,0x54,0xee,0x8b,0x6b,0x35,0x9a,0x94,0x27,0xe, + 0x48,0x62,0x4,0x93,0x1a,0x8b,0x8d,0x34,0xfc,0x91,0x9,0x78,0xfe,0x99,0x47,0xc3, + 0x24,0x39,0x57,0x68,0x62,0x1c,0x9,0xdb,0xb2,0x5,0x30,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x2e,0x8e,0x2e,0x30,0x6,0x8c,0x12,0x63,0xb2,0x2,0xb1,0x52,0x1e, + 0xde,0xc,0x42,0x9e,0xb4,0xe3,0x33,0xdf,0x99,0x59,0x6b,0xe8,0xc2,0xee,0x5c,0x7a, + 0x27,0x4a,0xd0,0x3b,0xf4,0xfc,0xce,0x5a,0x6,0x6c,0x9d,0x9b,0x13,0x5b,0xb0,0x71, + 0xdd,0x2e,0x79,0x1a,0x1e,0x1b,0xb6,0x81,0x8a,0xe7,0x78,0x71,0x64,0x18,0xb0,0x2e, + 0x63,0xd6,0x5a,0x9f,0x77,0x10,0x7b,0x83,0x40,0x8,0xb4,0x30,0x91,0xdf,0x42,0x86, + 0x9,0x36,0xfa,0xb8,0x89,0x22,0xca,0xc5,0x1c,0xd,0x4a,0xb1,0xef,0x2a,0x8e,0x54, + 0x4c,0xed,0x12,0x19,0xd1,0x88,0xb9,0x8c,0x22,0x12,0xbe,0xee,0x3d,0x12,0x19,0xab, + 0x6a,0x12,0x96,0xf2,0x2f,0x41,0xe3,0xe5,0x3c,0x53,0xa2,0x68,0x33,0x20,0x26,0x41, + 0xca,0x5c,0xe3,0x92,0xa9,0x48,0x28,0x52,0xac,0x9c,0xc,0xa5,0x79,0x85,0xce,0xb4, + 0xa6,0x12,0x8c,0x82,0x45,0x1a,0x5a,0xa1,0x88,0xaa,0x41,0x95,0xa,0x8f,0x31,0x25, + 0xa5,0x91,0x92,0x50,0xa9,0x59,0x9f,0x50,0x42,0x6a,0xcb,0xed,0x38,0x49,0x91,0x1a, + 0x48,0xb1,0x70,0xc5,0xe3,0xc8,0xd7,0xfa,0x59,0x71,0xcc,0xa1,0x2b,0x95,0xca,0x46, + 0x42,0xd3,0x8,0xcd,0xf0,0xcd,0x19,0xfd,0xb1,0x83,0x93,0x64,0x43,0x82,0xea,0xf8, + 0xa4,0x46,0x94,0x95,0xb2,0x90,0x54,0x48,0x69,0x9e,0x16,0x9f,0x90,0x71,0x16,0xc1, + 0x89,0xa4,0xfd,0x21,0x62,0x7a,0x9a,0x30,0xad,0x1,0x84,0xa7,0x1d,0x15,0x1b,0x4f, + 0x79,0x51,0x46,0x0,0x24,0x4c,0xad,0x26,0xcd,0xaa,0x26,0x18,0xbe,0x80,0x54,0x52, + 0x14,0x19,0x17,0x17,0x96,0x12,0xca,0xd3,0x7e,0xdc,0xc0,0x78,0x6b,0xca,0x50,0x67, + 0x8c,0x80,0xd7,0x8d,0x84,0x2d,0x93,0x5c,0x8d,0xc5,0x64,0x2f,0x9c,0xe2,0x98,0x44, + 0x9,0xcf,0xec,0x9b,0x2a,0x81,0xd6,0x6e,0x44,0x6e,0x2d,0xe9,0x8e,0x4,0x99,0x6b, + 0x6c,0x4a,0x9d,0x12,0x7b,0x72,0xe3,0x53,0x2a,0x39,0x4e,0x32,0x14,0x36,0xb0,0x19, + 0x9b,0x84,0x92,0xd9,0x95,0xfb,0xa2,0x4a,0x16,0x76,0xea,0xcc,0x71,0xbc,0x14,0x17, + 0x96,0xc8,0x18,0xb,0xb6,0x44,0xc6,0xc0,0x5a,0xcb,0x15,0x18,0xb2,0xb0,0x5c,0x71, + 0x13,0x3b,0x55,0xfc,0xe4,0x2,0x58,0x17,0xf4,0x92,0x3c,0xb8,0x62,0x1d,0xd0,0x16, + 0xba,0x61,0x29,0x1e,0x21,0xf5,0x88,0x74,0x50,0x20,0xc2,0x85,0xa2,0x1e,0x9d,0xcb, + 0xc4,0xe,0x38,0xed,0x78,0x43,0x2e,0x8,0x47,0x66,0x5d,0xa2,0x2e,0xe6,0xe1,0x41, + 0x10,0x53,0x21,0xf5,0xc8,0xec,0x96,0xdc,0x1c,0x62,0xe6,0x7c,0xdd,0x95,0x1c,0xf0, + 0xb2,0xce,0x58,0x85,0x73,0x8b,0xbb,0x3f,0xe8,0x8f,0xa1,0x9c,0xd6,0x15,0x31,0xb, + 0x54,0xa1,0x94,0x97,0xce,0x9c,0x86,0x78,0xe2,0x64,0x6c,0xc9,0x1c,0xe3,0x49,0xe2, + 0x5e,0x3d,0xc4,0xf0,0x70,0xf4,0x79,0x29,0x18,0x4d,0x19,0x3f,0xd8,0xfb,0x3f,0xd1, + 0xf6,0x47,0x9a,0xc8,0x70,0x6c,0xa8,0x28,0xb1,0x6a,0x3d,0xe8,0x1e,0x7d,0x64,0x15, + 0xa1,0x7,0x29,0xf2,0x37,0x97,0x94,0x90,0x3e,0xd,0x24,0x1d,0x5d,0x5c,0x87,0x46, + 0x2e,0x43,0x24,0x5,0x86,0xa9,0x98,0x82,0x87,0x92,0xb9,0x2d,0x1a,0x5d,0xa9,0x45, + 0x15,0x47,0xec,0xc3,0x37,0xef,0x6e,0x60,0xf2,0x84,0x83,0x18,0x6b,0x1e,0x3e,0x27, + 0x34,0xc7,0x1e,0x46,0xf2,0xdb,0x6c,0xef,0xe7,0x66,0x1c,0x28,0x6e,0x5d,0x88,0x30, + 0x47,0x75,0x1a,0x59,0x43,0xce,0x2d,0x82,0x2d,0xfb,0xc9,0xdd,0x5a,0xc3,0x64,0xac, + 0x6f,0x7e,0xfd,0x7f,0x44,0x67,0x15,0xf6,0x6c,0x3,0xb2,0x4,0x76,0xe1,0x2d,0x49, + 0x44,0x6f,0xe0,0x34,0x6d,0x59,0x6c,0x2a,0xb2,0xa0,0x4e,0x1d,0x7b,0x6a,0x44,0xda, + 0x67,0x40,0x29,0x53,0xf2,0x27,0x17,0xec,0xc6,0x8d,0xa,0xd,0xcb,0xcd,0x64,0x64, + 0xe1,0xab,0x7a,0x2f,0x6b,0x5,0xc8,0x73,0xb1,0xbf,0x85,0xf6,0x9c,0xa6,0x12,0xf0, + 0x30,0x9f,0xc2,0xf5,0x25,0x20,0xf7,0x82,0x44,0x65,0x20,0xbe,0x28,0xfe,0x12,0x1e, + 0xb,0x14,0x27,0x96,0xbb,0x45,0xe9,0xf9,0x1d,0x8d,0x26,0x74,0x3e,0xbb,0x60,0xc1, + 0x72,0xa9,0x30,0x48,0x96,0x2e,0x4d,0x0,0x54,0x12,0xac,0x60,0x91,0x59,0x8,0x17, + 0x65,0x25,0xd5,0x2b,0x48,0xcb,0xfd,0x89,0x18,0xe1,0x3c,0x41,0x2a,0x94,0x6,0x2, + 0x54,0x80,0xcc,0xb9,0xd0,0xdc,0xe6,0x1b,0x11,0x69,0xd,0xab,0xf2,0xaa,0x73,0xde, + 0x1f,0x53,0x26,0x45,0xcb,0x3d,0x2c,0x58,0xaf,0x82,0x5,0x64,0x4f,0x65,0xa9,0x9f, + 0xa9,0xa7,0xd6,0x8d,0x91,0x42,0x74,0xa8,0xf0,0xfb,0xf3,0x8f,0x43,0xeb,0xd4,0x3, + 0x66,0x9e,0xc9,0x24,0x29,0x42,0x13,0xd1,0xd8,0x42,0x44,0x4a,0x31,0xa5,0xa2,0x62, + 0x42,0xa1,0xa9,0x78,0xa8,0x17,0x1e,0x62,0x67,0x31,0x9,0x9a,0x30,0x4d,0x82,0x9c, + 0x92,0x2b,0xd,0x9d,0xb1,0xc0,0x44,0x83,0x93,0x64,0x4e,0x23,0x22,0xfd,0x48,0x1d, + 0x73,0x9c,0xa4,0x5c,0x7a,0xfb,0x2b,0x15,0x6b,0xd0,0xfa,0x14,0x2a,0x7b,0x43,0x93, + 0x13,0xa6,0x58,0x6d,0xa,0x29,0xb5,0x96,0x53,0x3a,0x68,0xdc,0x89,0x77,0x48,0xa, + 0x5d,0xc8,0xb8,0x4d,0xad,0x63,0x61,0x87,0x43,0xd4,0xc0,0x90,0x35,0x6c,0xd,0x33, + 0x5b,0x9f,0xd6,0x61,0x3,0xd3,0xcd,0x11,0x83,0x8d,0x73,0xaf,0x6,0x99,0xb8,0x23, + 0x8e,0x7,0xe,0x67,0x90,0xa8,0x44,0x34,0x8c,0xfb,0xe9,0x9e,0x83,0xe0,0xac,0x50, + 0x4c,0x20,0xca,0x19,0x5f,0x70,0x8c,0x37,0x46,0x75,0xd0,0xba,0x49,0xc4,0x42,0x48, + 0x81,0xa0,0x84,0x89,0x88,0xa9,0x40,0x95,0xa6,0x12,0x9f,0xa,0x69,0x7a,0x63,0xa0, + 0xd7,0x53,0xd1,0x57,0x5f,0xee,0x73,0x49,0x99,0x21,0x82,0xb2,0x3,0x33,0x69,0x14, + 0xa3,0xc2,0x9,0x49,0xff,0x15,0xdc,0xd9,0xfd,0xdd,0x69,0x39,0x41,0x19,0xde,0xdc, + 0xc4,0xe9,0xcf,0x53,0xec,0x3c,0xac,0xdb,0x7f,0xc4,0xcb,0x3f,0xb4,0xab,0x96,0x61, + 0x29,0x11,0xb7,0xa4,0x2d,0x9f,0x5a,0x45,0x47,0x83,0x43,0x8,0x4,0x9,0x52,0xcb, + 0x1f,0x5e,0xfb,0x24,0x1,0x34,0x82,0x89,0xec,0x7d,0x16,0x90,0xf2,0xe6,0xa5,0x90, + 0x33,0xdb,0x90,0xaa,0xc3,0xa1,0x10,0xf7,0xc9,0xca,0x26,0x41,0x17,0x96,0x92,0x1f, + 0x94,0x1c,0x24,0x4b,0xe8,0x40,0x72,0x98,0x48,0xe2,0x9,0xff,0x42,0xfa,0x52,0x47, + 0xe9,0x4c,0x65,0x36,0xa4,0xd5,0xc3,0xe1,0x9d,0x10,0x42,0x29,0xf8,0x32,0x1e,0xb0, + 0x1b,0xf2,0xc4,0x3,0xb,0x76,0x3a,0x42,0x30,0xac,0xe3,0x91,0xa0,0x52,0x31,0x60, + 0xeb,0x60,0x78,0x3,0xc3,0xcc,0xd6,0x38,0x13,0x78,0xeb,0x24,0x21,0x6c,0xd9,0x54, + 0xc,0x71,0xd7,0x32,0x3b,0x64,0x8b,0xd9,0x80,0x6d,0x97,0x25,0x7f,0x28,0x66,0x14, + 0xd8,0x8,0xdb,0x38,0x4f,0x7d,0x66,0x56,0x83,0x19,0x4b,0x70,0x22,0x3f,0xe,0x8a, + 0xe,0x9c,0x72,0x6d,0x2c,0xd3,0xe7,0x19,0x25,0x96,0xe1,0x1,0x4d,0xf,0x88,0xad, + 0x83,0xdc,0xa9,0x64,0xd8,0xce,0xfd,0x4e,0x73,0x2,0xbd,0x74,0x30,0x84,0x12,0xa9, + 0xc5,0x6c,0xf5,0xe0,0x85,0x2f,0x4d,0xea,0xa3,0xee,0x18,0x5,0xe8,0x95,0xe5,0x3e, + 0x3b,0x3c,0xd,0xca,0x25,0x68,0x61,0xda,0xc,0x92,0x63,0x4e,0xba,0x39,0x25,0x9f, + 0x52,0xa8,0x8e,0x9a,0xe8,0x59,0x16,0xe2,0x78,0x55,0xe5,0x4e,0x13,0x9c,0x3d,0x67, + 0x2a,0xc9,0x9a,0x21,0x5,0xfd,0x13,0x6b,0xb8,0x4c,0xa5,0xac,0x11,0x21,0x6f,0xab, + 0xd4,0xb4,0xaf,0x20,0xf3,0x92,0x73,0x94,0x35,0xc2,0x50,0x64,0xb1,0xf7,0x78,0xff, + 0xa8,0x7,0xcb,0x9d,0xf3,0x5b,0xb9,0x24,0x20,0x84,0xca,0x7f,0x34,0x65,0xe6,0x8, + 0x79,0x85,0x22,0xe2,0xd2,0x6f,0xa4,0x3c,0x32,0x54,0x7e,0x5c,0x66,0xfb,0x92,0x3e, + 0x3c,0xc,0xc9,0xa8,0xc8,0xc4,0x56,0x4f,0x93,0x75,0x5c,0xad,0x9b,0x0,0x3d,0x86, + 0x7d,0x39,0x2a,0xf0,0x53,0xa2,0xf1,0x93,0x24,0x49,0xc3,0x13,0xa3,0xc,0x50,0xa0, + 0x8b,0x77,0x94,0x9,0x49,0x67,0x13,0x32,0x89,0x84,0x10,0xa7,0x18,0x13,0xfd,0xff, + 0x28,0x9f,0x7a,0x44,0x6,0x78,0x28,0xde,0xfd,0xfd,0x75,0xc,0xf6,0x35,0xa8,0xaf, + 0xaf,0x8e,0x81,0x46,0x1d,0x7d,0x8d,0x3a,0x9a,0x8d,0x1a,0xfa,0xfb,0xea,0xd4,0xdf, + 0xa8,0xa3,0x5a,0x21,0xe7,0x94,0x49,0x40,0xb7,0x6b,0xd1,0xe9,0x58,0xde,0xd9,0x3f, + 0xc2,0xfa,0xf6,0x1,0x9e,0xad,0x6e,0xf3,0xd6,0xfe,0x41,0x8a,0x41,0x2d,0xb8,0x2a, + 0xf8,0xa9,0xc4,0x58,0xeb,0x4f,0x78,0x30,0xac,0x1,0x19,0xeb,0x42,0xac,0xfc,0x4e, + 0xde,0x1a,0xa7,0xde,0x21,0x72,0x7b,0x75,0xef,0xa9,0xe0,0xea,0x50,0xb2,0xa8,0x55, + 0x4f,0x23,0x4c,0xe5,0x50,0x70,0x79,0xdc,0x9c,0x7,0x85,0x94,0xc0,0x3e,0x4c,0x80, + 0xe6,0xc3,0xae,0xdd,0x19,0x72,0x27,0x12,0x63,0x61,0x8d,0x98,0xf6,0xbc,0xd2,0x6e, + 0xc0,0xf9,0x7f,0x19,0x21,0x22,0x14,0x10,0x3a,0xe7,0x13,0x8b,0xca,0xd9,0xcc,0xec, + 0x85,0x49,0xeb,0xa2,0xd4,0xdd,0xc0,0x19,0x1a,0xe9,0x5d,0x5,0x38,0xed,0xb0,0x23, + 0xd3,0xd9,0x23,0x45,0x69,0x92,0xf0,0xaa,0xac,0x90,0xe0,0xed,0x3f,0x48,0x29,0x93, + 0x1e,0x6c,0x10,0x7c,0xca,0x8c,0x33,0xed,0x4b,0x1c,0xc7,0x18,0xc,0x28,0x91,0xb2, + 0xf8,0x7a,0x50,0xa2,0xb8,0x9a,0xa0,0xe5,0xf,0x13,0x7a,0x82,0x22,0x3,0x0,0x4f, + 0x1e,0x6b,0xf0,0xea,0x83,0x84,0x5,0x7a,0x34,0x2b,0xd3,0xb9,0xb0,0xc4,0xf1,0xc1, + 0x0,0x6a,0xb5,0xa,0x6,0x9b,0x75,0x34,0x1b,0x75,0x6a,0x36,0x6a,0xe8,0xab,0xd7, + 0xd0,0xa8,0x55,0xd1,0xec,0xab,0xa3,0x5e,0xad,0x50,0xad,0x6a,0x50,0x31,0x6,0xc6, + 0xb8,0x7f,0x93,0x21,0xd4,0x8c,0x47,0x98,0x1c,0xd5,0xc,0x96,0x2d,0x6c,0xf0,0xc7, + 0xb0,0x8c,0x2e,0x5b,0x74,0xba,0x8c,0x4e,0xa7,0x8b,0x93,0x4e,0x17,0xed,0x93,0xe, + 0x77,0x3a,0x16,0x27,0xdd,0xe,0xda,0xed,0x2e,0xb5,0x3a,0x1d,0xb4,0x5a,0x27,0x38, + 0x68,0x1d,0x73,0xeb,0xf8,0x4,0xdd,0x2e,0xcb,0xa6,0x2a,0x1a,0x1a,0x71,0xcc,0xe9, + 0xc8,0x38,0x56,0x24,0xc2,0xc3,0x4c,0x60,0xff,0xb9,0xcb,0x1a,0x20,0x22,0xb,0xeb, + 0xd4,0xf,0xd6,0x13,0xfb,0xd,0x93,0x89,0xec,0x45,0xb8,0xd9,0xdb,0x7a,0xd8,0x9d, + 0x45,0xbc,0x97,0x5,0xd8,0x90,0x31,0xc,0x8b,0xb0,0xd7,0x8a,0xc2,0x37,0x90,0xcc, + 0x2e,0x15,0x39,0x2,0x3a,0xd,0x56,0x57,0x3c,0xbd,0x88,0x83,0x34,0x9c,0x52,0x48, + 0x72,0xbe,0xd4,0x64,0xb5,0x86,0xd6,0x8,0xab,0x3c,0x97,0xab,0x2c,0xa1,0x6d,0xa5, + 0xa1,0xa3,0x82,0x23,0x90,0xca,0xe9,0x2e,0x21,0xd2,0x91,0xb2,0x74,0xa5,0x42,0x1, + 0x28,0xc5,0xa0,0x95,0x40,0x97,0x94,0x56,0x91,0x44,0x71,0x92,0x30,0x38,0x51,0x89, + 0x46,0x1b,0x72,0x9f,0xdc,0x23,0xdb,0x26,0x7b,0x1e,0xc5,0xc9,0x5d,0x1a,0xda,0xc8, + 0x6a,0xc4,0x99,0x49,0xb,0x17,0xf7,0xf,0xaa,0xe7,0x35,0x2f,0x72,0xb0,0x57,0x49, + 0x6c,0x4c,0xac,0xa5,0x6d,0x65,0xeb,0xc,0x92,0x40,0x7f,0x1e,0xc9,0xca,0xe5,0x94, + 0x78,0x42,0x76,0xe9,0x48,0xfb,0xe1,0x5e,0x54,0xfa,0x2,0xcb,0x48,0x1,0xf0,0xc5, + 0xb5,0x4d,0x4e,0x49,0xe4,0x22,0xb,0x51,0x12,0x3e,0x73,0x6d,0xba,0x9c,0xa,0x2, + 0x21,0x47,0x98,0xc8,0xb0,0x40,0xe5,0x54,0x21,0x50,0x76,0x97,0x70,0xa4,0x2b,0x7, + 0x9a,0x1b,0x27,0xcb,0xf1,0x90,0xaf,0xdf,0xdd,0x26,0x6,0x7b,0x28,0x3e,0x71,0x8f, + 0x6e,0x48,0x76,0x66,0x71,0xc2,0x49,0x1a,0x34,0x82,0x49,0x68,0x79,0xf0,0xc1,0x14, + 0x65,0x3e,0xf7,0x3d,0x20,0xe1,0xe2,0xc3,0x51,0xb0,0xb,0x6a,0x36,0xaa,0x18,0x1d, + 0x1c,0xc0,0xa9,0xe9,0x11,0x9a,0x9b,0x1c,0xc5,0xdc,0xe4,0x30,0x66,0xc6,0x87,0x69, + 0x6a,0x62,0x10,0x53,0x63,0x43,0x98,0x1e,0x1b,0xa2,0x99,0xf1,0x61,0xf4,0x35,0xaa, + 0xa8,0x54,0x2a,0x20,0x22,0x74,0x3a,0x1d,0x1c,0x1e,0x77,0x70,0xef,0xf1,0x73,0xfe, + 0xfc,0xbb,0x25,0xfc,0xf2,0xf3,0xbb,0xf6,0xeb,0x7b,0xcf,0xb0,0xb2,0xb9,0x1b,0xe8, + 0x3e,0xd1,0xe9,0x4d,0xf1,0xb8,0xc9,0x18,0x66,0x77,0xea,0x18,0xe7,0xdb,0x4e,0x64, + 0xc8,0xed,0xd3,0x3d,0x5a,0xcc,0xb6,0x42,0xc4,0xc,0x4b,0x36,0xb9,0xe4,0xf8,0x4b, + 0x97,0xc5,0x96,0x52,0xc8,0xe1,0x3,0x61,0x2a,0xc2,0xe7,0x9,0xf5,0x30,0x26,0x70, + 0xe,0x9c,0x8f,0x3c,0x87,0xa4,0x78,0x13,0xc8,0x73,0xd1,0xe7,0x2c,0x8d,0x88,0x4, + 0x4a,0xf9,0xe8,0x71,0x53,0x67,0x4,0xbc,0x1e,0x1a,0x7d,0xc3,0x14,0x77,0x45,0xa2, + 0x71,0x74,0x4f,0x8b,0x33,0xc2,0xac,0xb8,0xae,0xbc,0xe7,0xbb,0x36,0x3a,0xc,0xde, + 0x7d,0xc2,0x4d,0x25,0xf5,0x94,0xa1,0x28,0xfb,0x62,0x60,0x2,0xef,0x4d,0x49,0x6a, + 0x59,0xb0,0x7a,0xe5,0x72,0x20,0xa8,0x95,0x38,0x4c,0xde,0x3e,0xb9,0x53,0xdc,0x94, + 0xd2,0x64,0x6,0xae,0x55,0x11,0xa,0x11,0x71,0x58,0x9b,0xb4,0x9b,0xf1,0xad,0x96, + 0x91,0xec,0x38,0x9f,0xc1,0x2e,0xf8,0x23,0xfe,0xf4,0xa,0x2b,0x2a,0x8e,0xc,0x38, + 0x12,0x11,0x46,0x1c,0xd7,0xf1,0x9c,0x11,0xb2,0x4c,0xc5,0xd0,0xd8,0x50,0x1f,0xa6, + 0xc7,0x87,0x68,0x76,0x7c,0x18,0x13,0xa3,0x3,0x18,0x1f,0x19,0xc4,0xc4,0xe8,0x0, + 0x4d,0x8e,0xe,0x61,0x62,0xa4,0xf,0xc3,0x3,0x7d,0xe8,0x6b,0xd6,0xa9,0x5e,0xad, + 0xa0,0x5e,0xab,0xa2,0x5e,0x73,0xff,0x6e,0xd4,0xab,0xa8,0x57,0x2b,0xb0,0x96,0x71, + 0xd2,0xb5,0xe8,0x74,0x2d,0xd8,0x32,0x3a,0x5d,0x8b,0x4e,0xb7,0x8b,0x4e,0xd7,0xa2, + 0xd5,0x3e,0xc1,0xe1,0xd1,0x31,0xf6,0xe,0x8f,0xf9,0xe0,0xa8,0x4d,0xfb,0x47,0x2d, + 0xec,0x1f,0xb6,0xb1,0xbb,0x7f,0x84,0xed,0xfd,0x23,0xde,0xd8,0xda,0xc7,0xca,0xc6, + 0x2e,0x2d,0x6f,0xec,0xf2,0xfa,0xf6,0x3e,0xe,0x8e,0x8e,0x5d,0x78,0x1d,0x92,0xc7, + 0xf,0x89,0x70,0xa3,0xd0,0xc6,0x5b,0x4e,0x2b,0x8e,0xd0,0x26,0x86,0x28,0x17,0xcf, + 0x31,0x61,0x36,0xae,0x9c,0x93,0x35,0xce,0xea,0xc7,0x10,0x60,0x8d,0x67,0x8d,0xb0, + 0x8f,0x68,0x33,0x6e,0xd6,0x76,0x41,0x3b,0x36,0xb4,0x12,0x1c,0x49,0x3b,0x22,0xdf, + 0x8f,0xa2,0xe0,0x30,0xdc,0x19,0x2c,0xf2,0x3a,0x48,0x67,0xa5,0x27,0xf3,0x3d,0x16, + 0xab,0xe7,0x38,0x5a,0xca,0xa0,0x29,0xd6,0x0,0x14,0x67,0x41,0x5a,0x9a,0xb0,0x2c, + 0x51,0x69,0xb1,0x96,0x9a,0x7c,0xe3,0x2f,0x3e,0x2b,0xa5,0x22,0xe7,0xf4,0xf8,0xd2, + 0xf3,0xbf,0x34,0x48,0x53,0x89,0x47,0x72,0xd7,0xb2,0x34,0x81,0x53,0x4f,0xc9,0xbd, + 0x9e,0x32,0x8b,0x5f,0x5f,0xfc,0xaf,0x17,0x89,0xca,0xd0,0x43,0x76,0x97,0x6b,0x28, + 0xf3,0xe2,0x5f,0x7c,0x55,0x9,0x59,0xc,0xaa,0x5c,0xec,0x17,0x8,0x5f,0xa1,0x48, + 0xe5,0x7a,0x1b,0xd6,0x3c,0xa8,0xa2,0xb9,0xab,0x60,0x8a,0x97,0x18,0x8,0x20,0xf, + 0xc4,0xc1,0x8b,0x65,0x80,0xa5,0xa,0x82,0x7c,0xd5,0xc1,0x5,0x14,0x86,0x7b,0x91, + 0x57,0x55,0x48,0xf,0x95,0xff,0x9e,0x1e,0xf1,0xe6,0xb9,0x34,0x8f,0x4,0xe7,0x11, + 0x22,0xdf,0x4,0x46,0xe4,0x92,0x8b,0x54,0xa8,0x68,0x7d,0x49,0x26,0x4e,0xde,0x6e, + 0x63,0xee,0x77,0xb9,0x1e,0x6a,0x4f,0x66,0x96,0xa2,0xa8,0x93,0x37,0x6d,0xf,0xcc, + 0xea,0xe4,0x70,0x1d,0x68,0x3a,0xa4,0xf2,0x56,0x3,0x32,0x10,0x81,0x9c,0xf8,0xd0, + 0x62,0x56,0x76,0xa0,0x3e,0xb,0x4e,0x1b,0xa6,0x46,0x7,0x69,0x72,0x6c,0x10,0xd3, + 0x63,0x43,0x34,0x35,0x36,0x84,0xc9,0x31,0x77,0x28,0xe,0xf,0xf4,0x61,0xa8,0xbf, + 0x89,0xfe,0x66,0xd,0x3,0xcd,0x86,0x9b,0xc8,0x9b,0x75,0xf4,0x37,0xeb,0xe8,0x6b, + 0xd6,0xd1,0x57,0xaf,0xa2,0x56,0xab,0x4a,0x31,0x53,0xb4,0x7a,0x3c,0x38,0x6a,0x63, + 0x7d,0x7b,0x1f,0x6b,0x5b,0x7b,0xfc,0x78,0x65,0xb,0xf7,0x9e,0xac,0xf2,0x47,0x5f, + 0x3d,0xe0,0xcf,0x6f,0x3f,0xb1,0xdd,0xae,0xd,0xea,0xa0,0xc4,0xdd,0x74,0xa3,0x92, + 0xd,0x26,0xb1,0x96,0xd9,0x3a,0x6c,0x10,0xd6,0xa7,0x51,0x59,0x76,0x49,0x21,0x9e, + 0xbb,0x6b,0xad,0xb7,0x90,0xf0,0x74,0x2f,0xe6,0xc8,0xcb,0x90,0xf9,0xe1,0xe1,0xd5, + 0xf4,0xd3,0xb8,0xda,0x9b,0xbb,0xd5,0x87,0x71,0xaa,0x28,0x63,0xa4,0xe3,0x1e,0xbb, + 0x98,0xe8,0xa0,0x87,0x8e,0x43,0xa1,0x34,0x66,0x9e,0x9d,0x1c,0xa1,0x6b,0x17,0xe6, + 0xe9,0xfa,0xa5,0x79,0x1a,0x19,0xec,0xc7,0xfe,0xc1,0x11,0x7e,0xf3,0xf5,0x23,0xfe, + 0xfa,0xfe,0x12,0xb6,0x76,0x8e,0x14,0x9d,0xb5,0xfc,0x8a,0x27,0x19,0xf,0x95,0x35, + 0xc4,0x81,0x9b,0x9e,0x7f,0x35,0x94,0xc9,0x9,0x14,0x7,0x48,0xa8,0x5c,0x52,0x32, + 0x83,0x8a,0x7a,0x10,0xcb,0x24,0x1f,0x43,0x2b,0x28,0x5e,0xcc,0x89,0x22,0x9c,0x32, + 0xbf,0xd3,0x67,0xc5,0xd7,0x50,0x16,0x36,0x95,0xf8,0xc2,0x3a,0x38,0x80,0x49,0x13, + 0xde,0x44,0xaa,0x20,0xe9,0xbd,0x5,0x44,0x28,0x51,0xca,0x2d,0x8,0x8a,0x9c,0xc1, + 0xfe,0x26,0xcd,0x4d,0x8e,0x60,0x66,0xc2,0x35,0x91,0x33,0x93,0xc3,0x98,0x1a,0x1b, + 0xa2,0xf1,0x91,0x7e,0xc,0xf6,0x35,0xd0,0xac,0xd7,0xd0,0xd7,0xa8,0xa1,0x51,0xaf, + 0x51,0xb3,0x5e,0x45,0x7f,0xb3,0x8e,0x46,0xcd,0x5d,0x9f,0xd5,0x8a,0x41,0xc5,0x10, + 0xaa,0xd5,0x8a,0x5a,0xbf,0xb3,0xc8,0x98,0x90,0xd7,0x2f,0xe0,0xc2,0xff,0xba,0x5d, + 0x1b,0x8b,0x7d,0xbb,0xdd,0x71,0x93,0x7a,0xa7,0x83,0x93,0xae,0x45,0xbb,0x7d,0x82, + 0xd6,0x71,0x87,0xf,0x5a,0xc7,0x68,0x1d,0x77,0xb0,0x7f,0xd4,0xc2,0xfe,0x51,0x1b, + 0x3b,0x7b,0x47,0x58,0xdf,0xde,0xe3,0xd5,0x8d,0x3d,0x2c,0x6f,0xec,0xf0,0xf2,0xda, + 0x2e,0x56,0xb7,0x77,0x99,0xbb,0x71,0xd1,0xc9,0x5a,0x53,0xc8,0x88,0xa,0x73,0x82, + 0x10,0x97,0x39,0x71,0x66,0xd4,0x9e,0x3b,0xff,0x3e,0x8e,0x32,0x4e,0x76,0xa6,0x7e, + 0x60,0x6b,0xb9,0xb,0xb,0x74,0xad,0xff,0x6e,0xcb,0xb6,0x6b,0xc3,0xbd,0xe4,0x3e, + 0xe7,0xfc,0xe2,0xad,0x92,0xc4,0x45,0xdf,0x38,0xe,0x26,0xf5,0x7a,0x60,0xcc,0x8, + 0xae,0x92,0x70,0x8a,0x5c,0xb9,0xa1,0x17,0xba,0xc5,0x9a,0x85,0x62,0xad,0x11,0x83, + 0x76,0x95,0xa,0xb6,0xa9,0xe5,0x39,0xab,0x4a,0x15,0x6a,0x74,0xb1,0x29,0x17,0xc5, + 0x91,0xf2,0x45,0x57,0xd3,0x9e,0xec,0x5a,0x4a,0xa3,0x65,0xb8,0x60,0x76,0x52,0x90, + 0xfa,0x30,0x9,0x2f,0x71,0xa1,0x5b,0x16,0xc6,0xf8,0xba,0x38,0x66,0x26,0x2d,0x4c, + 0x8a,0xa8,0x57,0xa4,0x71,0xb,0x63,0x0,0xce,0x8a,0x39,0x17,0xb,0xa5,0x2e,0x56, + 0x32,0x66,0xb4,0x18,0x70,0x9f,0x18,0xbb,0xe1,0x71,0x53,0xc2,0x6c,0xf2,0xec,0x70, + 0x92,0x42,0x22,0x8,0x9a,0x99,0x4c,0x8f,0xd0,0xc1,0x2f,0xcc,0x45,0x17,0xb7,0x3c, + 0x5d,0x2d,0x34,0x93,0xb9,0xc2,0x82,0x45,0x95,0x25,0x70,0x66,0xab,0xab,0x13,0xd9, + 0xf4,0xde,0x2d,0x38,0x89,0x41,0xe9,0xd4,0xd5,0x1a,0x94,0xf2,0xde,0x45,0xd8,0xbf, + 0x9a,0xb8,0xbd,0x29,0x68,0xb7,0x61,0x1c,0xb5,0x2d,0xf8,0x58,0x7,0x66,0x2f,0x67, + 0xae,0x70,0xce,0x46,0xc6,0x10,0xf9,0x7d,0xae,0x31,0x30,0xc,0xc9,0xba,0x76,0xa5, + 0xd9,0xf8,0x82,0xe3,0x6c,0x9b,0x49,0x84,0xa0,0x32,0x85,0x85,0x7d,0x32,0x41,0xd1, + 0x10,0x25,0x33,0x83,0x2a,0x86,0x1a,0xd5,0xa,0x6a,0xb5,0x3a,0xb9,0x83,0xce,0xa0, + 0xbf,0x51,0xc7,0xc4,0xe8,0x20,0x2d,0x4c,0x8f,0xe2,0xd4,0xf4,0x28,0x9d,0x9a,0x1e, + 0xc3,0xc2,0xf4,0x8,0x4e,0x4d,0x8f,0xd1,0xdc,0xd4,0x8,0x1a,0xbe,0x58,0xcb,0x43, + 0x2f,0xff,0xef,0x18,0xf3,0x2c,0xe,0x44,0x22,0xc2,0x60,0x7f,0x3,0x83,0xfd,0xd, + 0x9c,0x99,0x1b,0xa7,0xf7,0x5e,0x3f,0x83,0x47,0xcb,0x9b,0x34,0x31,0x32,0x60,0xeb, + 0xb5,0x8a,0xb9,0xf3,0x78,0x9d,0xb7,0x76,0xf,0xd0,0xb5,0x5d,0x78,0x7,0x8c,0xb4, + 0x9c,0xf5,0xe9,0xce,0xee,0x25,0x36,0x88,0x4e,0x73,0xee,0x56,0x70,0x4b,0x77,0x76, + 0x94,0x1f,0x1b,0xf6,0x92,0x61,0xb5,0x2e,0xd,0xfa,0x42,0x35,0x31,0x51,0x3c,0xe6, + 0xcb,0x76,0x68,0x9e,0x3c,0xf4,0xce,0x62,0xf5,0x21,0x34,0xea,0x46,0x85,0xb3,0x24, + 0xa,0x7b,0x70,0xd1,0x9d,0x1c,0x1b,0xa4,0x1f,0xbe,0x79,0xce,0xfc,0xfe,0x7b,0x97, + 0xe9,0x87,0x6f,0x5e,0xa0,0xc9,0xd1,0x1,0x6c,0xee,0x1c,0x62,0x7a,0x62,0x98,0x9b, + 0x8d,0x1a,0x7f,0xf4,0xf5,0x3,0xec,0x1f,0x1c,0xa3,0x56,0xad,0xa0,0x52,0x31,0xa8, + 0x1a,0x83,0x4a,0xc5,0xa0,0x56,0x31,0xa8,0x54,0x2b,0x71,0x4d,0x51,0x9,0x5b,0x17, + 0xb1,0x2e,0xd4,0x32,0xd3,0x70,0x17,0x73,0x30,0xcc,0x5,0x23,0x4c,0x92,0x96,0x6c, + 0xd7,0xa2,0xdb,0xb1,0x7c,0x62,0xbb,0xe8,0x76,0x2c,0x3a,0xd6,0xa2,0xd3,0xe9,0xa, + 0x5e,0x6c,0x50,0x76,0x8b,0xfb,0x23,0xd0,0x11,0x5d,0x63,0xe8,0x73,0xa4,0x3c,0x76, + 0xc0,0xce,0x71,0x8c,0x6d,0xa0,0x7b,0x45,0xcc,0xde,0x81,0xc4,0x36,0xcd,0x7e,0xf1, + 0x34,0x8b,0x29,0x9d,0x9e,0xe7,0x17,0x50,0xab,0x8,0x93,0xe8,0xac,0xb5,0x94,0xd0, + 0x2a,0xb3,0xb,0x1c,0x0,0x2,0x76,0xb9,0x2,0xcd,0x46,0x1d,0x8d,0x7a,0x95,0xfa, + 0x9b,0x35,0x4c,0x8c,0xc,0xd2,0xfc,0xd4,0x30,0xce,0x9e,0x9a,0xc4,0xe9,0xe9,0x31, + 0x3a,0x3d,0x3f,0x81,0xd3,0xb3,0xe3,0x34,0x3f,0x39,0xac,0x42,0xd1,0x7a,0x5d,0xab, + 0x52,0x76,0x2d,0x8b,0x79,0xfe,0x75,0xb2,0xc8,0x1b,0x77,0xbb,0xc5,0x86,0x15,0x3, + 0xfa,0x9a,0x4f,0x3c,0x76,0x7d,0x1f,0x6c,0xef,0x1e,0x62,0x69,0x6d,0x9b,0x1e,0xaf, + 0x6c,0xf1,0xc3,0xe5,0xd,0x7a,0xf8,0x6c,0x83,0x9f,0x3e,0xdf,0xa6,0x95,0x8d,0x1d, + 0x3e,0x3a,0x3e,0x41,0xbb,0xdd,0xa1,0x56,0xfb,0x84,0x8f,0x4f,0x3a,0xe8,0x74,0xba, + 0x91,0x9,0x1,0xc1,0x5b,0x12,0x1e,0x16,0x62,0xe5,0xcb,0x86,0x43,0x60,0x11,0x59, + 0x77,0x19,0x5a,0xb8,0xbc,0x54,0xc3,0xc4,0x1c,0x88,0x53,0x1c,0xd6,0x18,0xfe,0xd, + 0x49,0xac,0x6d,0xb2,0x89,0xd1,0x9e,0xc4,0x5c,0xdc,0x63,0x55,0x49,0x5,0x15,0x56, + 0x8e,0x9f,0x16,0x14,0x1b,0xa5,0x6d,0x6b,0x89,0xe8,0x8d,0x34,0x72,0x4a,0x93,0xd7, + 0xff,0xe2,0x33,0x12,0x32,0x2c,0x2e,0x90,0xbb,0x4a,0x48,0xa1,0xc8,0x4c,0x6,0x4a, + 0xed,0xfe,0xf4,0x54,0x96,0x85,0x91,0x95,0x1a,0xdf,0xa8,0xe1,0x1c,0x3d,0xec,0x62, + 0xa9,0x80,0x82,0xab,0x9d,0x1b,0x4a,0xe0,0x8a,0x5c,0x18,0x96,0xc,0x57,0x38,0x23, + 0x7a,0xe8,0xc7,0x29,0x33,0x6f,0x65,0x2a,0x1a,0x73,0xb6,0x2f,0xce,0xa,0x2e,0xa, + 0xd2,0x3a,0x2e,0xcd,0x34,0x47,0x8e,0x37,0x70,0x6a,0x56,0xa4,0xbb,0x9d,0x36,0x8d, + 0xc9,0x5e,0x6b,0xca,0xe6,0x77,0x9,0x8,0x88,0xdf,0x4f,0xf9,0x5c,0xcf,0xba,0x18, + 0xa3,0x44,0x19,0x59,0xc4,0x3a,0x24,0x71,0x32,0x31,0xda,0x74,0x83,0xc1,0xa5,0x97, + 0xb3,0x9a,0x87,0x94,0xfd,0x58,0x16,0x5f,0x47,0x32,0x6f,0x85,0x28,0x6a,0xcd,0xe3, + 0xcd,0x45,0x64,0xc,0xdc,0x8e,0xdc,0xef,0xc5,0x49,0xfe,0xdd,0x38,0xd3,0x67,0x63, + 0x8c,0x71,0xb6,0xca,0x26,0xb0,0xb0,0x1d,0x1c,0xcf,0x50,0x21,0x2c,0x9c,0x3c,0x35, + 0x83,0x1,0x34,0x45,0xad,0x2d,0xca,0x8,0x6e,0x84,0x91,0xe1,0x3e,0x3a,0x37,0x37, + 0x81,0xb,0x8b,0x53,0x74,0xfe,0xd4,0x24,0x9d,0x9e,0x19,0xc7,0xc2,0xec,0x18,0x46, + 0x87,0xfa,0xa9,0x56,0x35,0xa8,0xd7,0xaa,0xa8,0x55,0x5c,0xf1,0x69,0xd4,0x2a,0xa8, + 0x56,0x2b,0xea,0xa0,0xcb,0xf,0xc5,0xb2,0x3,0xf4,0x45,0xc5,0xff,0xe4,0xa4,0x83, + 0xa3,0x76,0x7,0x8f,0x57,0x36,0xf9,0x2f,0x3f,0xf8,0x9c,0xff,0xee,0xe3,0xef,0xec, + 0xfd,0xa5,0x35,0x66,0xcb,0x2c,0xa6,0x75,0xe,0x2,0x1e,0x8,0x53,0x19,0xcf,0xac, + 0xb6,0xfe,0x4b,0xac,0x65,0x96,0xba,0x5c,0xb0,0xd,0xc,0x6c,0x1b,0x8,0x5b,0xc4, + 0xce,0x7a,0xd5,0x93,0xda,0x4c,0xe0,0xb4,0x9b,0x90,0xac,0xe6,0x8e,0xc1,0x50,0xcc, + 0x95,0x99,0x89,0x60,0x63,0xfb,0xf7,0x30,0x98,0xee,0xf9,0x56,0xfb,0xca,0xb9,0x59, + 0xfa,0xa3,0x1f,0x5c,0xa5,0x3f,0xfc,0xfe,0x55,0xba,0xb8,0x38,0x4d,0x8d,0x5a,0x5, + 0x95,0x4a,0x5,0xdd,0x6e,0x17,0x27,0x5d,0x8b,0x8f,0x6f,0x3d,0xe2,0xff,0xf1,0x2f, + 0x3f,0xe4,0x27,0x6b,0x5b,0x68,0xd4,0xaa,0x18,0x1f,0x1e,0xc0,0xe4,0xe8,0x0,0x26, + 0x46,0xdd,0x44,0x39,0x31,0x3c,0x80,0xc9,0xb1,0x41,0x8c,0xd,0xf6,0x61,0x60,0xa0, + 0x49,0x15,0x32,0xa5,0xa8,0x5d,0x78,0xd,0x2d,0xb3,0x9b,0x16,0x4f,0x3a,0x7c,0xdc, + 0xee,0xe0,0xa8,0x7d,0x82,0xdd,0xfd,0x16,0x36,0x77,0xf,0xb1,0xb9,0xb3,0xcf,0x1b, + 0xdb,0x87,0xd8,0xd8,0xde,0xc7,0xda,0xce,0x3e,0x6f,0xee,0x1c,0x62,0x75,0x73,0x17, + 0x7b,0x7,0x2d,0xce,0x32,0x92,0xf5,0x31,0x17,0xa7,0x73,0xe6,0x3c,0x9f,0x12,0x82, + 0x2,0x1f,0xc9,0x45,0x60,0x4d,0xd0,0x93,0xb9,0x59,0xa9,0xf1,0x16,0x91,0x88,0x94, + 0xb7,0xc2,0xbd,0x52,0xff,0xa4,0x24,0x9f,0x0,0xc2,0xe4,0xe8,0x10,0x5d,0xbf,0x38, + 0x47,0x6f,0x5c,0x3c,0x85,0xd7,0xce,0xce,0xd2,0x99,0xb9,0x31,0x1a,0x1b,0x1a,0x40, + 0xb5,0x6a,0x50,0xab,0xb8,0x6b,0xb3,0x51,0xab,0xa0,0x5e,0xaf,0x15,0xae,0xc9,0xfc, + 0x7a,0xcc,0x3f,0xfe,0xb2,0xcf,0x95,0x35,0xab,0xa5,0x20,0x62,0xf6,0xf3,0xc2,0xdf, + 0xc3,0x35,0x70,0xdc,0xee,0xa0,0xd3,0xb1,0x38,0xe9,0x74,0x71,0x74,0xdc,0xc6,0xee, + 0x41,0x8b,0x1f,0xaf,0x6c,0xe2,0xce,0x93,0x55,0xfe,0xfa,0xfe,0x32,0xbe,0xb9,0xbf, + 0xcc,0xcb,0x6b,0x3b,0xcc,0x2c,0x19,0x51,0xc9,0xbf,0x3d,0x7e,0x20,0x5e,0xf7,0x62, + 0x52,0xb7,0xee,0xae,0x71,0x9,0xe8,0xfe,0xef,0x96,0x2d,0x82,0x29,0x13,0xac,0x65, + 0x66,0x4b,0x5d,0x77,0xf,0xb1,0xd,0xc8,0x97,0x47,0xb4,0xd8,0x6,0xb3,0x60,0x56, + 0xab,0x2a,0x8e,0x76,0x43,0x40,0x6e,0xda,0x4d,0xd1,0x74,0xa7,0x58,0xc4,0x94,0x1, + 0x99,0x9e,0x1a,0x75,0xfe,0x48,0x21,0x0,0x4,0x20,0x42,0xb5,0xb4,0x8b,0x60,0x91, + 0x77,0xad,0x2d,0xbe,0x34,0x6f,0x2a,0x2b,0xca,0x8a,0x8d,0x1b,0x9,0xc,0x89,0x49, + 0x1d,0x18,0xd1,0x9c,0x4d,0xdf,0x6a,0xfa,0xa7,0x92,0x5d,0xb3,0x22,0xb,0x24,0x16, + 0xbc,0xdc,0xf0,0x2a,0x1d,0x34,0xb,0xd9,0x16,0xe7,0x53,0x3c,0xab,0x69,0x91,0x73, + 0xb,0x5b,0x49,0xae,0x51,0xd2,0x30,0x9d,0x2e,0xa6,0xaf,0x48,0x46,0xc6,0x53,0x2c, + 0x36,0xa,0x48,0x50,0x1e,0xb,0x1f,0x2b,0x2e,0x1a,0x31,0x20,0x8b,0xc0,0xd1,0x52, + 0xbc,0xcc,0x30,0x47,0x96,0x4a,0x15,0x8b,0x9a,0xc5,0xa3,0x26,0x44,0x84,0x75,0x57, + 0xc8,0x89,0x89,0x4f,0x2f,0x28,0xc2,0xfa,0xf7,0x93,0x88,0x49,0xa4,0x8c,0x38,0x49, + 0x5,0x7,0x3d,0x45,0x31,0x50,0x1e,0xbb,0x61,0x7,0x1c,0xf8,0xdc,0x86,0x52,0xd8, + 0x12,0x11,0xab,0xb7,0xd3,0x84,0x14,0x74,0x2,0x55,0x1c,0xf5,0xc9,0x24,0xcf,0x70, + 0xb7,0x3d,0x8c,0xfe,0x32,0x8e,0xf0,0x46,0x95,0x60,0x68,0x62,0xa4,0xaf,0x3b,0x60, + 0x4c,0xc2,0x5b,0x4,0xcb,0x9d,0x92,0x91,0x78,0x34,0xc2,0x30,0x44,0x3,0xcd,0x3a, + 0xe6,0xa7,0x46,0x69,0x72,0x74,0x80,0x26,0xc7,0x6,0xb1,0x30,0x3d,0x4a,0xb,0x33, + 0x63,0x98,0x9f,0x1a,0xc5,0xec,0xc4,0x8,0xcd,0x8e,0xf,0x61,0x6c,0x64,0xa0,0xf4, + 0xf0,0x92,0x53,0x8,0x3b,0xa7,0xc9,0x38,0x9,0x11,0xd1,0x4b,0xf,0xb8,0x7c,0xa, + 0x2,0x80,0x5a,0xad,0x8a,0x7a,0xbd,0x86,0xeb,0x17,0x4f,0xd1,0x71,0xbb,0x3,0x0, + 0x66,0x6d,0x6b,0xdf,0xee,0x1e,0xb4,0x40,0xce,0xc2,0x5d,0xec,0x8e,0x3d,0xc0,0xc7, + 0x6,0x6c,0x2c,0xa9,0x4e,0xcf,0x72,0x64,0x71,0x83,0x9d,0xb7,0x3b,0x99,0x80,0x58, + 0x26,0x8b,0xdd,0x48,0xc1,0x97,0x3e,0xee,0x46,0xb9,0xbe,0x91,0x50,0xfa,0x45,0x2e, + 0x42,0x72,0xde,0x73,0x72,0xb5,0x10,0x2a,0x12,0x6e,0xa1,0xbe,0x46,0x83,0xde,0xb9, + 0x72,0x9a,0xfe,0xf9,0xf7,0xaf,0xd2,0xeb,0xe7,0xe7,0x48,0x4e,0x88,0x95,0x4a,0x5, + 0xc6,0x18,0xbc,0x79,0x69,0x81,0xfe,0xf4,0x27,0xd7,0xb1,0xb1,0x7d,0x80,0x5a,0xad, + 0x8a,0xa1,0xfe,0x6,0x46,0x7,0xfb,0x30,0x34,0xd8,0x47,0xc3,0x3,0x4d,0x8c,0xe, + 0xf6,0x61,0x64,0xa8,0xaf,0x80,0x80,0xf4,0x2a,0xe8,0xea,0xae,0x65,0x47,0xd4,0x3a, + 0x3c,0x3e,0xc1,0xce,0xfe,0x11,0x76,0xf,0x5a,0xb4,0xb3,0x7f,0xc8,0x3b,0x7b,0x2d, + 0xec,0x1d,0xb4,0x68,0xf7,0xb0,0x85,0xad,0xdd,0x3,0x6c,0xed,0x1e,0xf2,0xee,0xfe, + 0x31,0xb6,0xf7,0xe,0x78,0x7d,0xe7,0x0,0x6b,0x5b,0x7b,0xb4,0xb5,0x7b,0x98,0xd2, + 0xd5,0x64,0xa2,0xd,0xc4,0xc1,0x7,0xe9,0x19,0x43,0x21,0xd8,0x4b,0x2c,0x98,0xbc, + 0x97,0x59,0x74,0x68,0xcb,0x64,0x5d,0x52,0x2c,0xa9,0x33,0x76,0x65,0x8b,0x99,0xe0, + 0x78,0xff,0xf9,0x99,0x89,0x11,0xba,0xb8,0x30,0x49,0x73,0x53,0x23,0x58,0x98,0x19, + 0xa3,0xb3,0xf3,0x13,0x38,0x7f,0x6a,0x12,0x8b,0x33,0x63,0x34,0x32,0xd8,0xa7,0xae, + 0xa7,0x7c,0xc2,0x76,0x1c,0x3f,0xf3,0xc2,0xeb,0xf1,0x55,0x3f,0x97,0xf5,0xe7,0x78, + 0xd9,0x1f,0xeb,0x7a,0xca,0xf8,0x98,0x8c,0x31,0x68,0x18,0x13,0xdf,0x5b,0xc9,0x53, + 0x39,0x33,0x3b,0x8e,0xb3,0xf3,0x13,0xb8,0xb8,0x38,0x8d,0x1b,0x17,0x4f,0xe1,0xe1, + 0xb3,0xd,0x5a,0x5a,0xdd,0xe1,0x67,0x6b,0x5b,0xfc,0xf4,0xf9,0x36,0x47,0x86,0x8d, + 0x4d,0xa6,0x11,0x4c,0x30,0x64,0x7d,0x70,0x5a,0x54,0x6,0x90,0xd3,0x9e,0x73,0x10, + 0xa,0x7b,0xec,0x8e,0x3,0x85,0xc2,0x10,0xb1,0x75,0x68,0x20,0x33,0x9c,0x76,0x8d, + 0x39,0x31,0xcb,0x21,0x7,0x61,0xb1,0xf2,0x67,0x21,0x93,0xce,0x6,0x20,0xe6,0x2, + 0xb,0xbe,0x40,0x74,0xb,0x83,0x58,0xee,0x65,0x12,0x4d,0xc6,0xf2,0xa9,0xdf,0xfd, + 0x96,0xaa,0x24,0x58,0xa5,0x4d,0xbf,0x40,0xf0,0x49,0xb8,0x89,0x89,0x7d,0xb6,0x2c, + 0x3c,0x24,0xa,0xa2,0x43,0x90,0x73,0x1b,0x7e,0x2a,0x38,0x41,0xe4,0x8d,0x1,0x45, + 0x28,0xbf,0x54,0x9d,0x8d,0x22,0xf0,0x4b,0x25,0xa4,0x2d,0x6d,0x92,0x22,0x9,0xb1, + 0xc1,0x1d,0x8e,0x44,0x94,0x1d,0x49,0xc8,0x59,0x34,0x6,0x94,0x11,0xc4,0x89,0x33, + 0x96,0x3b,0x9,0x53,0x96,0x2c,0x61,0x34,0x16,0xb4,0x52,0x31,0x22,0x92,0x29,0x65, + 0x86,0x5a,0xe4,0x44,0x3c,0x2a,0xb,0xb5,0xe7,0x4c,0xaf,0xce,0xd2,0x13,0xde,0x68, + 0xe8,0x4,0x82,0x9c,0x28,0xc8,0x13,0x45,0xf9,0x1d,0xe9,0x38,0xd6,0xa8,0x22,0x60, + 0xa1,0x9d,0x66,0x95,0xee,0x96,0xc3,0xe7,0xa4,0xfb,0xaf,0x84,0x94,0xb0,0xce,0xd3, + 0x56,0x6f,0x1a,0x9,0x9,0x82,0x38,0xb0,0x94,0x8f,0xb4,0x9,0x61,0x14,0x9,0x76, + 0x8f,0x1a,0x24,0x5f,0xbc,0xc3,0x1e,0xd7,0xc4,0x9d,0xb9,0x31,0xce,0x38,0xdb,0x18, + 0xf7,0xf5,0xc6,0x90,0x89,0x93,0xa2,0x91,0x31,0x93,0xd1,0xba,0x34,0xa0,0x6,0x48, + 0xc0,0x1,0x19,0x7,0x5,0xc,0xf7,0x37,0xe9,0xf2,0x99,0x19,0xfa,0xd1,0x8d,0xf3, + 0xf4,0xf6,0xd5,0xd3,0xb8,0x72,0x7a,0x86,0xc6,0x87,0xfb,0xe3,0xd4,0x1d,0xe,0xc1, + 0x1c,0x42,0xcc,0xe1,0x47,0x9,0xa1,0xff,0x43,0xfe,0xf4,0xfa,0xbe,0x77,0xaf,0x9e, + 0xa6,0x4e,0xd7,0xe2,0xa3,0xaf,0x1e,0xd2,0x37,0xf,0x56,0xd8,0x76,0x53,0xc,0x5b, + 0xd2,0x4e,0x50,0xd0,0xd1,0xc6,0x8b,0x86,0xc9,0xb1,0xb3,0xfd,0x7b,0x6b,0xd8,0x5a, + 0x4b,0x52,0x1a,0xc5,0x1c,0x98,0xe5,0x31,0xc7,0x33,0x32,0xdd,0x23,0x83,0x8b,0x54, + 0x48,0x8b,0x70,0x33,0x13,0xc5,0x5c,0x1b,0x9e,0x84,0xf7,0x77,0xa0,0xaf,0x49,0xaf, + 0x9f,0x9f,0xa3,0xef,0xbf,0x79,0x8e,0xae,0x5f,0x5a,0xa0,0x32,0x58,0x97,0x88,0x30, + 0xd4,0xdf,0xc0,0x9f,0xff,0xe4,0x6,0x95,0xad,0x27,0xf2,0xd7,0xf9,0x55,0x5e,0xbf, + 0x7c,0x52,0xac,0x56,0x2b,0x18,0xae,0x56,0x30,0xd4,0xdf,0x8,0x3f,0x8f,0xf2,0x9f, + 0xd7,0xe9,0x74,0x69,0x75,0x6b,0xf,0xf,0x9e,0x6d,0xf0,0xe7,0xb7,0x9f,0xe2,0xf3, + 0xef,0x9e,0xf2,0xad,0xfb,0xcb,0x58,0xdb,0xdc,0xe3,0x4e,0xb7,0x4b,0xca,0xff,0x7, + 0xc6,0x3f,0x17,0xe1,0xd4,0xe0,0x67,0x35,0x81,0x99,0x7b,0x32,0x97,0x11,0x7e,0x84, + 0x36,0x86,0x7c,0x44,0x93,0x5d,0x88,0xc4,0x73,0xef,0xc8,0x49,0xec,0x29,0x7d,0x62, + 0x49,0x24,0xcd,0x89,0x87,0xfa,0x1b,0xf4,0x3b,0x37,0xce,0xd1,0x7f,0xfd,0xcf,0xde, + 0xa1,0xab,0x67,0x67,0x69,0x7c,0x64,0xa0,0x74,0x9a,0xce,0xe3,0xcf,0xc3,0xeb,0xf8, + 0xf,0xbd,0x3e,0xff,0x31,0xfe,0xc8,0x46,0xe2,0x45,0x8d,0x19,0x33,0x63,0x78,0xb0, + 0x89,0xeb,0xc3,0xa7,0xe8,0xfa,0xc5,0x53,0xe8,0x76,0xbb,0xb4,0xbd,0x77,0x84,0x4f, + 0xbe,0x7d,0xc2,0x3f,0xff,0xf4,0x2e,0xff,0xcd,0x6f,0xbe,0xb5,0xcb,0xeb,0xdb,0x41, + 0x68,0xa5,0xe8,0xcc,0x30,0x6c,0x88,0xc9,0x86,0x60,0x35,0x98,0xe8,0x8,0x47,0xcc, + 0x11,0x85,0x32,0xb0,0xdc,0x85,0x75,0xca,0x2,0x4b,0x44,0xf0,0x46,0x32,0x6e,0x85, + 0x12,0x1a,0xb0,0xe8,0x20,0x48,0x59,0x0,0x5b,0x66,0xd3,0x4a,0x52,0x89,0xa8,0x8c, + 0x8f,0x58,0xa5,0x9b,0x52,0x46,0x4f,0x22,0x85,0x7e,0x27,0xdf,0x94,0x32,0xf9,0xb7, + 0xbb,0xc,0xab,0xca,0xe4,0x8c,0x75,0x90,0x41,0x31,0x5f,0x3b,0x3b,0xc1,0x73,0xb2, + 0x56,0x34,0x95,0xa7,0x6c,0xaa,0x96,0xbb,0xea,0x62,0xdc,0xa8,0xf2,0x9,0xa6,0x4c, + 0xe3,0x8,0x8d,0x3a,0xc9,0xa6,0x35,0xc5,0xf2,0x64,0xd0,0x33,0x17,0xb2,0xba,0xd2, + 0x5e,0x9b,0x85,0xdc,0x55,0x75,0x4a,0x2,0x42,0xd7,0x6,0xed,0x9a,0xad,0x4d,0xba, + 0x1e,0xc9,0xaf,0xa7,0x6c,0xc2,0x8f,0xe,0x81,0x2c,0x76,0xea,0x32,0x32,0x36,0x6a, + 0xed,0x49,0xc7,0x2d,0x97,0xa1,0xd1,0x52,0x53,0xcf,0x5c,0xca,0x7a,0x53,0xe3,0x8f, + 0xaa,0xd1,0x1,0xe2,0xa1,0x10,0xa1,0xad,0x74,0xaf,0xf9,0xd5,0x51,0x48,0xf5,0x21, + 0xca,0xde,0x7,0x46,0xa9,0xbe,0x5a,0x75,0x32,0xa4,0xd3,0xdb,0xb,0xb1,0xb2,0x9c, + 0xbc,0x3e,0x55,0x32,0x5c,0x28,0x1e,0x72,0xe2,0x83,0xb2,0x74,0xa5,0x40,0x85,0x53, + 0x45,0xc5,0x6b,0xcb,0x25,0x7b,0x3d,0xb0,0xda,0x33,0x89,0x9a,0x92,0x5e,0xc5,0xe, + 0xc7,0xc4,0x20,0x8c,0x8a,0x31,0xb8,0x7c,0x76,0x86,0xde,0xba,0xbc,0x40,0xd7,0x2e, + 0xcc,0xd3,0xd9,0xf9,0x9,0x4c,0x8e,0xe,0xd2,0xec,0xf8,0x30,0x46,0x86,0xfa,0x7a, + 0x4e,0x7d,0x11,0xd6,0x15,0x53,0xf8,0x3f,0xf6,0x1f,0xd9,0x3c,0x84,0x7b,0xee,0xd4, + 0xf4,0x28,0xfd,0xf4,0xbd,0x2b,0xd4,0xe9,0x5a,0x73,0xfb,0xc1,0x8a,0x95,0xd3,0xa2, + 0x23,0xe9,0x4a,0xc,0xdf,0x25,0xbd,0xb8,0xd5,0x7a,0x8,0x64,0xb1,0xce,0x87,0xc7, + 0xb2,0xb0,0x4d,0x50,0x81,0x29,0x48,0xab,0x9,0x10,0x93,0x89,0xc5,0x3d,0xac,0x38, + 0xfc,0x5a,0x3e,0xda,0xed,0x92,0x71,0xe1,0x36,0xe4,0x79,0x9,0xcc,0x8c,0xb1,0xa1, + 0x7e,0x7a,0xed,0xdc,0x2c,0x2d,0xcc,0x8c,0xd1,0x99,0xb9,0x71,0xba,0x72,0x66,0x6, + 0xd7,0x2e,0xcc,0x45,0xb2,0xb9,0xb5,0xb6,0xf0,0x7a,0x86,0xfd,0xab,0xfc,0x7b,0xfe, + 0xfc,0x7b,0x41,0xb6,0x65,0x3b,0xdf,0x7c,0x2a,0xed,0xd5,0x7c,0xc9,0xaf,0xad,0xd5, + 0xaa,0x98,0x9f,0x1a,0xc5,0x60,0x5f,0x93,0x66,0x27,0x47,0xf0,0xfd,0x6b,0x67,0xf1, + 0x7c,0x73,0x97,0x9e,0xae,0xed,0xe0,0xe1,0xb3,0x75,0x7e,0xb0,0xb4,0x81,0xbb,0x4f, + 0x56,0x79,0x73,0xf7,0x20,0x86,0x99,0xa5,0x91,0x4d,0x99,0xc1,0x11,0xb3,0x61,0x6f, + 0x91,0x94,0xc,0x69,0x12,0x25,0x5f,0xc8,0xe3,0xe3,0xbc,0xe8,0x3f,0xec,0x9,0xe, + 0x7e,0x8f,0x9b,0x52,0x72,0xd2,0x91,0x3f,0x3e,0x3c,0x40,0x7f,0xf6,0x93,0x37,0xe9, + 0xf7,0xdf,0xbd,0x44,0x6f,0x5c,0x98,0xa7,0xe1,0x81,0x66,0x81,0x8f,0x51,0xb6,0xd2, + 0x79,0xd5,0x9,0xfa,0xff,0xcd,0x3f,0xf9,0xb5,0x91,0x5f,0x13,0xe3,0x23,0x3,0x78, + 0xf7,0xb5,0x45,0x9a,0x9d,0x18,0xc2,0xbb,0xaf,0x2f,0x56,0x3e,0xfc,0xe2,0x3e,0xff, + 0xfc,0xd3,0x3b,0x76,0x65,0x63,0x2f,0x70,0xd5,0x42,0x5b,0x15,0x15,0x0,0x40,0x32, + 0xdf,0xf1,0xae,0xd,0x64,0x6c,0x88,0x48,0x77,0xc5,0x3d,0xda,0xf3,0x12,0x83,0x9d, + 0x5d,0x1c,0x3b,0xf4,0xce,0x8a,0xdc,0x99,0x18,0xb6,0x23,0x56,0xaf,0xfe,0x9b,0xb, + 0x61,0x54,0x32,0x35,0x34,0x67,0xbf,0x6b,0xb2,0x79,0x31,0x34,0x48,0x60,0xca,0x24, + 0x73,0x33,0x52,0xed,0xaa,0x4a,0x29,0x96,0x8a,0x2c,0x45,0x6,0xbb,0xcb,0x3,0x5c, + 0xc6,0x37,0x50,0x8f,0x3c,0x17,0x86,0xb2,0x7e,0x4d,0x93,0x6e,0x71,0xab,0x50,0xaa, + 0xfc,0x92,0x85,0xaa,0xe8,0xef,0xa6,0x8b,0x6a,0xc1,0xcd,0x20,0xf3,0x25,0x97,0x5e, + 0x15,0x79,0x80,0x80,0x78,0x12,0x85,0xdf,0x90,0x11,0xc9,0x50,0xaa,0xfd,0xe6,0x92, + 0xef,0xd7,0x7d,0x58,0x4a,0x9a,0xcb,0x8c,0x1b,0xd4,0xdf,0xa9,0x4c,0xbc,0x5d,0x22, + 0x5d,0x93,0xd3,0x6d,0xde,0xe2,0xf6,0x20,0x42,0x52,0x5e,0xe8,0x95,0xbc,0x87,0xb, + 0x5f,0x4c,0xe5,0xcf,0x97,0x7a,0xa,0xcc,0xa1,0xbb,0xce,0x2,0x89,0x43,0xbf,0xfe, + 0x51,0x7c,0x9b,0x5a,0x73,0xe5,0x0,0x7,0x91,0x54,0x6,0xa4,0xa8,0xc7,0x10,0xa2, + 0x12,0xd,0x61,0x4c,0x28,0xe2,0xb1,0x1,0x30,0x61,0xae,0x2f,0x91,0xa8,0x51,0xd0, + 0xbf,0x41,0xfe,0x2f,0xd,0x3b,0x54,0xaf,0x55,0x31,0x31,0x36,0x44,0xe7,0x66,0xc7, + 0xe9,0xfd,0x37,0xcf,0xd2,0x8f,0xae,0x9f,0xc7,0x9b,0x97,0x4e,0x51,0xad,0x56,0xed, + 0x39,0xe1,0x95,0x1d,0x86,0xc6,0x99,0xb2,0xf5,0x2c,0x38,0x65,0x45,0x45,0x16,0xeb, + 0xb2,0x89,0x45,0xfe,0x2e,0x59,0xfc,0x98,0x19,0x23,0x83,0x7d,0xf8,0xbd,0x77,0x2e, + 0xd1,0xfd,0xe5,0x75,0xbe,0xfd,0x60,0x25,0x4d,0xc,0x1c,0x88,0x40,0x69,0x52,0x21, + 0x9f,0x5a,0xe1,0x1d,0xdf,0x0,0xe7,0x72,0xe5,0x50,0x46,0x23,0xbc,0xa7,0x38,0xd0, + 0xda,0xc,0x45,0x4f,0x2e,0x12,0x9e,0xf7,0x59,0x82,0x9a,0xe,0x64,0xe1,0x94,0x70, + 0x7,0xa2,0x6a,0xc5,0xd0,0xe4,0xf8,0x10,0xbd,0x73,0x79,0x91,0xde,0xbf,0x7e,0x96, + 0xae,0x9e,0x9d,0xc5,0xe9,0xd9,0x31,0x9a,0x9d,0x1c,0x89,0x6b,0x88,0x40,0x9e,0x7a, + 0xd9,0xea,0xe1,0x1f,0xa,0x1,0xf7,0xfa,0x59,0xbd,0xbe,0x27,0x27,0x7a,0x11,0x11, + 0x46,0x86,0xfa,0x30,0x3c,0xd8,0x4,0x2d,0x4c,0x11,0x33,0x63,0x67,0xef,0x8,0x77, + 0x9f,0xae,0xe1,0xcb,0x3b,0x4b,0x98,0x99,0x18,0xc6,0xed,0x47,0xcf,0xb1,0xb3,0x77, + 0x84,0xc3,0xa3,0x63,0x1c,0xb6,0xda,0xe8,0xb2,0x2f,0x23,0x24,0xf1,0x71,0x31,0xc4, + 0x19,0x22,0x6f,0xb2,0xab,0xc2,0xfa,0x84,0x2b,0xb0,0x9a,0xa1,0x58,0x7a,0x1a,0x90, + 0xbc,0xe3,0x5c,0x59,0x9f,0x99,0x18,0xa6,0x3f,0xfe,0xc1,0xeb,0xf4,0xce,0x6b,0xb, + 0x24,0x77,0xe2,0xf9,0x75,0xf6,0x4f,0xbd,0x78,0xbf,0x6c,0x7a,0xef,0x75,0x2f,0x4d, + 0x8c,0xe,0x62,0x62,0x74,0x90,0xae,0x5f,0x3c,0x85,0xd9,0xf1,0x11,0x0,0x64,0x3e, + 0xfa,0xea,0x81,0x7d,0xbc,0xbc,0x85,0xd4,0xd3,0x46,0xf5,0x82,0xd7,0xf5,0x71,0x52, + 0xc2,0x71,0xf2,0xb8,0xe0,0x88,0x34,0x31,0x59,0x97,0x90,0xeb,0x48,0x8e,0xae,0xd, + 0x20,0x16,0x59,0x79,0x41,0xa,0x93,0xec,0x86,0x7a,0x7b,0xe1,0xb3,0x58,0xb,0x87, + 0xe2,0x9f,0x85,0xdb,0x65,0xe7,0xbc,0x5e,0x75,0x4b,0x72,0xae,0x48,0xb6,0x8f,0x3f, + 0xaf,0xa,0xd2,0x7b,0x51,0x69,0xe6,0x5b,0x9c,0xac,0x38,0x8b,0xf0,0x2c,0x67,0xc4, + 0xe7,0x55,0x97,0x4a,0x76,0xcd,0x5a,0xf6,0x96,0x39,0x40,0x11,0x7a,0x30,0xe8,0x4b, + 0x3a,0x87,0xc2,0xa4,0x99,0x95,0x20,0x92,0x8e,0x57,0xe5,0x8c,0xc2,0x82,0xfc,0x5b, + 0x26,0x84,0x66,0xfb,0xe6,0xa2,0xfc,0x8b,0x64,0xb6,0x4b,0x91,0x25,0x98,0x55,0x63, + 0xf5,0xfd,0x9e,0xba,0xcd,0xf2,0xb5,0x2d,0x68,0xcb,0xb2,0x6,0x4a,0x49,0xea,0x4a, + 0x2a,0x79,0xc1,0xc8,0x5d,0x59,0xd3,0x15,0x82,0x72,0x84,0x71,0x6c,0xd9,0xb7,0xe7, + 0xda,0x1e,0x91,0x98,0x20,0x47,0xb7,0x24,0xea,0x61,0x49,0xb6,0x63,0x4e,0x4c,0x7f, + 0x8a,0xa4,0x4b,0xed,0x8c,0x20,0x8a,0x6a,0x5a,0x69,0x78,0x56,0x7b,0xfa,0xa5,0x29, + 0xdf,0x3c,0xf1,0xaa,0x7c,0x31,0x21,0x43,0x9,0x2e,0x4f,0xfb,0xdb,0x98,0x73,0xe, + 0xe3,0x95,0xc7,0xb1,0x98,0x53,0x32,0x1d,0x10,0x11,0x9e,0xc0,0x7b,0xd7,0xce,0x9a, + 0xdf,0x7f,0xf7,0x22,0xfd,0xf8,0xed,0x4b,0x34,0x33,0x36,0x84,0x46,0xa3,0x86,0x7a, + 0xbd,0x56,0x7a,0x28,0xe6,0x13,0xc3,0xab,0x4c,0xd6,0x65,0x44,0xb7,0x7c,0xe2,0xfe, + 0x87,0x40,0xf1,0xc3,0x3,0x4d,0x5c,0xbb,0x38,0x47,0x67,0x67,0x27,0x82,0x1d,0x68, + 0x4c,0xf1,0x4a,0x86,0x2d,0x72,0x48,0x9,0xe1,0xaa,0x21,0x46,0xda,0x15,0xfe,0x98, + 0xb1,0xa4,0xef,0x43,0xe5,0x7a,0x1f,0xa1,0xf5,0x50,0xdc,0xc3,0x36,0x38,0xc2,0x29, + 0x7e,0x32,0x17,0x99,0xf2,0xe7,0x17,0xa7,0xe8,0x7f,0xf8,0xb3,0x1f,0x9a,0xb7,0xae, + 0x2c,0xd2,0xcc,0xd8,0x10,0xea,0x5e,0xb7,0xdc,0x4b,0xf6,0xf4,0x4f,0xe1,0x4f,0xaf, + 0x89,0x5e,0xbe,0x77,0x83,0xfd,0x75,0x5c,0x3d,0x37,0x47,0x17,0x16,0xa6,0xf0,0x47, + 0x3f,0x7c,0x9d,0xd6,0xb7,0x76,0xf9,0xe6,0xdd,0x65,0xfc,0xe6,0xeb,0x87,0xfc,0xd1, + 0xcd,0x7,0x58,0xdf,0x3e,0x10,0x41,0x62,0xd4,0x3,0x3e,0x90,0x6a,0x39,0x52,0x69, + 0xd0,0xf9,0x7e,0x8c,0x62,0x34,0x48,0x1c,0x74,0x22,0xb7,0xb7,0x42,0x86,0x66,0xc7, + 0x87,0xb1,0x38,0x37,0x46,0x52,0xfe,0x58,0xc6,0x40,0xff,0xff,0xd3,0x9f,0x5e,0xab, + 0x9a,0x77,0xaf,0x2e,0xd2,0xdc,0xd4,0x8,0x8d,0xc,0x36,0xf1,0x1f,0x7f,0xf1,0x95, + 0x5d,0xd9,0xd8,0xf3,0x4d,0xb6,0x98,0x89,0x9d,0xd5,0x5b,0x2c,0x80,0xde,0x18,0x8e, + 0xdc,0xe2,0xdd,0x5d,0xce,0x6c,0xc,0x99,0x2e,0x13,0x1b,0xeb,0x8e,0x19,0xeb,0x97, + 0x92,0x1e,0xcb,0xa2,0x2,0x35,0x3d,0x99,0x6c,0x94,0xbd,0xda,0xa4,0xe6,0x3c,0x52, + 0x21,0x6a,0x65,0x59,0x8d,0x54,0x98,0xe6,0xa,0x1f,0x85,0xc,0xff,0xaa,0x96,0x4d, + 0x5f,0xca,0x58,0x94,0x34,0xac,0xac,0xca,0x70,0xc0,0xf3,0x45,0x61,0x89,0xc5,0xa1, + 0xc4,0x1,0xa7,0x17,0xd,0x5f,0x3d,0x9,0x2e,0xde,0x40,0xde,0xe8,0x3a,0xf3,0x13, + 0x2c,0x4e,0x8f,0x5c,0x5e,0x6e,0x4b,0xd8,0x84,0x28,0x84,0x89,0x14,0xdd,0xf1,0x0, + 0xe5,0xf3,0x23,0xe5,0x5f,0x32,0x18,0x9d,0xca,0x33,0xe1,0x14,0xe6,0x2f,0x8a,0x2a, + 0x4b,0x16,0x23,0x8b,0xc4,0xb5,0x42,0xd3,0xa4,0x77,0xd6,0x2a,0x6e,0x50,0x53,0xcf, + 0x12,0xd8,0x21,0xe4,0x6b,0xca,0x71,0x8f,0xf5,0xe3,0x51,0x31,0xa6,0x2a,0xdf,0x9d, + 0xf3,0x29,0x3b,0xd9,0x20,0x49,0xc2,0x9d,0xb,0x2d,0x12,0x1,0x3d,0x4,0x16,0x4, + 0xe,0xa9,0x26,0x0,0xb3,0x8f,0x3a,0x36,0xde,0x1b,0x43,0x4e,0x20,0xfe,0x32,0x34, + 0x32,0x9a,0xd4,0x97,0x68,0x3f,0xb0,0xb3,0x9,0x71,0x90,0xbe,0x40,0x57,0x9c,0x4, + 0x2d,0x24,0x77,0x51,0x30,0x36,0x91,0x86,0x27,0x21,0xed,0xcb,0xcb,0xd7,0x18,0xc9, + 0x5d,0xcb,0x6b,0x79,0x63,0x1,0xaa,0x56,0xc,0x9d,0x9e,0x1b,0xa7,0x37,0x2f,0x2d, + 0xd0,0xf,0xae,0x9f,0xa3,0x77,0xaf,0x2e,0xd2,0xc5,0xc5,0xe9,0x9e,0xd3,0x78,0x3e, + 0x31,0xc8,0x49,0x39,0xc0,0xc1,0x72,0x92,0x96,0x7,0x6a,0xcb,0x11,0xd8,0x84,0xdb, + 0xa0,0x27,0x80,0x11,0xd0,0x68,0xd4,0xb,0x53,0x54,0xce,0x6e,0xcf,0xa7,0x77,0x39, + 0xdd,0xf6,0x35,0xea,0x98,0x9f,0x1a,0xa1,0xc5,0xe9,0x51,0x3c,0x5b,0xdb,0x45,0xc7, + 0x76,0x21,0x75,0x5b,0xc9,0x26,0x3a,0xde,0xb4,0x1c,0x5e,0x7c,0x8e,0x61,0x2c,0x7e, + 0xb9,0x1e,0xbd,0x96,0x4d,0x2c,0x20,0x49,0xbf,0x1f,0xa2,0xea,0x82,0x9d,0xab,0xd8, + 0x97,0x13,0x15,0x8c,0x9f,0x2f,0x9f,0x99,0x32,0x7f,0xf8,0xbd,0xd7,0xe8,0x47,0x6f, + 0x5d,0xa0,0x53,0x53,0xa3,0xa5,0xc5,0xfb,0x9f,0x62,0xb1,0x29,0x43,0xb,0xf2,0xc6, + 0xae,0x52,0xa9,0xa0,0xbf,0x52,0xc1,0x40,0x5f,0x1d,0x63,0xc3,0xfd,0x38,0x35,0x35, + 0x42,0x63,0xc3,0x83,0x98,0x9d,0x18,0xc1,0x85,0x85,0x49,0xfa,0xea,0xfe,0xa,0xdf, + 0x79,0xf4,0x9c,0x9f,0xae,0x6e,0xfb,0x24,0xd5,0x80,0x6d,0xb8,0x17,0xdb,0x5a,0x66, + 0x32,0x86,0x54,0x5e,0x84,0x2,0x14,0x63,0xf3,0x1e,0x0,0xe2,0x28,0x91,0x8b,0x64, + 0x79,0xdf,0x9,0x8f,0xc,0x36,0x31,0x35,0x31,0x44,0x3,0xfe,0x3a,0xea,0x85,0x7a, + 0xfc,0x63,0x40,0xdf,0xf9,0xeb,0xf3,0x2a,0xcc,0xf8,0x5e,0x7c,0x86,0x17,0x29,0x3b, + 0xf2,0xd5,0x4b,0x2f,0xb4,0xaa,0xec,0x31,0x54,0xab,0x15,0x9c,0x9e,0x1d,0xc3,0x1f, + 0x7d,0xff,0x2a,0x75,0xba,0xd6,0xfc,0xfb,0x9f,0x7d,0x69,0x37,0xb6,0xf,0xa2,0x9f, + 0x1,0xc5,0x9b,0xd3,0x10,0x60,0x93,0x5f,0x70,0xb0,0x35,0x76,0x59,0xaa,0xa5,0x83, + 0x9f,0x57,0xdd,0xb0,0x60,0x69,0xfb,0x8f,0xb3,0xca,0x40,0x40,0x4f,0x8a,0x71,0xf, + 0x74,0x5b,0xbd,0xe7,0xd9,0x17,0x15,0x7c,0x49,0x32,0x28,0x36,0x40,0xee,0x19,0x8f, + 0x5c,0x0,0xc6,0xc1,0x99,0x27,0xc1,0xd6,0xc1,0x3b,0x9d,0xa3,0xd3,0x1a,0x17,0xf6, + 0xed,0xac,0x26,0x54,0x2a,0xd5,0xa4,0xa9,0x98,0x91,0x62,0xd2,0x88,0xfa,0x56,0x3d, + 0x65,0xe6,0x26,0x64,0xd9,0xa1,0x10,0x2d,0x57,0xc5,0xc4,0x98,0xf1,0xb0,0xb8,0x4, + 0xee,0x66,0x31,0xc0,0xc7,0x9e,0x2b,0x58,0xc5,0xca,0x64,0xb5,0x40,0x76,0x61,0x91, + 0xdb,0x1,0xfd,0x78,0xd2,0x7a,0x81,0xa3,0x26,0x32,0x4b,0x7c,0x89,0x72,0x67,0xce, + 0x1d,0xd4,0x44,0x2e,0x61,0xa1,0x31,0x50,0xbf,0x47,0x5a,0x72,0x50,0x21,0xdd,0x8d, + 0x54,0x52,0x4f,0x26,0x37,0x2c,0xeb,0x2,0x33,0xc6,0x3f,0x17,0xb0,0x10,0x2a,0x80, + 0xe8,0x5,0xbe,0x83,0x8f,0x32,0x8,0x33,0x9d,0x82,0xfa,0xb3,0x55,0x7b,0x66,0xef, + 0x2a,0xa2,0x48,0xd,0x29,0xa5,0xbd,0x89,0xf1,0xa8,0x90,0xa9,0x68,0x61,0x3a,0x17, + 0xa4,0xb8,0xa8,0x7f,0xe,0x3c,0xf8,0x64,0x85,0x99,0x5c,0x66,0x38,0x2c,0x37,0xfd, + 0x3,0xa8,0x55,0x2b,0x34,0x3f,0x3d,0x4a,0x7f,0xfe,0x7,0x37,0xcc,0x9f,0xff,0xde, + 0xd,0x9a,0x9d,0x18,0x42,0xc3,0x4f,0xe4,0xf2,0xb0,0x78,0x15,0x88,0xb7,0x97,0x2c, + 0xad,0xd3,0xe9,0xe2,0xa0,0xd5,0xc6,0xce,0x7e,0xb,0x7b,0x7,0x47,0xc9,0x12,0x53, + 0x5c,0xd6,0xf5,0x5a,0x15,0xa3,0x83,0xfd,0x18,0x1b,0x6a,0xc6,0xc2,0x9e,0x6b,0xd2, + 0x7b,0xc1,0xc6,0xf2,0x63,0x73,0x93,0x23,0xb8,0x76,0xf1,0x14,0xed,0x1d,0x1e,0x63, + 0x7b,0xaf,0x5,0x38,0x16,0xf,0x27,0xb2,0x2a,0xb9,0x30,0xa9,0x60,0x5,0xda,0xf5, + 0x3e,0xa1,0x5e,0x9a,0xe6,0xfc,0x45,0xc3,0x1d,0x24,0xf6,0x7c,0xa9,0x86,0x7b,0xb7, + 0x37,0x93,0x92,0xb7,0x99,0x24,0xa6,0x9c,0xec,0x61,0xd,0x51,0xb3,0x5e,0xa5,0x7f, + 0xf1,0x3b,0xaf,0xd3,0xbf,0xfa,0xd1,0x75,0x9a,0x19,0x1b,0xea,0x9,0x77,0xff,0x7f, + 0x65,0x72,0xcc,0x1f,0x6b,0x59,0x53,0x72,0x66,0x6e,0x1c,0x67,0xe6,0xc6,0xe9,0xa7, + 0xdf,0xbb,0x84,0x4f,0x6e,0x3d,0xc1,0x7f,0xfc,0xd5,0xd7,0xf4,0xd7,0x1f,0x7d,0xcb, + 0xcf,0xd6,0x76,0x38,0x71,0x4a,0xdc,0xc9,0x1a,0x39,0x89,0x24,0xe9,0xa9,0x1e,0x4f, + 0x12,0x33,0x83,0xb2,0xb4,0x4b,0x14,0x2f,0x19,0x9a,0x80,0xe1,0xc1,0x3e,0x1a,0xee, + 0x6f,0x26,0xb2,0xef,0xff,0x43,0xaf,0x69,0xaf,0x2,0x5c,0xa6,0x47,0xef,0x55,0xd4, + 0xf3,0x62,0xdd,0xab,0x90,0xff,0x97,0x20,0x37,0x65,0xd,0x98,0xb5,0x16,0xef,0x5d, + 0x3b,0x43,0x8d,0x46,0x15,0x5f,0xde,0x5d,0xa2,0xcd,0x9d,0x43,0xff,0x16,0xd8,0x94, + 0x7c,0x4a,0x0,0xd9,0x90,0x56,0x28,0xea,0x45,0x58,0x2d,0xb1,0x5c,0x3c,0x3b,0x1e, + 0x23,0xa4,0x7f,0x0,0x31,0xa1,0x9b,0xd1,0x7e,0x39,0xd7,0x58,0xcb,0xe2,0x8,0x15, + 0x37,0x5d,0x88,0xd9,0xd6,0xa8,0x6f,0x69,0xad,0x8f,0x68,0x8e,0x20,0x28,0x87,0xe1, + 0xaa,0x9a,0x4f,0x6e,0x32,0x51,0x4b,0xb1,0xa8,0x73,0x12,0x54,0x66,0x82,0xc2,0xf9, + 0xc7,0x2,0xf6,0x4f,0xa4,0x62,0xe3,0xe4,0x6e,0x81,0xe5,0x8e,0x5c,0xa0,0xc8,0x5c, + 0x98,0xe0,0x49,0x33,0xfc,0x4a,0x92,0xca,0x74,0x21,0xcc,0xb3,0xc3,0x20,0xa3,0x26, + 0xa,0xc4,0xf1,0x3c,0xea,0x33,0x3e,0x46,0xb9,0xbb,0xca,0xb,0x36,0x32,0x0,0x81, + 0x55,0x11,0x26,0x69,0xce,0x4e,0x62,0xea,0x56,0x28,0x3e,0x51,0x66,0xb9,0x4e,0x5, + 0x1a,0x41,0x41,0xef,0x1f,0x59,0x4b,0xe9,0xb,0xa5,0xbc,0x90,0x64,0x58,0x8d,0x5a, + 0x71,0x17,0xe5,0x6f,0x62,0x82,0xe7,0x32,0xa7,0x3e,0x52,0x1d,0x54,0xb6,0x60,0x31, + 0x44,0xf2,0x1,0x8,0xfd,0x83,0x92,0x3,0x90,0x82,0xcd,0x49,0x11,0xfb,0x48,0x38, + 0x41,0x4,0x99,0x61,0x40,0x6e,0x39,0x66,0x9b,0x23,0x45,0x73,0x1a,0x91,0xf0,0x15, + 0x5d,0x4a,0x42,0x64,0xa7,0x9,0xc9,0xce,0x11,0x6e,0x67,0xf,0xbd,0x13,0xfb,0x49, + 0xdf,0x97,0x35,0x0,0x18,0xe8,0x6b,0xd0,0x3b,0xaf,0x9f,0x36,0xff,0xd5,0x8f,0xaf, + 0xd3,0xbb,0x57,0x4f,0xd3,0xc2,0xf4,0x88,0x92,0x93,0xf5,0x2a,0xa4,0x12,0x6a,0x2f, + 0x3b,0x68,0xb6,0x76,0xf,0xf1,0x6c,0x7d,0x7,0x4b,0xab,0xdb,0x58,0x5a,0xdb,0xc6, + 0xca,0xfa,0x2e,0x56,0xb7,0xf6,0x70,0x70,0xd4,0x46,0xb7,0x6b,0x95,0xc8,0x30,0xbc, + 0x42,0x86,0x8,0xf5,0x7a,0x5,0x83,0x7d,0xd,0x8c,0xc,0xf4,0x61,0x7c,0x74,0x0, + 0x93,0x23,0x3,0x98,0x9b,0x1c,0xc6,0xa9,0xa9,0x31,0xcc,0x4f,0xe,0xa1,0x5e,0xaf, + 0x95,0x4e,0xeb,0x72,0x7a,0x99,0x18,0x19,0xc0,0x85,0x53,0x53,0x74,0xf3,0xce,0x12, + 0x6f,0xef,0x1f,0x5,0x34,0x29,0xb5,0x9d,0x1c,0x51,0x72,0x96,0x83,0x1f,0x8c,0xb8, + 0x10,0xa5,0x43,0x70,0x30,0x9b,0xc9,0xe2,0x79,0x23,0xb1,0x30,0xb9,0x1c,0x93,0x44, + 0xc3,0xc8,0x3,0x74,0x8b,0xb3,0xe3,0x74,0xfd,0xe2,0x29,0xba,0x72,0x76,0x86,0xf2, + 0xd7,0xef,0x55,0xb,0x8e,0x44,0x40,0x5e,0x75,0xef,0xfd,0x8f,0x9,0xe1,0x97,0xa1, + 0x24,0xb2,0x78,0xe4,0x13,0x6b,0x78,0xc,0x95,0x4a,0x5,0xd7,0x2e,0xce,0x53,0xa3, + 0x51,0xc5,0xdc,0xe4,0x30,0x7e,0xf6,0xe9,0x5d,0xfc,0xea,0xcb,0x87,0x21,0x59,0x35, + 0xb9,0x5c,0xe4,0x41,0x3d,0x19,0xcf,0x86,0x72,0xaf,0xab,0xc0,0x63,0xcc,0x66,0xbb, + 0x4e,0xd7,0xa2,0x1b,0xb2,0x47,0x4a,0xae,0x8d,0x7f,0xcc,0x82,0xce,0xcc,0xd8,0x3b, + 0x3c,0xc6,0xf2,0xfa,0xe,0x9e,0xad,0xef,0x60,0x7d,0xeb,0x0,0xfb,0x87,0x2d,0xec, + 0x1d,0x1d,0x63,0xef,0xe0,0x18,0x7,0x47,0xc7,0x68,0x77,0xba,0xe5,0x9e,0x20,0x2, + 0x9d,0xaa,0x18,0x42,0xb3,0x5e,0xc3,0xf8,0xc8,0x0,0x26,0x86,0xfb,0x31,0x3e,0x32, + 0x80,0xe9,0xb1,0x21,0x4c,0x8d,0xd,0x62,0x66,0x7c,0x8,0xcd,0x46,0xad,0x74,0xdd, + 0xf1,0x22,0x46,0xbe,0xfc,0x7c,0x40,0xb1,0xe6,0x26,0x47,0xe9,0x77,0xdf,0xba,0x40, + 0xad,0xe3,0xe,0xdd,0xba,0xbf,0xcc,0x9a,0xa8,0x10,0x52,0x1d,0xe1,0xd8,0xeb,0xd1, + 0xb1,0x2c,0xf9,0xd0,0x19,0x43,0xc4,0xd6,0xc1,0x85,0xec,0x5a,0x72,0x8f,0xd6,0xfb, + 0xb7,0xc1,0x10,0x73,0x84,0xda,0xbe,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xc1, + 0xca,0xcd,0xa9,0x70,0xa3,0xe5,0x68,0xa2,0x46,0xe9,0x27,0x4b,0x76,0x3b,0xa9,0x7a, + 0x23,0x13,0x43,0x25,0xf3,0x3a,0x7c,0x4d,0x9e,0x28,0x2a,0xb8,0xcf,0x4e,0x87,0x9e, + 0xc7,0x14,0xca,0x74,0x34,0xc9,0x6e,0x96,0xa8,0x3b,0x41,0xaf,0x70,0xa3,0x69,0xbc, + 0xd2,0x86,0xa7,0xe9,0x94,0x62,0x62,0x99,0x48,0x5d,0xb,0xd9,0x73,0x48,0x29,0x6a, + 0xfa,0x35,0xa6,0x12,0xb6,0x5f,0x2a,0x4b,0xca,0x50,0xe6,0x25,0x0,0x7,0x4b,0xb3, + 0x66,0xc1,0x46,0x7,0x17,0x57,0xd4,0xa4,0x4d,0xe5,0xa5,0x99,0x4,0x18,0x5a,0x67, + 0x9e,0x60,0x67,0x61,0x1a,0xaa,0x12,0xcb,0x42,0x20,0x4c,0x7a,0x1e,0x24,0x50,0x8c, + 0x90,0x96,0x93,0x6f,0x13,0x58,0x6,0xcc,0xc4,0x86,0x20,0x11,0xc,0xe5,0xf3,0x11, + 0x49,0x93,0xa2,0xf5,0xe1,0x12,0x8a,0x82,0xf6,0xfe,0x65,0x29,0x89,0xf5,0x56,0x5e, + 0xb9,0xbf,0x73,0xfc,0xa1,0xa1,0xd0,0x1,0xc8,0xfc,0x97,0x54,0x7e,0x3c,0x9,0xb6, + 0x9f,0x1b,0x3f,0x90,0x91,0xe,0x7d,0xda,0x7a,0xb4,0xc0,0x50,0x27,0x97,0xb7,0x7, + 0x95,0x59,0xe5,0x94,0x9a,0x23,0x52,0xc9,0x68,0xae,0xa6,0x9b,0x24,0x99,0x22,0x6, + 0xa1,0xe2,0xf7,0xe2,0x1c,0x8a,0xbf,0x8,0x71,0x49,0xb2,0x2a,0x8c,0xe,0xf5,0xd1, + 0x8d,0xcb,0xb,0xe6,0x8f,0x7f,0x70,0x95,0xfe,0xec,0xc7,0xd7,0xa9,0x5e,0xaf,0xbe, + 0xd2,0xa1,0x2d,0xf,0x89,0xf0,0xf1,0xa3,0xe3,0xe,0x8e,0xdb,0x27,0x68,0x9f,0x74, + 0xb1,0xbe,0xbd,0x87,0x7,0xcf,0x36,0x71,0xff,0xd9,0x6,0xee,0x3f,0x59,0xc3,0x9d, + 0xa7,0xeb,0x78,0xf2,0x7c,0x13,0x7,0xad,0x76,0x91,0x30,0xda,0x63,0xeb,0x54,0xaf, + 0x56,0x30,0x3f,0x39,0x8a,0xf9,0xa9,0x11,0x9c,0x99,0x1b,0xc7,0x85,0x85,0x49,0x5c, + 0x39,0x33,0x8d,0xf3,0xa7,0x26,0x31,0x36,0xdc,0xaf,0x34,0xb9,0x39,0xac,0x3f,0x34, + 0xd8,0xa4,0xd9,0xa9,0x61,0x34,0x1b,0xf5,0xac,0x21,0xb,0xa8,0x89,0x4d,0xf2,0x86, + 0x20,0x77,0xb0,0x72,0x9b,0x27,0xee,0x66,0x49,0xc8,0x91,0x64,0x38,0x9f,0x21,0x9e, + 0x3c,0xe4,0x62,0x66,0x4e,0xe2,0x27,0x10,0x68,0x7c,0x64,0x90,0x2e,0x2d,0x4e,0xe1, + 0xf4,0xcc,0xb8,0x2a,0x74,0xaf,0x5a,0x60,0xe4,0x6b,0x9e,0x93,0x1,0x4f,0x4e,0x3a, + 0x38,0xe9,0x32,0xba,0xd6,0x99,0x8d,0x9c,0x9c,0x74,0x9d,0xab,0x5b,0xd7,0xc2,0x76, + 0xbb,0xbd,0xb0,0xcc,0x97,0xff,0x4e,0x76,0xbd,0x4d,0xb5,0xe2,0xcc,0x56,0xfa,0x1a, + 0x75,0x34,0xea,0x15,0x34,0x3c,0xc1,0xac,0x6c,0x8d,0x52,0x36,0x5d,0x86,0x7f,0xf, + 0xf4,0xd5,0x71,0xe3,0xf2,0x2,0x26,0xc7,0x6,0x69,0xa8,0xbf,0x89,0x8d,0x9d,0x43, + 0xbe,0xfb,0x64,0xd,0xd6,0xed,0x68,0xa1,0xbd,0x14,0x5,0x9a,0x15,0xc9,0x4b,0x86, + 0xa,0xe7,0x1a,0x65,0xb4,0x1f,0xff,0x82,0xef,0x1d,0x1d,0x63,0x73,0xe7,0x10,0xbb, + 0x7,0x2d,0xc,0xf,0x34,0x5f,0xd8,0x98,0x96,0x41,0xdd,0x2f,0x93,0xad,0xc9,0x46, + 0x8c,0x88,0xb0,0xb9,0x73,0x0,0x27,0xe1,0x5b,0xc2,0xa3,0x95,0xd,0xec,0xec,0xb5, + 0xb0,0xb9,0x77,0x88,0xed,0xdd,0x43,0x1c,0x77,0xba,0xb9,0xeb,0x73,0x4f,0x10,0x9a, + 0x0,0x4c,0x8f,0xf,0x61,0x6e,0x62,0x18,0xb3,0x93,0xc3,0x38,0x35,0x35,0x82,0xc5, + 0x99,0x31,0x2c,0xce,0x8e,0x61,0x7a,0x74,0x10,0x43,0x3,0xcd,0x14,0x60,0x24,0x72, + 0xe,0x7a,0xc1,0xff,0xf9,0x7b,0x4,0x0,0x7d,0x8d,0x1a,0x7e,0x78,0xfd,0x3c,0x2d, + 0xaf,0xed,0xd2,0xad,0xfb,0xcb,0xaa,0x3b,0x71,0x39,0xf5,0x21,0x1d,0x3a,0x26,0x7c, + 0x3a,0x44,0xcf,0xb1,0xda,0x93,0x54,0x19,0xd2,0x8,0x94,0xa2,0x97,0x50,0xaf,0x85, + 0x79,0x48,0xe7,0x21,0xc5,0x5c,0xd7,0x12,0xee,0x54,0xf7,0x58,0x91,0xaa,0x35,0xc3, + 0x22,0x8b,0xab,0xce,0xa,0xbe,0x44,0x61,0xab,0xc5,0x9d,0x34,0x27,0x4f,0x4,0x15, + 0xb6,0xce,0x2a,0x7b,0x9b,0x38,0xe5,0x81,0x23,0x42,0xd1,0x92,0x1f,0x90,0x8,0x69, + 0x1a,0xca,0xcd,0xb5,0xd6,0x5c,0x20,0x7,0xa4,0x89,0x94,0x35,0xc3,0x5d,0xc6,0x7d, + 0x72,0x19,0x80,0xc0,0x29,0x61,0x29,0x90,0x75,0x43,0x21,0xec,0x91,0x70,0xc6,0x9c, + 0x40,0x30,0x48,0xe4,0x1b,0x5a,0xe,0x97,0x80,0x9,0x93,0xd8,0x5b,0x61,0xf9,0x9b, + 0xf1,0xc5,0x5d,0x9c,0xb1,0x89,0xa2,0xc2,0x20,0xdb,0xe5,0x8c,0x0,0x28,0x15,0xfc, + 0x99,0xf9,0x8a,0x92,0xe3,0x73,0x82,0xe9,0xb,0x72,0xc0,0x2,0x23,0x81,0x49,0x87, + 0xab,0x99,0x12,0x66,0xaf,0x4c,0xb1,0xb,0xb8,0x93,0x2c,0xf6,0x92,0x79,0x5f,0xb4, + 0xa8,0xd7,0xa4,0xc,0x5,0xaf,0x43,0x34,0x4d,0x48,0x5c,0xe8,0x2,0xe7,0x9d,0xb2, + 0x28,0xbc,0xc4,0x34,0x8f,0xc5,0x43,0xc8,0xd4,0x52,0x4e,0x39,0x52,0x34,0x6a,0xa4, + 0xd4,0x89,0x53,0x6,0x51,0xa0,0x26,0x3d,0xc7,0x85,0x46,0x9a,0x31,0x3b,0x31,0x4c, + 0xdf,0x7f,0xe3,0x9c,0xf9,0x37,0xff,0xfc,0x6d,0xba,0x71,0x79,0x91,0x1a,0x8d,0xda, + 0x2b,0x11,0xd3,0xca,0x20,0xf8,0xdd,0x83,0x16,0xbe,0x7b,0xb4,0x8a,0x2f,0xee,0x2c, + 0xe1,0xf3,0x3b,0x4f,0xf1,0xf0,0xd9,0x6,0xb6,0xf7,0x8e,0xd0,0x3a,0xee,0xe0,0xa4, + 0xd3,0xc1,0xf1,0x49,0x17,0x27,0x9d,0x4e,0x46,0x6a,0x11,0x21,0x1f,0x25,0x47,0x5e, + 0xfb,0xa4,0x8b,0xa7,0x6b,0xdb,0x58,0xdd,0xda,0xc5,0xcd,0x7b,0x4b,0x68,0xd4,0x6a, + 0x98,0x1a,0x1b,0xc4,0x9b,0x97,0x4e,0xe1,0xbf,0xfd,0xa3,0x77,0x71,0xfd,0xd2,0xa9, + 0x9e,0xb2,0xb8,0x66,0xdd,0xf9,0xc4,0x57,0x2a,0x49,0xb6,0x92,0xc6,0x88,0xd4,0x2, + 0x8b,0xd5,0x52,0xd8,0xc,0xb,0xfd,0xa7,0x86,0x93,0xc8,0x18,0x8a,0xa1,0x39,0x1c, + 0xfd,0x4f,0x95,0xa9,0x38,0xa3,0xc8,0xb3,0x99,0x9e,0x18,0xa2,0x2b,0x67,0x67,0xa8, + 0xd1,0xa8,0xf5,0x94,0xa5,0xbd,0xca,0x24,0x98,0xef,0xaf,0x5b,0xed,0x2e,0x56,0x37, + 0xf7,0xf0,0x7c,0x73,0xf,0xab,0x5b,0x7b,0x58,0x59,0xdf,0xe1,0xa7,0xcf,0x77,0xf0, + 0x74,0x7d,0x1b,0x6b,0x9b,0x7b,0x38,0x6a,0xb5,0x3,0x71,0x5f,0xad,0x4,0x4b,0x74, + 0xa6,0x72,0x50,0x20,0xf6,0xe9,0x76,0xd5,0x8a,0xc1,0xdc,0xe4,0x8,0x2e,0x2e,0x4e, + 0xe1,0xfa,0xc5,0x79,0x7a,0xe3,0xfc,0x1c,0x2e,0x9d,0x9e,0x7e,0xe9,0xe4,0xde,0x4b, + 0xcb,0xcd,0xcc,0x38,0x35,0x35,0x8a,0xdf,0x7d,0xeb,0x2,0x31,0x80,0x7f,0xf7,0xb3, + 0x9b,0xf8,0xed,0xd7,0x8f,0x38,0xbb,0x23,0x88,0x33,0x54,0xb6,0xac,0x42,0x94,0xa9, + 0x64,0x1,0xc0,0x2,0xd8,0x3b,0x68,0xe1,0xbb,0x27,0xab,0xf8,0xe6,0xe1,0x73,0x8c, + 0xc,0x34,0x31,0xe8,0x75,0xf5,0xbd,0xa,0xfb,0xff,0x5d,0xdd,0xf9,0xf3,0x8d,0x3d, + 0x7c,0xf4,0xf5,0x23,0x7c,0xfa,0xed,0x63,0x2c,0x6f,0xec,0xc5,0x2,0xdb,0xb5,0x2c, + 0xb1,0xbf,0x9e,0x51,0x10,0x2c,0x86,0xad,0xf5,0xed,0x3,0x6c,0xef,0x1f,0xe1,0xee, + 0xd3,0x75,0xd4,0x6b,0x15,0x54,0x2b,0x6,0xd5,0x4a,0x5,0x23,0x43,0x4d,0xcc,0x4f, + 0x8d,0xe2,0xb5,0xd3,0xd3,0x78,0xeb,0xf2,0x29,0x7c,0xef,0xda,0x59,0xc,0xf5,0x9b, + 0x9e,0x64,0xc5,0x5e,0xef,0x4f,0x7f,0xb3,0x86,0xd7,0xcf,0xcd,0xd2,0x6f,0x67,0xc6, + 0xfc,0x5,0x6b,0x90,0x8c,0x7f,0x39,0xd1,0x82,0x85,0x1d,0xb8,0x4d,0x37,0x40,0xda, + 0xa7,0xab,0xec,0x34,0x9b,0xee,0x65,0x96,0x30,0x75,0x66,0xf5,0x45,0x3a,0x1a,0xab, + 0x90,0x91,0x11,0x25,0x28,0x22,0xc0,0xf,0x24,0x90,0xd9,0x44,0xb8,0x63,0xce,0xf8, + 0x60,0x72,0x85,0xed,0x2f,0x8a,0xaa,0x4c,0x85,0x89,0xfb,0x5d,0x95,0xf,0x5e,0x64, + 0xab,0x13,0x67,0x82,0x77,0x7a,0x71,0x94,0x27,0x95,0x5c,0x9f,0xd2,0x77,0x9c,0xca, + 0xc,0xe2,0xa0,0x13,0xd9,0x39,0x2b,0x26,0xaa,0xd6,0xb0,0x82,0x3,0xf5,0xd4,0x98, + 0xeb,0x9f,0x4b,0x78,0x78,0x39,0x10,0x4f,0x94,0xe3,0xe3,0xa5,0xb1,0x5a,0x2,0xb2, + 0xa7,0x72,0x32,0x22,0x6b,0x68,0x5a,0x53,0x19,0xa8,0xbc,0x6d,0x55,0xad,0x77,0x68, + 0x81,0x8c,0x7a,0x81,0x64,0xcd,0x2e,0x7c,0x2b,0xe5,0x8c,0xb,0xcd,0x9e,0x2f,0x90, + 0x36,0x4c,0xc,0xde,0x28,0xb8,0xb0,0x66,0x17,0x46,0x96,0xc2,0xaa,0xaf,0x2c,0x52, + 0x49,0x69,0xf2,0xc1,0x10,0x21,0x7,0xec,0x23,0x1c,0x64,0xd4,0x65,0x95,0x1c,0xc6, + 0x52,0x16,0x79,0xb2,0x65,0xd,0xda,0xe7,0xa8,0x3d,0x37,0x52,0x97,0xae,0x5c,0xcb, + 0x5c,0x74,0xa5,0xb8,0xfa,0xdd,0x6b,0x31,0xd8,0x6c,0xd0,0xfb,0x6f,0x9c,0x35,0x7f, + 0xfa,0xe3,0x6b,0xf4,0xce,0xd5,0xd3,0xd4,0xc8,0xc2,0x50,0xf2,0x49,0xb0,0xec,0xe0, + 0xdb,0xdd,0x3f,0xc2,0xe3,0x95,0x4d,0x3c,0x59,0xdd,0xc6,0xa3,0xe5,0x2d,0x3c,0x78, + 0xb6,0x8e,0x7,0x4b,0x1b,0xf8,0xee,0xe9,0x1a,0x76,0xf7,0x5b,0x3a,0xb3,0x86,0x4b, + 0xee,0xd,0x75,0x55,0xe7,0x86,0x4b,0x88,0xb1,0xa9,0x87,0x5d,0x77,0xa4,0xec,0xa1, + 0x8d,0xf5,0x9d,0x7d,0xec,0x1d,0x1e,0xe3,0xea,0xd9,0x19,0x8c,0xe,0xf7,0x63,0x6e, + 0x62,0x28,0x22,0x5,0x92,0x8c,0xd7,0x3e,0x71,0xd6,0x98,0xdd,0xae,0xd,0x91,0xe9, + 0x2a,0xcb,0x20,0xdc,0xc6,0xd1,0x2a,0xcb,0xba,0xc6,0xd3,0xb9,0x9c,0x24,0xf7,0x20, + 0x89,0x96,0x85,0x12,0x6f,0xc8,0xad,0x2d,0xdc,0x65,0xe1,0xd2,0xcf,0xa3,0x83,0x72, + 0x58,0xd,0x71,0xf0,0x6c,0x7,0x3a,0x1d,0x8b,0xd6,0xf1,0x49,0xec,0x6b,0x5f,0xe6, + 0x46,0xd6,0x6b,0x1a,0x3c,0x3e,0xe9,0xe0,0xc9,0xca,0x16,0x9e,0x6f,0xee,0x62,0x63, + 0xf7,0x10,0x6b,0x9b,0xfb,0xd8,0xdc,0x3d,0xe0,0xcd,0x9d,0x43,0x6c,0xee,0x1e,0x62, + 0x6b,0xf7,0x10,0x6b,0x5b,0x7b,0x58,0xdd,0xda,0xe3,0xd6,0x71,0x57,0xd1,0x39,0x23, + 0x32,0x96,0x5b,0x4a,0x17,0x40,0x12,0x12,0xe1,0x2f,0x84,0x27,0x2b,0x5b,0xf4,0x74, + 0x75,0x1b,0x8f,0x57,0x36,0xf9,0xd6,0xfd,0x15,0x9c,0x9e,0x1d,0xa3,0x99,0x89,0x61, + 0xcc,0x8c,0xf,0x62,0x66,0x7c,0x18,0x93,0x23,0x3,0xa8,0xd5,0xaa,0x85,0x86,0x23, + 0x7f,0x4e,0xf2,0x1a,0x3a,0x3d,0x3b,0x8e,0x1f,0xbf,0x5,0xda,0xd8,0x3e,0xe0,0x27, + 0xcf,0xb7,0x69,0x75,0x63,0x97,0x2d,0xa3,0x50,0xf4,0xa0,0xf2,0x1f,0xa,0x3e,0xda, + 0x4a,0xc0,0x96,0xfb,0x53,0x3e,0x5b,0xdd,0xc1,0x7f,0xf8,0xf9,0x97,0x58,0x59,0xdf, + 0xc1,0xe5,0xc5,0x69,0x8c,0xc,0x35,0xd1,0x6c,0xd4,0x60,0xc8,0xc0,0x18,0x77,0x4d, + 0x5b,0x66,0x1c,0xb7,0x3b,0x38,0x6c,0x9d,0xe0,0xf0,0xb8,0x8d,0xa,0x11,0x2e,0x2e, + 0x4e,0x61,0x72,0x74,0xf0,0x95,0x89,0x6c,0x0,0xb0,0xb9,0x77,0x88,0xdb,0x8f,0x9e, + 0x63,0x69,0x75,0x17,0x96,0xb9,0xe4,0x8,0xd3,0x6a,0x29,0x49,0xe6,0x65,0x85,0x70, + 0x32,0xac,0x5,0xda,0xed,0x2e,0xda,0xd4,0xc1,0xfe,0x51,0x42,0x8,0x97,0xd7,0x77, + 0xf1,0x78,0x79,0xb,0x4b,0xcf,0xb7,0xf0,0x70,0x65,0x13,0x77,0x9f,0x6e,0xe0,0xfd, + 0xd7,0x17,0xf1,0xd6,0x95,0xc5,0x97,0xae,0x55,0xe4,0xfa,0x8c,0x88,0x30,0x3c,0xd8, + 0x87,0xd1,0xa1,0x26,0xb4,0xbd,0x1e,0xc0,0x8e,0x94,0x18,0xd3,0xd2,0x92,0x9b,0x68, + 0xfa,0xef,0x98,0xe1,0x9b,0x14,0x3e,0xce,0xbc,0xba,0x2c,0xa8,0x2c,0x37,0x3c,0x95, + 0x3,0x59,0x56,0x6a,0x38,0x97,0x2a,0xb2,0x18,0xf1,0x64,0x4,0x30,0x48,0xbb,0xb2, + 0x66,0xf6,0xe9,0xd2,0xed,0xb4,0x5a,0x8e,0x87,0x50,0x9,0x76,0x2d,0x6d,0x5c,0x11, + 0xa1,0xf9,0xa2,0xee,0xab,0xec,0x2f,0x52,0x1a,0x27,0x6e,0x2,0x1,0x21,0x14,0xbf, + 0x97,0x33,0x6f,0x13,0x2a,0x2e,0x62,0x14,0xb,0x30,0xeb,0xc6,0xb3,0xec,0xed,0x62, + 0x42,0xa9,0xb6,0xc4,0x41,0x49,0xe7,0x94,0x7e,0xb1,0x98,0xaa,0x59,0x70,0x26,0xb2, + 0x5a,0x45,0x6a,0xac,0x67,0x8,0x56,0x9c,0x82,0xb2,0x35,0x1c,0x95,0xf1,0xc,0x20, + 0x9e,0xb,0x89,0xd7,0x97,0xd3,0xf3,0x37,0xd1,0x55,0x2a,0x91,0x33,0xd3,0xce,0x9a, + 0x33,0x62,0xa2,0x7a,0x4d,0x7c,0x46,0x7,0x17,0xa7,0xc6,0x2,0xbb,0xd2,0x63,0x50, + 0x62,0x5f,0x9f,0xec,0x2c,0xb8,0xc8,0x99,0x48,0x12,0x30,0x14,0x19,0xe,0x9a,0xe9, + 0xe8,0x42,0x3e,0x82,0xcd,0xb2,0x91,0x56,0x96,0xde,0x1e,0x54,0x10,0xdf,0xc,0x91, + 0xf,0x9c,0xa6,0x60,0xcd,0xce,0x32,0x42,0x55,0x90,0xb0,0x10,0x19,0xec,0x9e,0xc6, + 0x6e,0x10,0xf5,0xa4,0x83,0x7d,0xd,0xba,0x2a,0x7c,0xc3,0xe5,0x61,0xd0,0x8b,0x41, + 0x9b,0x4f,0xe6,0x1b,0xdb,0x7,0xf8,0xf6,0xd1,0xa,0xfe,0x8f,0x5f,0x7f,0x8b,0xdf, + 0x7c,0xf5,0x8,0xf7,0x9e,0xae,0xa3,0xcb,0xb6,0x98,0x61,0x20,0x7d,0xf9,0x8b,0x9a, + 0x8b,0xac,0xa8,0x50,0x89,0x52,0x43,0x2b,0x6,0xdd,0x14,0xb3,0x8f,0xaf,0x1f,0x2c, + 0xe3,0xf4,0xec,0x18,0xa6,0x46,0x7,0x50,0xa9,0x14,0x49,0x49,0xbb,0xfb,0x47,0xfc, + 0x6c,0x6d,0x87,0x5b,0xed,0x8e,0xe6,0x7a,0x94,0xa8,0x1e,0xe5,0xa,0x9d,0x13,0x12, + 0x17,0x2e,0x24,0x79,0x7d,0x44,0x4f,0xfd,0xe0,0x68,0x22,0x5b,0x4a,0xa,0x5e,0x1, + 0x91,0x4c,0xe7,0xc0,0xc8,0xd5,0xad,0x3d,0xbe,0xfd,0x78,0x8d,0xb6,0x77,0xf,0x79, + 0x61,0x7a,0x94,0xfe,0x4b,0x4c,0x4c,0xe4,0x73,0x5a,0xdf,0x3e,0xc0,0x7f,0xfa,0xf0, + 0x1b,0xfc,0xea,0xcb,0x7b,0xfc,0xed,0xe3,0x35,0xec,0x1d,0xb4,0x9c,0x51,0xa7,0x2a, + 0xf,0xfe,0xce,0x32,0x9c,0xd1,0x3d,0xa4,0x24,0x8c,0x4b,0x1a,0x69,0xcf,0xde,0x67, + 0xbd,0x42,0x3a,0xe9,0x32,0x3f,0x5a,0xde,0xc2,0xa3,0x95,0x4d,0xfa,0xe0,0x93,0xbb, + 0xa8,0x56,0xc,0x5f,0x98,0x9f,0xc4,0x9b,0x97,0xe7,0xe9,0xfd,0x6b,0x67,0xf1,0xd6, + 0xe5,0x53,0xb8,0xb0,0x30,0xf5,0x42,0x4f,0xf3,0xb2,0xeb,0xea,0xf4,0xec,0x38,0x7e, + 0x78,0xfd,0x1c,0xad,0x6c,0xec,0xf0,0x7,0x9f,0xdc,0xa5,0xd5,0xcd,0x3d,0x15,0x90, + 0xa4,0xa7,0x74,0xa9,0x33,0x96,0x2b,0x3f,0x31,0xe0,0x8,0x76,0x10,0x81,0xb0,0x77, + 0xd8,0xa6,0xff,0xf0,0xf3,0x5b,0xf8,0xf8,0xd6,0x13,0xbc,0x76,0x6e,0x16,0xe7,0xe7, + 0x27,0xe2,0x2e,0x3a,0xf4,0xeb,0x47,0xad,0x13,0x6c,0xef,0x1d,0x62,0x79,0x7d,0x17, + 0x3b,0x7,0x2d,0x8c,0xc,0x34,0xf1,0xdf,0xfd,0xc9,0xfb,0x98,0x18,0x19,0x78,0xe5, + 0xf7,0x85,0x99,0xb1,0x77,0xd0,0xc2,0xd2,0xfa,0x2e,0xba,0x92,0x98,0x85,0x32,0x13, + 0xac,0x4c,0x93,0x4d,0x65,0x1,0x58,0x1,0xcc,0x25,0x99,0xdb,0x4,0x30,0x70,0xd8, + 0x3a,0xc1,0xed,0xc7,0x6b,0xb8,0xfd,0x78,0xd,0x1f,0xfc,0xf6,0x3b,0xfc,0xc5,0x9f, + 0xbe,0x8f,0xb7,0xae,0x2c,0xbe,0x32,0xff,0xa1,0x70,0xbd,0x85,0xba,0x63,0xf5,0x31, + 0xef,0xce,0x26,0xab,0x14,0x44,0x2a,0xe3,0x22,0x9e,0xb1,0xc6,0x1b,0x36,0x41,0x57, + 0x58,0x16,0xe6,0x98,0x99,0x69,0x3b,0x95,0x32,0xd7,0xb9,0xc0,0x65,0xa,0x77,0x9f, + 0x52,0x10,0x51,0xfe,0x78,0x48,0xc9,0x4a,0x29,0x33,0x84,0xa9,0x16,0xa0,0xa8,0xfc, + 0x17,0xc7,0x64,0x35,0x16,0xad,0x3b,0x4a,0xa,0x2b,0x50,0x1e,0xf3,0x26,0xa,0x2, + 0xe7,0xa2,0x26,0x2a,0x8f,0xe1,0xcc,0x13,0xbd,0x84,0xdf,0x5,0x40,0x19,0xd1,0x2e, + 0xbc,0xa0,0x62,0x2d,0xc5,0xc5,0x2e,0x11,0xe8,0x35,0x28,0x65,0x31,0xa7,0xf1,0xaa, + 0x13,0xf6,0xb6,0xb1,0x3e,0x19,0xca,0xc8,0xfb,0x91,0x97,0x9d,0xae,0xa,0xd2,0x64, + 0x83,0x40,0x1c,0xa,0xdc,0xa1,0xa8,0x76,0xc8,0x7c,0x80,0x73,0x54,0x40,0x2e,0xdc, + 0x49,0xef,0xda,0x9c,0xb,0x51,0xc8,0x6c,0x12,0x8,0xa,0x85,0x94,0x25,0xc5,0x94, + 0x70,0xdf,0x69,0x65,0x3b,0x4b,0x1a,0xbb,0x23,0x56,0xc7,0x5d,0xb4,0xc1,0x61,0xb1, + 0x18,0x4f,0x77,0x2d,0xb1,0x1e,0xf,0xd2,0xa7,0x42,0xf3,0xa3,0x89,0x3d,0x44,0xa2, + 0x8b,0x8c,0x96,0x95,0xe1,0x82,0x4c,0x50,0x7a,0x7a,0x12,0x3e,0x8a,0xc5,0x65,0x5b, + 0xb9,0x4d,0x3,0x7b,0x1b,0x58,0x16,0x4b,0x71,0x44,0x46,0xbb,0xb4,0x38,0x45,0x34, + 0xa2,0x9,0x24,0x3d,0x26,0xc6,0xc2,0xcc,0x18,0xfd,0x37,0x7f,0xfc,0x9e,0x79,0xff, + 0xda,0x59,0x5,0x1,0xf7,0x3a,0x7c,0xe5,0x64,0x7e,0x74,0xdc,0xc6,0xa7,0xb7,0x9f, + 0xe2,0x57,0x5f,0xde,0xc7,0x67,0xdf,0x3e,0xc5,0xa3,0xe7,0x5b,0x58,0xdf,0xda,0x43, + 0x97,0xad,0x20,0x4a,0x6a,0x8f,0x7c,0x75,0xbb,0xc6,0x74,0xae,0x32,0x25,0x1,0xf7, + 0xb8,0x83,0xb4,0xfe,0xc4,0x32,0x30,0x3e,0x3c,0x88,0x89,0x91,0x81,0xd8,0xbb,0xe4, + 0x64,0xa1,0xfb,0xcb,0x1b,0xf8,0xd5,0x97,0xf,0xb0,0xbd,0x7b,0xc8,0xfa,0x56,0xce, + 0x92,0x6,0x43,0xe1,0xe6,0x62,0xe,0x2,0x93,0x27,0xf8,0x90,0x42,0xfb,0x90,0x54, + 0x1d,0xb2,0x49,0x23,0x2a,0xb6,0xee,0xee,0xad,0xd8,0x3d,0x68,0xd1,0xed,0x47,0xcf, + 0xf1,0xeb,0xaf,0x1e,0x62,0xa0,0xbf,0x81,0x85,0xa9,0x91,0x94,0xb6,0xf5,0xa,0x70, + 0xbb,0xb5,0x16,0xed,0x93,0x13,0x7c,0xf7,0x64,0x15,0x7f,0xf3,0xdb,0xdb,0xfc,0xcd, + 0xc3,0x15,0x74,0x1c,0x6a,0xc1,0xaa,0x3d,0x8e,0xbd,0xb8,0x3,0xda,0x51,0x6c,0x5c, + 0x5c,0x2e,0x4d,0x74,0xb1,0x4c,0xb,0x18,0x5f,0x24,0x59,0xa0,0x51,0xa4,0xdb,0x19, + 0xf7,0xa,0x76,0xbb,0x96,0x1e,0x3c,0xdb,0xc0,0xee,0x61,0x8b,0xbf,0x7b,0xbc,0x86, + 0xbf,0xff,0xf4,0xe,0x5d,0x39,0x3d,0x83,0x1f,0xbf,0x73,0x1,0xaf,0x9d,0x9e,0x46, + 0x30,0x1e,0x2a,0x23,0xfc,0xe5,0x6,0x43,0xaf,0x9d,0x9b,0xc5,0x9f,0x74,0xde,0xa0, + 0x7,0xcf,0x36,0x79,0x75,0x6b,0x4f,0x5b,0x73,0x64,0x8c,0x58,0xa5,0x98,0x95,0xeb, + 0x48,0x19,0xa4,0x18,0x9a,0x7e,0x4e,0xae,0x7e,0x2b,0x1b,0x7b,0x38,0x6a,0x9f,0xe0, + 0xfe,0xd2,0x3a,0xfa,0x9a,0x75,0x54,0x4d,0x2a,0xa6,0x9d,0x8e,0xc5,0x51,0xbb,0x8d, + 0xfd,0xc3,0x36,0xe6,0x27,0x87,0x71,0xfe,0xd4,0x4,0xfa,0x1a,0xb5,0x57,0x86,0xde, + 0xbb,0xdd,0x2e,0xb6,0xf7,0x5b,0x58,0x5a,0xdb,0xc1,0xfe,0x41,0x4b,0x4d,0x9c,0x24, + 0x1a,0x28,0x15,0x30,0x45,0x59,0x98,0x96,0xc,0xbc,0x22,0x94,0x22,0xb8,0x94,0x8f, + 0xb9,0x7e,0x12,0xa8,0x98,0x57,0xbb,0x86,0x64,0x21,0xb7,0xd6,0xe2,0xb0,0x75,0x82, + 0xbd,0xc3,0xb6,0xde,0xc,0xb1,0xb3,0xd3,0xd,0xf6,0xd8,0xb1,0x58,0x86,0x17,0xde, + 0x19,0xc2,0xa5,0xf5,0x6f,0xd8,0x89,0xfb,0x24,0xf5,0x28,0x29,0x26,0x6d,0x19,0xce, + 0xa4,0x7,0x40,0xe6,0x72,0xb3,0x2e,0x69,0xf1,0xa,0xa1,0x2a,0x8d,0x6f,0x24,0x65, + 0x86,0x29,0x4c,0xd1,0xc7,0x3d,0x45,0x64,0x19,0x55,0x4f,0xab,0x71,0x9f,0x27,0x6c, + 0xe5,0x38,0xb3,0x5f,0x25,0x19,0xc0,0x5e,0xc8,0xb,0x15,0xf3,0x7b,0xbc,0x89,0xa8, + 0x50,0xdf,0x3,0x2,0xaa,0x22,0x3e,0x21,0xe8,0x38,0xd2,0x69,0xb5,0x97,0x99,0xb, + 0x51,0x41,0x4c,0x9f,0xa6,0x7d,0x3d,0x9c,0x83,0x62,0x16,0x64,0x86,0x3c,0x70,0x40, + 0x7b,0xb2,0xc7,0x19,0x2f,0xfa,0x58,0x14,0x53,0x91,0x27,0x22,0xb9,0x96,0x8c,0xd8, + 0x44,0x94,0x54,0x29,0x41,0x56,0x24,0x8,0xa6,0x53,0x47,0x47,0xb9,0x66,0x86,0x39, + 0xa9,0xa0,0x96,0xc9,0xf5,0x20,0x7c,0xf4,0xe3,0x4f,0x57,0x79,0xb9,0x54,0x7a,0x23, + 0xe8,0x29,0xd9,0x54,0xbc,0xc6,0x80,0xc3,0xb9,0x97,0x2e,0x3a,0xe,0x38,0x29,0x5c, + 0xe5,0x57,0x95,0x57,0xa0,0x33,0x9,0x28,0x20,0x92,0x52,0x37,0xdf,0xb7,0x26,0xcd, + 0x7a,0xb6,0x1b,0xc9,0x87,0x57,0x45,0x3e,0x4,0x47,0x5d,0xad,0x97,0x41,0xc7,0x5c, + 0xce,0xe0,0xf6,0x16,0x1d,0xe2,0x32,0x8f,0x70,0x4e,0x7c,0x2c,0xff,0xfd,0x61,0xcc, + 0x34,0xc1,0x40,0x9b,0x98,0x40,0xf5,0x6a,0x95,0x5e,0x3f,0x3f,0x47,0x3f,0x7d,0xf7, + 0x32,0x8d,0xe,0xf7,0x17,0xa6,0xa9,0x5c,0x53,0x2b,0x61,0xec,0xa3,0xe3,0x36,0xbe, + 0xba,0xbb,0x8c,0xbf,0xfa,0xf0,0x16,0x3e,0xf8,0xf8,0xe,0x96,0xd7,0x77,0x45,0x1a, + 0x1f,0x29,0xbd,0x4a,0x92,0x62,0x92,0x22,0x1d,0xa8,0x15,0x55,0x41,0xcd,0x92,0xa3, + 0x33,0xfa,0x58,0xb,0x7c,0x8e,0x7a,0xcd,0x60,0x71,0x66,0x4,0x8b,0xd3,0x63,0x31, + 0x8b,0x3a,0x14,0xf5,0xc3,0x56,0x1b,0xcf,0xd6,0x77,0xf0,0xd9,0xb7,0x4f,0xf8,0xd6, + 0x83,0x65,0x3e,0x3e,0xe9,0xea,0x86,0xb2,0xb0,0xc2,0xf7,0xb4,0xd0,0xe0,0x19,0xe7, + 0x5f,0x58,0x16,0xd2,0x88,0x34,0x5d,0x5,0x8e,0x82,0x68,0x9a,0xd,0x29,0xde,0x64, + 0x48,0x8a,0x7,0x69,0x58,0x7b,0x79,0x7d,0x97,0x3f,0xf8,0xe4,0x3b,0xd4,0x6b,0x55, + 0xfc,0xc9,0xef,0x5e,0xa3,0x89,0x91,0xea,0xb,0xb,0x47,0xfe,0xda,0x3f,0x5c,0xde, + 0xc2,0x97,0xdf,0x2d,0xe1,0xdb,0x87,0xcf,0xd1,0xb1,0x36,0x2a,0x65,0x55,0xa3,0xc1, + 0x3e,0x29,0x23,0x87,0xe9,0x38,0xb8,0xa3,0xa3,0x8c,0xc8,0xc1,0xd1,0x67,0x89,0xa1, + 0xf9,0x3,0xce,0xe0,0x5b,0xd4,0x7e,0xf7,0x2b,0xdb,0xb6,0x8b,0x95,0xcd,0x3d,0x2c, + 0x6f,0xee,0xe1,0xcb,0xbb,0x4b,0xfc,0xc5,0x9d,0x67,0xd4,0x72,0x39,0xde,0xb8,0xb8, + 0x30,0x89,0x91,0xc1,0x66,0xb4,0xa9,0x95,0x64,0xad,0xfc,0xda,0x1a,0xea,0x6f,0xe0, + 0xed,0x2b,0x8b,0xb8,0x76,0x71,0x9e,0xee,0x2d,0xad,0xf3,0xe6,0xce,0x11,0x2c,0xb8, + 0x2c,0x5e,0x58,0x30,0x1f,0xf4,0xc4,0x18,0xcd,0xdd,0x63,0x6f,0x68,0x28,0xb8,0x8e, + 0x85,0xcf,0xef,0xec,0xb7,0xb0,0xb3,0xdf,0xca,0x3a,0x6e,0xbd,0x4a,0x3d,0xbf,0x30, + 0x81,0x1b,0x97,0x16,0x30,0x3e,0x3c,0xf0,0x4a,0x4c,0x7f,0x66,0xc6,0xe1,0x71,0x7, + 0x5f,0xde,0x5d,0xc2,0xbd,0x67,0x1b,0x60,0xa2,0xa2,0x1b,0x88,0x57,0x76,0x27,0x22, + 0x79,0x9e,0xaf,0xa1,0x9b,0xcc,0xb2,0xb9,0x8b,0x4,0x17,0x27,0xfc,0x65,0xa8,0xbf, + 0x89,0x77,0xae,0x2c,0xe0,0xf2,0xe9,0xc9,0x9e,0x91,0xad,0xf9,0xba,0x23,0xbc,0xf6, + 0xc7,0x27,0x5d,0x3c,0x5a,0xde,0xe0,0x95,0xcd,0x5d,0x56,0xa8,0x8a,0x24,0x5e,0x11, + 0xe5,0xa1,0x38,0x22,0xd,0x21,0x3a,0xfe,0x85,0xb,0x8e,0xc3,0xe5,0x6e,0x99,0x44, + 0xd6,0x85,0x6f,0x7a,0xad,0xf5,0xcd,0x0,0x31,0x53,0xe6,0x96,0x19,0x65,0x6a,0x12, + 0xbc,0x65,0xb1,0x9b,0xf7,0x9e,0xfd,0x5,0x95,0x59,0xe6,0xb2,0x9a,0x2c,0xa,0x54, + 0xa8,0x6a,0x55,0xae,0xfa,0x24,0x16,0xcf,0x2a,0xc1,0x8f,0xf5,0x4e,0x97,0xa4,0xff, + 0x2c,0x9,0xe6,0x65,0x2a,0xa0,0xc2,0xd7,0x53,0xe0,0x7e,0xa4,0x53,0x4b,0x14,0x64, + 0xc6,0x51,0x5f,0x7,0x15,0x55,0xa4,0x4d,0x4d,0x72,0xd8,0x9f,0xb3,0xe2,0x26,0x59, + 0xf7,0x3a,0xd2,0x34,0xc3,0xa1,0x65,0xbe,0x78,0x94,0x1c,0xa,0xca,0x86,0x21,0xca, + 0xf6,0xf5,0x5e,0x8d,0x90,0x4e,0xb3,0x98,0x72,0xa4,0xa8,0x35,0x41,0x58,0xed,0xa7, + 0x79,0x13,0x16,0xd7,0x9e,0xd1,0xef,0x67,0xfa,0x34,0xa5,0xe6,0x68,0xbf,0x17,0x1b, + 0x31,0x8a,0x33,0x73,0x7c,0xbe,0x62,0xb7,0x9e,0x55,0x9,0xce,0x33,0xde,0xa3,0x68, + 0x49,0xc4,0x5a,0x27,0xa6,0x3b,0xab,0xa9,0x32,0x90,0xf9,0x2c,0x73,0x2e,0xa7,0x48, + 0x7c,0x7,0x26,0xc5,0x9f,0xf2,0x5,0x39,0x5f,0x4,0x12,0xa9,0x66,0xa7,0xb8,0x49, + 0x8e,0x26,0x24,0x46,0xd8,0xba,0xa6,0x20,0x10,0xf6,0x52,0x35,0x32,0xd2,0x75,0x5d, + 0xff,0x43,0x31,0xa0,0x5,0xce,0xda,0x3d,0x14,0x9b,0xf8,0xb8,0x9,0xf5,0x5a,0x15, + 0xef,0xbd,0x7e,0x86,0xde,0x7d,0x6d,0x91,0x9a,0xcd,0x5a,0x69,0x7,0xdf,0x8b,0x4c, + 0x63,0xad,0xc5,0x5f,0xff,0xe6,0x36,0xfe,0xf3,0x47,0xdf,0xe2,0xa3,0x9b,0xf,0xb1, + 0xbe,0x73,0x98,0xf1,0x4,0xc3,0xde,0x4d,0x2,0x1e,0xa4,0xae,0xfd,0x74,0x20,0xeb, + 0xeb,0x4e,0xca,0x34,0x12,0x8a,0xad,0xf3,0xea,0x25,0x3a,0x62,0x8c,0xc1,0xec,0x84, + 0xf3,0x92,0xcf,0x77,0xfb,0xb7,0xee,0xaf,0xe0,0x7f,0xfe,0xab,0xdf,0xf2,0x6f,0xbe, + 0x7e,0x8c,0xe3,0x28,0x17,0x4a,0x5e,0xcf,0x94,0xe3,0xb9,0xe4,0xfa,0xb6,0x18,0x64, + 0xca,0xd1,0x51,0xbf,0x0,0xef,0x89,0x11,0xca,0xcb,0x1,0x41,0x6a,0x69,0x14,0x1e, + 0x3c,0x1,0x45,0xe1,0x2b,0xd1,0xaf,0xbf,0x7a,0x4,0x6,0xe1,0xad,0x2b,0xa7,0x30, + 0x32,0xd0,0x54,0xcd,0x48,0x2f,0x88,0xd4,0xed,0x55,0x19,0x1f,0x7f,0xf3,0x4,0x1f, + 0x7d,0xf5,0x28,0x91,0x80,0xa1,0xe2,0xfb,0x58,0xd4,0x62,0x96,0x8,0x5e,0x3c,0xbd, + 0xa8,0xdc,0x38,0x51,0x2e,0x37,0x28,0x78,0xaa,0x23,0x2d,0x71,0xdc,0x99,0xcb,0x24, + 0x92,0x2,0xf5,0x6e,0x8e,0xc,0x56,0x36,0x76,0xf9,0x7f,0xfa,0xab,0x8f,0xf1,0xf9, + 0xdd,0x67,0xf4,0xaf,0x7f,0xfa,0x16,0xde,0x7f,0xfd,0x34,0x66,0x27,0x86,0xcb,0x61, + 0xde,0xec,0xb9,0xd5,0xab,0x15,0xfc,0xf0,0x8d,0xb3,0xd8,0xde,0x3b,0xa4,0xbf,0xfa, + 0xd5,0x37,0xdc,0x6a,0x75,0xb4,0x1a,0x58,0x82,0xeb,0x9c,0x5b,0x83,0x52,0x21,0x72, + 0xa3,0xc4,0x54,0x2e,0x11,0x87,0x91,0x23,0x2c,0xa9,0x2f,0x3b,0x3d,0x33,0x8e,0xef, + 0xbd,0x7e,0x1a,0x13,0x23,0xfd,0x2f,0x2c,0x8e,0xb2,0x1,0xde,0x3b,0x68,0xe1,0x83, + 0x8f,0xef,0xe2,0xeb,0x7b,0x2b,0xa9,0x48,0x73,0x86,0xf2,0x84,0x3d,0xb4,0x18,0xa8, + 0x24,0x1c,0xcf,0x19,0xd1,0x28,0xae,0x7e,0x4,0x5d,0x3b,0x12,0xa2,0xfd,0xef,0xb8, + 0xb8,0x30,0x89,0x7f,0xfb,0x2f,0xbf,0x87,0x77,0xaf,0x2c,0xaa,0xcc,0x84,0x57,0x81, + 0xdd,0x8f,0x8f,0x4f,0xf0,0xd9,0x77,0x4b,0x7c,0xef,0xe9,0x26,0xb2,0xb0,0xc7,0x12, + 0xab,0xf2,0x30,0x99,0x3b,0x92,0x9,0x87,0xa4,0x1d,0x3,0xb0,0x85,0x3b,0xc7,0xd9, + 0xc6,0xf1,0xdd,0xd,0x6e,0xc6,0x75,0x8f,0xb0,0xfa,0x9e,0x31,0x28,0xac,0x98,0xbd, + 0xa4,0x48,0xf9,0xaa,0x38,0xa4,0x40,0x36,0x5d,0x6,0xc5,0x2e,0x88,0x41,0x6c,0x94, + 0x9f,0x47,0x38,0xf2,0xe4,0x2a,0xa6,0x5a,0x84,0xfb,0xe4,0x64,0x58,0xdc,0xfe,0xea, + 0x4c,0x6e,0x5d,0x34,0x49,0x4c,0x73,0x59,0xb8,0x69,0x76,0xd0,0x69,0x82,0x40,0xee, + 0x64,0xa6,0x7c,0xc7,0x55,0xb8,0x2a,0x89,0xb0,0x97,0x2,0x80,0xa1,0xf6,0x17,0x9a, + 0x7a,0xcd,0x45,0x54,0x27,0x95,0x65,0xf5,0xa5,0xec,0x2b,0x82,0xd0,0x44,0xc7,0x42, + 0x48,0x42,0x92,0x25,0xf8,0xee,0xfe,0x82,0x26,0xa,0x1d,0xa5,0x7,0x8d,0x43,0xf0, + 0xa,0x45,0x1f,0x53,0x39,0xd9,0x29,0xd6,0x78,0xc9,0x3,0x33,0x72,0x82,0xcb,0x90, + 0x6f,0xeb,0x90,0x41,0x26,0xe8,0xee,0x4f,0xae,0xb0,0x18,0x2a,0x5f,0x35,0x37,0x77, + 0x89,0x33,0xb8,0xcb,0xf,0x50,0x4d,0x9d,0x31,0x1c,0x8b,0xa2,0x11,0xef,0xa2,0x91, + 0x84,0x8e,0x4,0x23,0x92,0x28,0x54,0xc9,0xb5,0xda,0x13,0xa9,0xd4,0xc8,0xa6,0xd8, + 0xd2,0x0,0x19,0x26,0xc9,0xc2,0x4b,0x41,0xaa,0x2a,0xb1,0xcb,0x48,0x12,0x1c,0x49, + 0x46,0xbb,0xdc,0x33,0x98,0xb0,0x36,0x37,0x81,0xac,0x45,0x20,0x50,0xbd,0x56,0xa1, + 0x37,0x2f,0xce,0xd3,0xf5,0x8b,0xf3,0xa8,0x55,0x8c,0xd2,0x70,0xbf,0x68,0x77,0xde, + 0x3a,0x3e,0xc1,0x9d,0x27,0xab,0xf8,0xbb,0x8f,0x9d,0x7e,0x78,0x6b,0xef,0x30,0x5f, + 0xff,0x29,0x84,0x5,0x65,0x59,0xf0,0xaa,0xfe,0x94,0x8c,0x5f,0xd0,0x5d,0x7a,0x61, + 0x4c,0x11,0x24,0x44,0x66,0x60,0x63,0xe7,0x10,0x1b,0x3b,0x7,0x38,0xe9,0x74,0xd1, + 0x6a,0x77,0xb0,0xb1,0x7d,0x80,0x47,0xcf,0x37,0xf1,0xc9,0x37,0x8f,0xf9,0xc3,0x2f, + 0x1f,0xf0,0xfa,0xce,0xbe,0xdb,0xbc,0x19,0x8f,0x24,0x6a,0xd6,0x4a,0xd0,0x42,0xba, + 0xf7,0xca,0xc8,0xd5,0x88,0xf5,0x87,0xa,0x11,0xd8,0xa6,0x1e,0xd5,0x88,0xe6,0x93, + 0x2,0x31,0xd3,0x24,0x38,0x30,0x22,0x35,0xe9,0x63,0x71,0x3b,0x28,0x9e,0xa6,0xa9, + 0x18,0xf4,0x35,0xea,0x2f,0x85,0xdc,0x65,0x31,0xd9,0xde,0x6f,0xe1,0xe6,0xdd,0x67, + 0xfc,0xf5,0x83,0x65,0x74,0xad,0x8d,0x36,0xe6,0xd1,0xd4,0x23,0xc9,0x86,0x2,0x6b, + 0x3f,0xeb,0xdb,0x99,0xf3,0xc4,0x44,0x96,0x7e,0xde,0xec,0xa6,0xda,0x68,0x13,0x15, + 0xfa,0x5e,0x31,0x99,0xc4,0xce,0x95,0x48,0xc,0x35,0xee,0xe7,0x74,0x2d,0xb0,0x7b, + 0x78,0x8c,0x4f,0xbe,0x79,0xcc,0xf5,0x6a,0x95,0x3a,0x9d,0x2e,0xfe,0xe0,0xbd,0xcb, + 0x18,0x19,0x68,0x28,0x4d,0x7a,0x4e,0x26,0x33,0xc6,0xa0,0x52,0x31,0xb8,0x7e,0x61, + 0x1e,0xcf,0x37,0xf7,0xf0,0x77,0x9f,0xde,0xa3,0xa3,0x76,0x17,0x79,0xe0,0x79,0x99, + 0x67,0x86,0x9e,0xc5,0x8a,0x4,0x63,0x2a,0xe1,0x20,0x95,0x71,0x64,0x2b,0x44,0x18, + 0x1b,0xee,0xc3,0x99,0xb9,0x71,0x4c,0x8d,0xd,0xbe,0x94,0x60,0x26,0x39,0xd,0x4b, + 0x6b,0x3b,0xb8,0x79,0xef,0x19,0x96,0xd6,0x76,0xc2,0x2e,0xd1,0x5d,0x6c,0x9e,0x2c, + 0x19,0x8f,0x9d,0xb8,0x58,0x33,0x7a,0x47,0x60,0x28,0xca,0x79,0x21,0xe9,0x18,0x90, + 0xc1,0x4f,0x69,0x6d,0x31,0x3c,0xd8,0xc4,0x8d,0x8b,0x73,0xf8,0x83,0x77,0x2f,0xe1, + 0x9d,0x2b,0x8b,0x31,0x1c,0xa9,0x17,0xb1,0x52,0xbe,0xce,0x92,0xc0,0xf7,0xf1,0x37, + 0x8f,0xf9,0xee,0xd3,0x35,0x16,0x53,0x48,0x42,0x4d,0x63,0x9e,0xaa,0x9,0x21,0xb7, + 0xae,0xbd,0x20,0x30,0x91,0x1,0xfb,0xd5,0x1a,0x91,0x85,0xd2,0x3a,0x87,0x19,0xc4, + 0x72,0xa9,0xc9,0x56,0xbc,0xa,0x4d,0xa8,0x5e,0x62,0xe0,0x65,0x52,0xc9,0xd3,0xd1, + 0x3f,0x44,0x84,0x7a,0x85,0x95,0x7d,0x4e,0xec,0x8e,0xbe,0x27,0xb9,0x6f,0x1b,0x1, + 0xd5,0x2,0x31,0x41,0x32,0x2d,0xb3,0xdd,0x75,0x22,0x5b,0xe5,0x7,0x45,0x66,0xf4, + 0xc6,0x84,0xd2,0x10,0x54,0x82,0xca,0x2,0x97,0x5,0x8d,0x4a,0xd6,0xdd,0x4c,0xc8, + 0x8c,0x68,0x50,0xb2,0xd8,0x2b,0x61,0x7d,0xb,0x60,0x9a,0x39,0xa5,0xf,0xea,0x8a, + 0x46,0x42,0x72,0x1e,0xe,0xad,0x4a,0x88,0x93,0x24,0x23,0x2c,0x51,0x20,0xa0,0x78, + 0x63,0xc2,0xeb,0x6d,0x92,0xfb,0x72,0x38,0xf8,0x4c,0x3a,0xad,0xd,0x74,0x15,0xf7, + 0xa6,0x5a,0x8e,0xf2,0x15,0xf2,0xda,0x9,0x4a,0x3e,0x63,0x14,0x29,0x8e,0x39,0x94, + 0x53,0xe9,0x5a,0xe7,0xcf,0x4f,0xca,0x43,0x67,0xc4,0xe6,0x1b,0x29,0xb2,0x49,0xaf, + 0x3,0xa5,0xd3,0x14,0x8c,0x3b,0xcc,0xb8,0x22,0xb6,0x32,0x2c,0x26,0xf6,0xcc,0x5e, + 0xb6,0x70,0x58,0x18,0xd5,0x45,0x64,0x3b,0x12,0xa3,0x16,0x96,0x30,0x22,0x7f,0x36, + 0x4c,0xe4,0x22,0xd1,0xcb,0x5f,0xa4,0x24,0x86,0x8d,0x0,0xf5,0x9a,0x24,0x82,0x8e, + 0xd3,0xa1,0x20,0xc5,0x85,0xf2,0x6f,0xa2,0xf4,0x8d,0x43,0x75,0xf,0xb6,0xaa,0xd5, + 0x2a,0x2e,0x9f,0x9d,0xa1,0xb3,0xf3,0x13,0xd4,0x6b,0x5f,0x5e,0x76,0x78,0x3d,0x5c, + 0xde,0xc0,0xcf,0x3e,0xbb,0x87,0xdf,0x7e,0xfb,0x18,0x5b,0x7b,0x47,0x59,0x1a,0x1d, + 0xf4,0x40,0x28,0x5e,0x33,0x83,0x32,0xcb,0x7c,0x2a,0x45,0xd4,0xb,0xe4,0xb8,0xdc, + 0x48,0x48,0xf0,0x58,0x3a,0x1d,0x8b,0xcf,0xef,0x2c,0xb9,0x33,0xd1,0x38,0xb2,0xd8, + 0x9d,0xc7,0xab,0xfc,0xd1,0xad,0x47,0x58,0x5e,0xdb,0x61,0x52,0x68,0x98,0xd,0x16, + 0xa1,0x2e,0xe,0x94,0x99,0xa5,0x76,0x55,0x86,0x24,0xb1,0x7f,0xd4,0x49,0xe7,0x1a, + 0xe3,0x6a,0xe1,0x70,0x25,0xa3,0xf4,0xfc,0xa1,0xa9,0x62,0x70,0x46,0x74,0x93,0x3a, + 0x45,0xd7,0xe2,0x54,0x8d,0x73,0x4e,0x7b,0xe7,0xd2,0x2,0xe6,0x7c,0x10,0xcb,0xab, + 0xb8,0xee,0x1d,0x1d,0x9f,0xe0,0xd1,0xca,0x26,0xee,0x3d,0x5d,0xc7,0x41,0xeb,0x84, + 0xcb,0x55,0x2a,0x11,0x43,0x14,0x74,0x1a,0x8f,0x7d,0x1a,0x44,0xa5,0x91,0x44,0xfd, + 0x54,0x40,0x83,0xf2,0xe1,0x96,0xf6,0xde,0x2c,0x13,0xa,0x1c,0x1f,0x53,0xfc,0x2, + 0x41,0x2,0x1,0x11,0xa1,0xdd,0xb1,0xf8,0xfb,0xcf,0xee,0x81,0xc1,0x18,0x19,0xec, + 0xc7,0xdb,0x57,0x4e,0x61,0x62,0x64,0xa0,0xe7,0x5a,0x27,0x7c,0x7c,0x6a,0x6c,0x10, + 0x17,0x17,0xa6,0x30,0xd4,0xdf,0xc4,0xf6,0x7e,0xeb,0xc5,0xdc,0xe2,0x12,0x9e,0x29, + 0x71,0x89,0xbb,0x74,0x61,0xb0,0x2a,0x4b,0xed,0x2,0x6,0xfa,0x1a,0xb8,0x71,0x79, + 0x11,0xe7,0xe7,0x27,0x5e,0x38,0x99,0xcb,0xf7,0xa5,0xdb,0xed,0x62,0x65,0x73,0x1f, + 0xb7,0x1f,0xaf,0x62,0x69,0x7d,0x57,0x98,0x82,0x25,0x24,0x4a,0xef,0xbc,0xe5,0x8a, + 0xd3,0x24,0xd2,0x17,0x74,0xac,0x75,0x71,0xb7,0x9c,0xee,0x95,0x91,0xa1,0x26,0xde, + 0x38,0x37,0x8b,0x7f,0xfb,0x2f,0xde,0xc3,0xef,0xbd,0x75,0x1,0x95,0xca,0xcb,0xe3, + 0x55,0xf3,0xc2,0x7e,0xd8,0x3a,0xc1,0xbd,0xa5,0xd,0xfe,0xfc,0xbb,0x67,0xbc,0xbe, + 0x73,0xc0,0xc9,0xb9,0xd3,0x5f,0x1e,0x71,0xe5,0x68,0xd9,0x21,0x35,0xc4,0x16,0x3a, + 0x3d,0x4d,0xa6,0x80,0x85,0xa1,0x92,0xd8,0xa,0x43,0x95,0x18,0xc6,0x2a,0x20,0x74, + 0xb9,0x94,0x35,0xe9,0xa,0xcb,0xee,0x19,0xcd,0xdd,0xd6,0x83,0x6e,0xe4,0x44,0x1b, + 0x14,0xe3,0x48,0x94,0x7d,0x7c,0xba,0x3e,0xaa,0x44,0x19,0xdb,0xaf,0xa0,0x9,0xd3, + 0x76,0xa2,0x2c,0x76,0x30,0x54,0xd8,0xd1,0x9,0xe6,0x7a,0xd0,0xa9,0xb,0x14,0x3b, + 0xee,0x96,0xb3,0xc9,0x94,0xa8,0x18,0xd5,0xa9,0xb6,0xaf,0x2c,0xa0,0xca,0xec,0xb8, + 0x8b,0x56,0xaf,0x2c,0xa2,0x5a,0x15,0x5,0x4b,0x14,0x6d,0x22,0xc5,0xd7,0x12,0x83, + 0x63,0x2c,0xce,0x69,0x25,0x61,0xd4,0xfa,0x2d,0x96,0x14,0xa1,0x98,0x56,0xbf,0x21, + 0xc0,0xce,0xd2,0xe9,0x85,0x74,0x5c,0x52,0x2,0xaf,0x33,0x14,0x81,0xb,0xc2,0x39, + 0x50,0x12,0xfe,0x27,0x3f,0xee,0xec,0xe,0x17,0x29,0x1c,0x19,0xc1,0xca,0x28,0x53, + 0x1c,0x8a,0x47,0x5d,0x64,0x34,0x47,0xda,0x8d,0x1b,0xc6,0x2d,0xb3,0xda,0x70,0x73, + 0x94,0x2f,0xe6,0x7b,0xb2,0x42,0x98,0x5b,0x64,0xd,0x4,0xcb,0x98,0x68,0x5e,0xa9, + 0x62,0xb3,0x59,0x26,0xe1,0x19,0x71,0x69,0xc4,0x80,0xf,0x90,0x92,0x33,0x44,0x5b, + 0x77,0x44,0x16,0x7b,0xf0,0x76,0x8f,0x1e,0xd6,0x8e,0x1,0x1f,0x78,0x24,0x7e,0x88, + 0x4f,0xcc,0x6c,0x80,0x60,0x2a,0x44,0x13,0x23,0x3,0x18,0xec,0x6b,0xbc,0x50,0xb7, + 0x9a,0x1f,0x4,0xdf,0x3c,0x7a,0x8e,0xbf,0xfd,0xe4,0xe,0xd6,0xb6,0xf,0x52,0x94, + 0x80,0x5c,0x7,0xb1,0xb8,0xe1,0xa,0xf7,0x41,0xd1,0x6f,0x1f,0xa5,0x57,0x6f,0x6, + 0x89,0x86,0xb7,0x4e,0x24,0x15,0x86,0x3f,0x27,0x5d,0x8b,0xf,0xbf,0x78,0x80,0x5b, + 0xf7,0x57,0x60,0xa8,0x82,0xa3,0xf6,0x31,0xef,0xec,0xb5,0xb0,0xba,0xb9,0x5f,0x50, + 0x6,0x92,0x28,0x5c,0xe,0x41,0x8e,0x19,0x9c,0xac,0xe4,0x35,0xf2,0x18,0x35,0x7e, + 0x94,0x10,0xae,0x8e,0x86,0xd,0x41,0xb,0x35,0xc4,0xdb,0x64,0xe2,0xb5,0x4e,0xd2, + 0x6d,0x4a,0xdc,0xdf,0x64,0xc,0xae,0x5f,0x9c,0xa7,0x1b,0x97,0x17,0xa8,0x5e,0x35, + 0x8a,0x24,0x96,0x1b,0xf7,0xc8,0xdb,0xe9,0xe1,0xb3,0xd,0xfc,0xf2,0x8b,0x7,0xbc, + 0xba,0xb3,0x9f,0xa5,0x13,0x32,0xeb,0xb1,0x3c,0xd0,0x52,0xa2,0xbb,0x7,0x7,0xf2, + 0x92,0xe3,0xb7,0x71,0x2a,0xfd,0xc2,0x41,0x2a,0x7c,0x5,0xf2,0xb5,0x94,0x13,0x23, + 0x45,0xc,0xd8,0x21,0xef,0xcc,0xe1,0x2c,0x60,0x81,0x97,0x85,0x2f,0xb,0xc3,0xd4, + 0x17,0x77,0x9e,0xa1,0x59,0xff,0x82,0x26,0x46,0xfa,0x31,0x31,0x32,0xf0,0x52,0x24, + 0x82,0x99,0x31,0x36,0xdc,0x8f,0xb,0xa7,0x26,0xb1,0xb5,0x7b,0x88,0x83,0xd6,0x49, + 0x7c,0xac,0x5,0xfa,0x43,0x76,0xc1,0x30,0x95,0x28,0x71,0x29,0xd7,0x48,0xe4,0x59, + 0x5f,0xe9,0x23,0x3,0x7d,0xd,0xbc,0xff,0xfa,0x69,0x5c,0x5c,0x9c,0x8a,0x8f,0xa5, + 0x97,0x47,0x7b,0x98,0x84,0x8d,0x31,0xf8,0xe2,0xce,0x12,0x3e,0xbc,0xf9,0x8,0x7, + 0x47,0x27,0x48,0xa6,0x60,0x88,0xb2,0x63,0x2e,0x95,0xe3,0x52,0xae,0x7e,0xce,0xd6, + 0x4a,0xac,0x89,0x17,0xfe,0xcf,0xf5,0xb,0x73,0xf8,0xc1,0x1b,0xa7,0xf1,0xa3,0x37, + 0xcf,0xe3,0xda,0xb9,0x59,0x54,0xab,0x95,0x42,0x98,0x51,0xae,0x32,0x28,0x8b,0x8a, + 0xfd,0xf0,0xcb,0xfb,0xfc,0xef,0x7e,0xfe,0xb5,0x5d,0xdf,0x39,0x10,0x5c,0x30,0xf6, + 0x89,0xd5,0x2e,0x6e,0x10,0x11,0x65,0xb2,0x9,0x55,0x60,0xcb,0x82,0xd,0x1e,0xc0, + 0x1c,0x16,0x94,0x74,0x61,0xd,0x47,0xa2,0xc4,0x91,0x20,0x6f,0x8,0xd2,0x1a,0x95, + 0x53,0x19,0x8c,0xf0,0x7d,0x52,0x8d,0x99,0x54,0x9b,0x96,0xa8,0xc8,0x15,0xdf,0x8a, + 0xb2,0x9,0x5d,0x4f,0xf4,0x9c,0xe1,0xf7,0xac,0x74,0xc9,0x5,0xe9,0x1,0x95,0x48, + 0x25,0xa3,0xa2,0x8d,0x4a,0xc8,0xe,0x54,0x4c,0x3b,0xcb,0xfd,0xdf,0x95,0x5a,0x5b, + 0x74,0xd7,0xc2,0xc6,0x27,0xe9,0x63,0xf5,0xab,0x25,0xfb,0x8d,0xd8,0x19,0xc6,0xbd, + 0x4,0x9,0x9e,0x37,0x47,0xb4,0x36,0x6d,0x9f,0x8d,0xc,0x90,0x22,0x16,0x24,0xb8, + 0x0,0x38,0xb,0x56,0xb5,0x20,0xcb,0x26,0x70,0x2e,0xd6,0x28,0xe,0x6b,0xe,0xe1, + 0xd9,0x1e,0xcc,0x9b,0x91,0xe7,0xdc,0x2a,0x79,0x4,0x28,0x52,0xd2,0xc5,0x3e,0x89, + 0x8a,0x37,0x8c,0x9b,0xd6,0x90,0x8,0x7c,0x6c,0xb4,0x2d,0xae,0x88,0x6e,0x22,0x23, + 0xd5,0x68,0xe9,0x65,0x71,0xd8,0xac,0x89,0xdd,0x26,0xb1,0xb2,0xc7,0x4b,0xaf,0x4e, + 0x64,0xa4,0xb2,0x38,0xd,0xa1,0x70,0x7d,0x23,0xb9,0x47,0x64,0x48,0xfa,0x21,0x29, + 0x9e,0xa5,0x74,0x88,0x45,0x8c,0x45,0x27,0x2d,0x13,0x74,0xf8,0x79,0xca,0x30,0x4f, + 0x96,0x64,0x69,0xdf,0xee,0x64,0xd4,0xa9,0x73,0x95,0x5a,0x42,0x77,0xe6,0x18,0x54, + 0xd0,0xac,0xd5,0x5e,0x69,0x12,0x91,0x87,0xed,0xf3,0x8d,0x3d,0x7c,0xf7,0x78,0xd, + 0x9d,0x8e,0x45,0x84,0x5e,0x38,0x97,0xc0,0xe4,0x10,0x54,0x2,0x3f,0x7b,0x45,0xe2, + 0x12,0x34,0x22,0x55,0xc,0x45,0x62,0x5,0xc7,0x93,0x30,0xf,0x79,0xb2,0xb6,0x8b, + 0x27,0xab,0x3b,0xac,0x20,0x2,0x27,0x1,0x50,0xf7,0x6e,0xde,0x50,0x30,0x85,0xfd, + 0x9b,0xf5,0xc,0x76,0xdf,0x60,0xda,0x0,0xed,0x91,0xef,0xdd,0x48,0x87,0x15,0x13, + 0xa7,0xc,0xf5,0xc4,0x10,0x22,0xa5,0x4c,0x20,0x49,0x54,0x74,0x3b,0xc6,0x30,0xa8, + 0x37,0xeb,0x55,0xbc,0x7e,0x6e,0x16,0xaf,0x9d,0x9d,0xe,0xd4,0x86,0x52,0x74,0x44, + 0x4e,0xaf,0xcc,0x8c,0xbb,0x4b,0xeb,0xf8,0xc5,0x97,0xf7,0xb1,0xbd,0x7b,0xc4,0x2, + 0xb2,0x66,0xe1,0xf,0xcc,0x94,0xf6,0xb5,0x1,0xce,0x72,0xd,0xb,0x53,0xd6,0x2a, + 0x73,0x1a,0x67,0x19,0x59,0x36,0xb4,0xe7,0xca,0x84,0x1f,0x2e,0x9d,0xac,0x2,0x13, + 0x90,0x34,0xb5,0x15,0x3e,0x9c,0x4e,0xaa,0x4f,0x18,0xc0,0xce,0x41,0xb,0x1f,0xde, + 0x7c,0x84,0x9f,0xbe,0x77,0x19,0xaf,0x9f,0x9b,0x41,0xfd,0x5,0xeb,0x85,0x70,0x1d, + 0x36,0xeb,0x55,0x2c,0xcc,0x8c,0xe1,0xc1,0xca,0x16,0xe,0x56,0xb6,0x2,0x91,0x5b, + 0x13,0xb2,0xb8,0xec,0x8c,0xcd,0x88,0x73,0xc9,0x42,0x40,0xa1,0x7d,0x9c,0x1,0xf5, + 0x81,0x6a,0x33,0x3a,0xdc,0x8f,0x6b,0xe7,0x66,0xb1,0x30,0x3d,0xfa,0x52,0x7,0xbf, + 0x0,0x5d,0x1f,0xb6,0x4e,0x70,0xf3,0xde,0x32,0xbe,0xb8,0xf3,0xd4,0xa9,0xd,0x48, + 0xdf,0x2,0xfa,0x4c,0x28,0x1e,0xef,0xf9,0xa,0x4a,0x66,0x41,0x84,0xaf,0xa9,0x54, + 0xc,0x9a,0xcd,0x1a,0x2e,0xce,0x4f,0xe2,0xa7,0xef,0x5d,0xc4,0x1f,0xbc,0x7b,0x11, + 0x57,0xbc,0xa9,0x8f,0x2c,0xe6,0x65,0x8a,0x14,0x79,0xff,0x86,0xfd,0xfa,0xd3,0xd5, + 0x1d,0x7c,0xf0,0xe9,0x3d,0xfe,0xc5,0x17,0xf7,0xb9,0xd5,0xee,0x78,0xba,0x15,0xa5, + 0x78,0xe,0xe3,0x93,0xa3,0xac,0x65,0xeb,0x8e,0x62,0xaf,0x48,0x77,0x8d,0xa3,0xf5, + 0x10,0xbc,0x5c,0x47,0x72,0xa0,0x66,0xc6,0xac,0x13,0x62,0x1d,0x47,0x4d,0xc8,0x17, + 0x96,0x85,0xd0,0xcd,0x2,0xe9,0xb1,0xe4,0x7d,0x95,0x83,0xb6,0x11,0x92,0x3e,0x52, + 0x4c,0xab,0xc4,0x6d,0xb,0xc6,0x32,0x85,0xc0,0x7,0x91,0xe9,0x25,0x19,0x74,0x2c, + 0xa0,0x13,0x96,0x64,0x86,0x4c,0x75,0x86,0x92,0x6e,0x8c,0xb,0x24,0x3d,0x51,0xc4, + 0xc,0xd2,0x85,0xac,0x24,0x5a,0x7e,0x9a,0xa,0xe8,0x6a,0x98,0x29,0xc5,0xbe,0x6, + 0x24,0xc3,0x53,0x22,0xdc,0x4f,0x79,0xb7,0x9a,0xac,0x43,0x85,0x5e,0xd8,0x18,0x1, + 0x12,0x86,0x2b,0x86,0x20,0x17,0xe3,0x62,0x31,0x2b,0x46,0x6c,0x9,0xc1,0x8b,0x69, + 0x90,0xe4,0xda,0xdb,0x50,0x59,0x7c,0x49,0x50,0x5a,0x2b,0x3d,0x3b,0x4a,0x26,0xa0, + 0x94,0x31,0xca,0xd2,0x12,0xaa,0xf0,0x4e,0x19,0xe1,0x6e,0x4,0x41,0xf4,0xd,0x6, + 0xdc,0x86,0xf4,0x4e,0xc2,0xcd,0x30,0x81,0xde,0x17,0x61,0x76,0xd5,0xa2,0x59,0xc9, + 0x94,0xe3,0xd2,0x9b,0x94,0xa,0xa9,0x7e,0x1e,0xa8,0x94,0x5b,0x30,0x45,0x2c,0x2e, + 0x88,0xfb,0xd4,0xe2,0x83,0xf2,0x6d,0x74,0xc,0x56,0x61,0xd2,0xe,0x72,0xc6,0xb8, + 0xd5,0xa6,0x9,0x2d,0x54,0x24,0xcc,0x25,0x17,0x78,0xa8,0x66,0x90,0x88,0xbd,0xbc, + 0xec,0xd5,0x3c,0xbe,0xe5,0x1,0x57,0xab,0x56,0x7d,0x42,0x9a,0xf0,0xc8,0xcf,0x50, + 0xf6,0x32,0xd1,0xd9,0xcb,0x5,0x40,0x9a,0x0,0xa7,0x29,0x8f,0xa4,0x8e,0xc2,0x94, + 0x99,0xc,0xf5,0x77,0x77,0xae,0x18,0x8,0xc0,0x45,0xb0,0x83,0x4d,0x50,0x59,0x80, + 0xad,0xdf,0x91,0x3b,0xd7,0x78,0x97,0xd8,0xc5,0x92,0x55,0x6d,0x88,0xc,0xb3,0xfb, + 0x12,0x8a,0xa,0x1e,0x2a,0x5c,0x98,0xd1,0x89,0x4f,0xef,0x3f,0xe5,0x2d,0x27,0x4d, + 0x1b,0x88,0x30,0x34,0xd0,0xc4,0xb9,0x53,0xe3,0x74,0x6a,0x6a,0xe4,0x95,0x5e,0x73, + 0x22,0xc2,0xfe,0x51,0x1b,0xf,0x96,0x36,0xf8,0xab,0xfb,0x2b,0x7c,0xd2,0xb1,0x69, + 0xa,0x27,0x82,0xb3,0xe9,0x8c,0x7,0x47,0x28,0xd6,0xc,0x36,0xbe,0xc0,0x73,0xb4, + 0x64,0x31,0x4c,0x2c,0x5f,0x39,0xdf,0xbd,0x26,0xb1,0xa8,0x60,0x9a,0x5,0x2,0x25, + 0x23,0xd1,0x5e,0x90,0x19,0x4a,0x84,0x68,0xa6,0x90,0x75,0x13,0x56,0x70,0x9,0xc1, + 0x25,0x1c,0x77,0xba,0xb8,0xfb,0x74,0xd,0xdf,0x3d,0x59,0xc7,0xa5,0x85,0x89,0x68, + 0x19,0xdb,0x8b,0x74,0x59,0x35,0x6,0xa3,0xc3,0x4d,0xc,0x34,0x6b,0xc8,0xfc,0x7f, + 0x4,0xf1,0x49,0x79,0xfc,0x15,0x52,0x22,0x3d,0x91,0x55,0xc5,0x18,0x43,0x6e,0x8, + 0x64,0xd8,0x86,0x61,0xd4,0x6b,0x15,0x9c,0x9e,0x1e,0xc5,0xe9,0xd9,0x31,0x34,0xeb, + 0xd5,0x57,0x6a,0x6e,0x4f,0x4e,0x3a,0x78,0xba,0xb6,0x8d,0xbb,0x4b,0x1b,0x58,0xdb, + 0x3e,0x54,0x90,0x37,0x97,0xad,0x9,0x4a,0x3e,0x1e,0xef,0x1b,0xa3,0x37,0xa6,0xb1, + 0xb0,0x19,0xc2,0xec,0xc4,0x30,0xfe,0xf4,0x47,0xaf,0xe3,0xc7,0x37,0xce,0xe3,0xec, + 0xfc,0x38,0xc6,0x6,0x9b,0xa5,0x6e,0x7c,0xbd,0x5e,0x53,0xd9,0x18,0x7e,0xf3,0x70, + 0x15,0xff,0xeb,0x7,0x5f,0xd8,0x8f,0xbe,0x7e,0xc8,0x7b,0x87,0x6d,0xce,0x74,0x9b, + 0xcc,0xd1,0x28,0xc2,0xef,0xca,0x99,0x18,0x30,0x1e,0x92,0x71,0xff,0x18,0x62,0xb6, + 0xd6,0x15,0x78,0xa7,0x58,0x73,0x0,0xa1,0x25,0xdf,0xd,0x4,0xbe,0x49,0xc9,0x92, + 0xb2,0xc8,0xa9,0xe1,0x17,0x22,0x9d,0x44,0x3d,0xd2,0xad,0xb,0x1b,0xc,0x99,0x37, + 0x62,0x40,0x2,0xb,0xe5,0xb8,0x43,0x2f,0xdc,0x6b,0x72,0xa3,0x5b,0xc,0x3a,0x29, + 0x88,0xb1,0x33,0x59,0x98,0xb6,0x4f,0xc9,0xa2,0x0,0x63,0xcd,0x36,0x8a,0xe1,0x98, + 0x34,0xef,0x94,0xb1,0x1f,0x65,0xb1,0xca,0xe4,0x27,0xd1,0x7e,0xd6,0x24,0x2a,0x4e, + 0x9a,0x17,0x33,0xfe,0x5d,0x30,0x35,0xf1,0xf6,0x6d,0x45,0x98,0x17,0xc1,0xff,0x3b, + 0x16,0x21,0xe1,0x70,0x29,0xa7,0x71,0x29,0xdc,0xa,0xae,0x66,0x1e,0xd6,0x8e,0x65, + 0x26,0x1a,0x96,0xb,0x8d,0x13,0x29,0xf6,0xbe,0x7e,0xab,0x55,0x34,0xaa,0xe1,0xe4, + 0xe,0xe4,0xc6,0x8,0x21,0x6d,0x62,0x21,0x5e,0x2b,0x51,0xfc,0x7,0x3d,0xa5,0xc9, + 0x38,0xbf,0x2,0x99,0xb0,0x32,0xf8,0x2f,0x5,0x31,0x86,0x9f,0xcd,0x2a,0xd5,0x27, + 0x9d,0x5,0x4a,0xc9,0x58,0xd8,0x2a,0x88,0xc2,0x9d,0x36,0x13,0x31,0x16,0x2a,0xcb, + 0xbd,0x53,0x1c,0xd7,0xa4,0xc2,0x91,0xcb,0x78,0xe7,0x5,0x9f,0x7e,0x94,0x63,0xd7, + 0x44,0x6e,0x7b,0x2c,0x32,0xc6,0x83,0xa0,0x46,0xe9,0xb,0xe3,0x55,0xd0,0x5,0xb0, + 0xb9,0x7b,0x88,0xf6,0x49,0x7,0xb5,0x6a,0xe5,0x95,0xcd,0x33,0x2e,0x2e,0x4c,0xe2, + 0x77,0xde,0x3c,0x87,0x5f,0xde,0x7c,0x80,0xfd,0xc3,0xe3,0x78,0x3d,0xe5,0xcc,0x58, + 0x53,0x16,0x3e,0x91,0xc1,0x8a,0x9c,0x39,0x3c,0x95,0xb1,0x12,0x54,0xd2,0x20,0xa0, + 0x88,0x90,0x52,0x12,0x24,0xcd,0x86,0xe2,0xb5,0xc3,0x99,0x44,0x48,0x62,0x39,0x4e, + 0xaf,0xef,0xd5,0x88,0x14,0x62,0x23,0x45,0x67,0xeb,0x8b,0xa0,0x71,0xa4,0x4e,0xca, + 0x91,0x7,0x79,0x4f,0x85,0x86,0xc6,0xa4,0xdc,0xb5,0x2,0x59,0x8b,0xa2,0x2b,0x1f, + 0x2e,0x2c,0x4c,0xd2,0xcc,0xd8,0x70,0xa1,0x68,0xe7,0xf2,0xa2,0x30,0x55,0xed,0x1d, + 0xb4,0xf0,0xd5,0xfd,0x15,0xdc,0x79,0xba,0x81,0x4e,0x57,0xaf,0xe0,0xc8,0x1f,0xbc, + 0x51,0x76,0x93,0x7e,0x22,0xa7,0x33,0x5f,0xa4,0x1f,0x90,0xed,0xb5,0x95,0x56,0x50, + 0x70,0xbc,0x98,0x42,0xeb,0xac,0x17,0x66,0x69,0x29,0x2f,0xb8,0x39,0x50,0x4a,0x37, + 0x51,0x70,0x2d,0x63,0x7d,0xe7,0x10,0xcf,0xb7,0xf6,0x70,0x7e,0x7e,0xa2,0xf4,0x5a, + 0x53,0xd3,0x25,0xb9,0x70,0x92,0x5a,0xad,0x26,0x1,0xf,0x69,0x6a,0x25,0x50,0x33, + 0x6f,0x38,0x92,0x3b,0x7b,0x2a,0x63,0x2d,0x92,0xb4,0x77,0x45,0xd2,0xa,0xa3,0xc5, + 0xf9,0xf9,0x49,0xbc,0x76,0x6e,0x6,0xc3,0xfd,0x8d,0x97,0xca,0x7,0xc3,0xe3,0x5f, + 0xd9,0xdc,0xc7,0x27,0xdf,0x3e,0xc5,0xd2,0xda,0x6e,0x81,0xc5,0x4b,0x78,0xc1,0x30, + 0xc7,0x45,0x42,0x9e,0xac,0x3,0xec,0x9,0x7a,0xa7,0x67,0x46,0x71,0x71,0x71,0x12, + 0x6f,0x9c,0x9f,0xc3,0xef,0xde,0x38,0x8b,0xd7,0xcf,0xcc,0x44,0x35,0x44,0x59,0x6c, + 0x70,0x59,0xf3,0x1d,0x57,0x53,0x27,0x1d,0xdc,0x7e,0xbc,0x86,0xff,0xf3,0xb7,0xb7, + 0xed,0xcf,0x3f,0xbb,0xc7,0x4f,0x57,0xf7,0xd8,0x9f,0x44,0x7e,0xa1,0x6d,0x53,0x43, + 0xe8,0x1a,0x40,0xa7,0xe8,0xf1,0x72,0x5d,0x2b,0x87,0x4d,0x22,0xc0,0x18,0x46,0x97, + 0xe3,0xb7,0x5b,0xf7,0x7d,0xee,0x7d,0xf1,0x3c,0x13,0x75,0xeb,0x67,0x7,0x9d,0x10, + 0xe,0x3,0xda,0xc5,0x3d,0x33,0x99,0xd2,0x94,0x73,0x52,0x1c,0x69,0x56,0xfe,0x66, + 0x80,0x50,0xd1,0x89,0x4e,0x90,0xc0,0xa8,0x6,0xb6,0x2b,0x97,0xd9,0xb5,0x66,0xc, + 0x35,0x39,0xa5,0x14,0x72,0xbb,0x15,0xc5,0x46,0xfc,0x17,0xc9,0x3d,0xaf,0x70,0x32, + 0x4b,0x79,0xa5,0x8e,0xbc,0x23,0x7f,0xa6,0x8c,0x13,0x94,0x9e,0x68,0x1e,0x56,0xd6, + 0x46,0xf5,0x26,0xda,0xc9,0xb3,0x62,0x1c,0x93,0x82,0xbe,0x93,0x34,0xca,0x7f,0x87, + 0x89,0xc5,0x59,0xe5,0x17,0x1a,0x16,0x1f,0x33,0x81,0x1,0xe1,0x67,0xd0,0xc0,0x6c, + 0x33,0x24,0x58,0xee,0x59,0x13,0x80,0x28,0x51,0x8c,0x12,0xb7,0x24,0xc0,0x30,0xa5, + 0x7b,0xd5,0xf4,0x46,0x4a,0x2a,0x1e,0x9,0x4c,0x5c,0x13,0xb,0x15,0xfa,0xc0,0x45, + 0xca,0xa0,0xfe,0x7a,0x56,0x8d,0x59,0x68,0xf,0x92,0x8d,0x93,0x71,0x93,0x4f,0xfa, + 0xd9,0xac,0x60,0x61,0x41,0x6e,0x4e,0x8c,0x7e,0x75,0x66,0x10,0x58,0xb2,0x8,0x49, + 0x7b,0xe7,0x46,0x1e,0xb4,0x51,0x4a,0x7c,0x31,0x80,0xf8,0xd7,0x49,0x3e,0x7c,0xdf, + 0xb2,0x18,0x8a,0x19,0xe6,0x21,0xfe,0x94,0x92,0xa9,0x3d,0x45,0xbb,0x3e,0x23,0x7, + 0x4a,0xed,0xc2,0x64,0xbb,0x8c,0x7,0xcf,0x36,0xf1,0x64,0x75,0x7,0x67,0x67,0xc7, + 0x50,0xad,0x9a,0x57,0xda,0xa1,0xbf,0xfb,0xda,0x22,0x4c,0xc5,0x60,0x65,0x63,0xf, + 0x5f,0xdc,0x5d,0x8e,0x5e,0x1,0xe9,0xf2,0x22,0x8d,0x9f,0x87,0x96,0xc8,0xe8,0x22, + 0xcd,0x46,0x9b,0x9,0x91,0xb4,0x6e,0xa3,0x32,0xda,0xa,0x69,0xe8,0x15,0x22,0x36, + 0x38,0xc7,0xe8,0xa4,0x54,0x51,0x89,0xf,0xc9,0x53,0x75,0x2,0xb2,0xcc,0xda,0xce, + 0x98,0x82,0x5e,0x96,0x93,0xfe,0x25,0xae,0xa5,0x73,0xf5,0x61,0x98,0x67,0x25,0x39, + 0x2e,0x5c,0xd0,0xc6,0x8b,0xec,0x63,0xc8,0x6d,0x6c,0x9c,0x17,0x67,0x46,0xf1,0xce, + 0x95,0x45,0xc,0xf9,0xc2,0xf1,0x32,0x6,0x35,0x0,0x6c,0xed,0x1d,0xe1,0xe7,0x5f, + 0xdc,0xe7,0xbb,0x4f,0xd6,0x3c,0x41,0x8d,0xa4,0xd8,0x38,0xd5,0x71,0x8e,0x6a,0x7a, + 0x46,0xcc,0xb7,0xf2,0x19,0x1b,0x3a,0x8,0xa2,0x7,0x0,0xec,0xc5,0x86,0x24,0xe3, + 0x95,0xd2,0xb1,0x8,0x12,0xf3,0xad,0x8c,0xb,0xe4,0x38,0xcc,0xfb,0xb7,0x34,0x28, + 0xf0,0x63,0xcc,0x2c,0x8e,0x4f,0x3a,0x38,0x6e,0x77,0x5f,0xba,0xe2,0x61,0x29,0x57, + 0x2c,0xac,0x31,0x25,0xb,0x4a,0xc0,0xd9,0x4c,0x99,0x62,0x88,0xd3,0x2,0x1b,0x3d, + 0x1c,0x5a,0xc4,0x7b,0x5e,0x31,0x84,0x6b,0xe7,0xe7,0xf0,0xf6,0xe5,0x53,0xa8,0x54, + 0x2a,0x2f,0x7d,0x5f,0xc2,0xe7,0x1e,0x3f,0xdf,0xc2,0x7,0x9f,0xde,0xc3,0xfa,0xf6, + 0x41,0x99,0x2c,0xa7,0x88,0x3e,0x21,0xdf,0x2b,0x89,0xe9,0x20,0x83,0x21,0x4e,0xcf, + 0x8e,0xe1,0x5f,0xfe,0xf0,0x35,0xfc,0xfe,0xdb,0xe7,0x71,0xe3,0xe2,0xbc,0xa,0x57, + 0x51,0x31,0xd,0xaf,0x20,0x4f,0x23,0x22,0x3c,0x58,0xd9,0xc2,0xff,0xf2,0x9f,0x3f, + 0xb3,0x1f,0x7e,0xf5,0x90,0x97,0xd6,0x76,0x3d,0x46,0xef,0x5f,0x2f,0x6b,0xd9,0xe1, + 0xec,0x96,0xa3,0x52,0xce,0xaf,0x6c,0xa2,0x5c,0x31,0x6,0x93,0xc4,0xf8,0xf9,0x24, + 0x19,0x61,0x62,0x81,0xd0,0xe8,0x2,0xce,0x19,0x29,0x90,0x23,0x1d,0x5b,0xc,0x5e, + 0x26,0x26,0xb1,0xe9,0x89,0x32,0x15,0x7d,0x2a,0x49,0x6e,0xa2,0xcc,0xa0,0x2d,0x20, + 0xd6,0x51,0x65,0x16,0xcd,0xc1,0x8,0x55,0x2e,0x13,0xfe,0x73,0xbe,0xfe,0xa6,0x82, + 0x99,0x9b,0x36,0xae,0xcb,0xe2,0x33,0x73,0xa,0x50,0x61,0x72,0x28,0x28,0xf7,0x5, + 0xa,0x29,0xf2,0xc2,0xc4,0xc1,0x4c,0x99,0x66,0x5b,0x6,0xa3,0x73,0x20,0x3a,0x4b, + 0xa6,0xa0,0x21,0xd2,0xc4,0x3d,0xa1,0xa9,0x91,0x24,0xf7,0xa8,0xad,0xf2,0xac,0x74, + 0xa3,0x27,0x70,0x57,0x63,0xbd,0xc7,0xb8,0x64,0x62,0x83,0xa2,0x76,0x9a,0xc4,0xa4, + 0x1f,0xa,0x1e,0xc7,0xfd,0xb9,0x49,0x50,0x7c,0x4e,0x5c,0x2b,0x70,0x5,0x42,0x71, + 0x37,0xa2,0x79,0x4a,0xfd,0x9d,0x2d,0x43,0x63,0x48,0x13,0x53,0x20,0xf2,0xda,0xb3, + 0x51,0xce,0x4f,0xda,0xee,0xe7,0x43,0xfa,0x6a,0x55,0xd2,0x45,0xe9,0x77,0x72,0xac, + 0x7c,0x83,0x8d,0x36,0x6f,0x54,0x2,0xc6,0x80,0xb7,0x1b,0x29,0x5d,0xf6,0x5c,0x22, + 0xaa,0x90,0xba,0x99,0x41,0x99,0xd3,0x0,0xe9,0x19,0x90,0x85,0x27,0x3c,0x55,0xc4, + 0x62,0x97,0x92,0x43,0x5c,0x2c,0x28,0x86,0xa,0xb,0xa9,0x38,0xb8,0x9b,0x78,0xcf, + 0xb4,0xbb,0x8c,0x5b,0xf,0x56,0xf8,0xec,0xdc,0x38,0xce,0xcd,0x8d,0xd1,0xcb,0xa2, + 0x25,0xc3,0x61,0x32,0x32,0xd8,0x87,0x37,0xce,0xcd,0xe1,0xbf,0xff,0x93,0xef,0xe1, + 0x6f,0x3e,0xbe,0x83,0xbf,0xfe,0xf8,0x2e,0xda,0xed,0x4e,0xd1,0x66,0x58,0x5d,0x9b, + 0x5c,0xe8,0x56,0x48,0xde,0x48,0xc9,0xd4,0xb,0x5,0x1f,0x68,0xc1,0x77,0x70,0xcd, + 0x93,0xf8,0x1d,0xa6,0xe4,0x8e,0x93,0x8a,0x3f,0x65,0x25,0x16,0xf3,0x9e,0x5,0xd, + 0x51,0xfa,0x4c,0x27,0xc2,0x23,0xc5,0xa9,0x3c,0x2c,0xa8,0x35,0xc1,0x29,0xbe,0xbd, + 0xe9,0xba,0xf,0x4c,0x13,0x4d,0x98,0x35,0x89,0xdc,0xe8,0xff,0x4e,0xf3,0x53,0xfb, + 0xd5,0x81,0xf3,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x23,0xf4,0xce,0x6b,0xb, + 0x34,0xea,0x75,0xf3,0xbd,0xa,0x9c,0xdc,0x8d,0xae,0xed,0x1c,0xe0,0xa3,0x5b,0x4f, + 0xf0,0xf0,0xf9,0x8e,0xe8,0x5a,0x39,0x45,0x1e,0x89,0x75,0x3e,0x9c,0xfd,0x5b,0x98, + 0x96,0xd8,0x9f,0x6c,0x1c,0xe8,0xa4,0x89,0xb0,0xe6,0xcd,0x34,0x29,0x13,0x77,0x85, + 0x62,0x6a,0x84,0x2e,0x87,0xa8,0xe8,0xc5,0x99,0x65,0x15,0x45,0x21,0x6,0x5,0xde, + 0x8a,0xf0,0x6a,0x20,0x83,0x5a,0xb5,0x82,0x7a,0xed,0xe5,0x5a,0x7b,0x0,0xe8,0x74, + 0xbb,0xd8,0x3f,0x6a,0xa3,0x75,0xd2,0xd5,0x36,0xcf,0xe2,0xf7,0x28,0xde,0x46,0xbe, + 0x6b,0x55,0xab,0xf,0x2e,0x49,0xb7,0x12,0xc8,0x27,0x18,0x15,0x63,0xf0,0xda,0xe9, + 0x69,0x5c,0x3b,0x37,0x8b,0x7a,0x95,0x5e,0xda,0x64,0x31,0x33,0xba,0xdd,0x2e,0x1e, + 0x2c,0x6f,0xe1,0xcb,0x7b,0xcb,0xd8,0x3e,0x3c,0x2e,0x38,0xc4,0x94,0xa5,0xa9,0x15, + 0x6d,0x8d,0x49,0xf9,0x9c,0xf4,0x35,0xaa,0x78,0xfd,0xec,0x2c,0xde,0xbe,0x3c,0x8f, + 0x6b,0xe7,0x66,0x70,0xf1,0xd4,0x4,0x4e,0xf9,0xf8,0xe2,0xdc,0xfd,0xb0,0x97,0x9e, + 0x3f,0xff,0xd8,0xea,0xd6,0x3e,0x3e,0xfc,0xea,0x21,0xff,0xe2,0x8b,0x87,0xfc,0xc9, + 0xb7,0x4f,0x78,0x79,0x63,0x4f,0x23,0x3a,0x9e,0x95,0x1e,0x98,0xec,0x89,0x99,0xce, + 0xec,0x67,0xce,0xb8,0x43,0xf,0xff,0x8b,0x1f,0x83,0x61,0x27,0xe7,0xc,0x96,0x22, + 0x4,0xee,0x5a,0xff,0x39,0xcf,0xb2,0x33,0x41,0xfa,0x23,0x10,0x6a,0xd6,0xe1,0x86, + 0x72,0xdd,0x56,0xac,0x9f,0xd4,0xa3,0xf,0xd3,0x23,0x61,0x44,0xd1,0xc,0x65,0x21, + 0x68,0xee,0x7a,0xa9,0xca,0xd8,0x4f,0xbd,0x94,0x27,0x15,0xbe,0x6e,0xe2,0xce,0x8e, + 0xb,0x72,0x1d,0x15,0xd9,0x59,0xec,0x86,0x63,0xd6,0x58,0x94,0x37,0xc8,0x7a,0xc, + 0x2a,0xa0,0x7b,0x2c,0x8b,0x3b,0x65,0xa4,0x21,0xd5,0xc8,0x66,0x6e,0x38,0x62,0x12, + 0x97,0x2e,0xee,0x6a,0xd,0x6f,0x48,0xee,0xc3,0x53,0xe4,0x88,0x30,0x36,0x9,0xfb, + 0x59,0x3f,0x90,0x53,0xc8,0x88,0x44,0xf2,0xcc,0x8a,0x2b,0xf6,0x50,0x67,0x38,0x4a, + 0x7e,0x82,0x4f,0x9a,0x89,0xe9,0xed,0xa4,0x21,0xbe,0x82,0x8f,0x5b,0x1e,0xcb,0xea, + 0xf0,0x51,0x83,0xcc,0xea,0x47,0xf4,0x6f,0x7a,0xbc,0x33,0x65,0x4,0x45,0x94,0x10, + 0xac,0x85,0x74,0xd2,0x5d,0xce,0xcc,0x9a,0x14,0x21,0xdf,0xf,0xcb,0xe5,0xdc,0x6, + 0x35,0x73,0x93,0x30,0x43,0xf0,0x1c,0x10,0x56,0x5c,0x68,0xf9,0x0,0x49,0xb,0x57, + 0xd2,0x8a,0x41,0x66,0xd6,0x32,0x9,0x2e,0x24,0x91,0x49,0xdb,0x91,0xf0,0xc6,0xf9, + 0x0,0x10,0x99,0xc8,0x96,0x27,0xf6,0x24,0x72,0x76,0xb7,0x6b,0xf1,0xed,0xa3,0x35, + 0x9c,0x3b,0xb5,0x8a,0x9f,0xbc,0x7d,0x1,0x3,0x7d,0xf5,0x82,0x36,0xb8,0x8c,0x2d, + 0x4b,0x44,0x98,0x1c,0x1d,0xc0,0x1f,0x7e,0xef,0x32,0x6,0xfa,0xea,0xd8,0x39,0x68, + 0xe1,0x9b,0xc7,0x6b,0xd8,0xde,0x39,0x84,0x2d,0x75,0x14,0xa6,0xf2,0xbf,0x1b,0x14, + 0xac,0x8d,0x23,0x99,0xc3,0x10,0xb4,0xff,0xa5,0xbc,0x31,0xa2,0x98,0x3c,0x39,0xdb, + 0x32,0x40,0xb0,0x1a,0x4,0x89,0x13,0x9d,0x74,0x36,0x33,0xe5,0x47,0x85,0x47,0x53, + 0x22,0x13,0x3c,0x51,0x6b,0x54,0x9a,0x0,0x93,0x6a,0xb5,0xd2,0x2b,0x4a,0xb1,0xd1, + 0x75,0x9c,0x5,0x83,0x10,0x51,0xa1,0xbe,0x8,0x0,0xe6,0xa7,0x46,0x70,0x79,0x71, + 0xa,0x83,0x7d,0xf5,0xd2,0xc3,0x59,0x1e,0xcc,0xd6,0x5a,0x1c,0x1c,0x9d,0xe0,0xc1, + 0xf2,0x6,0x3f,0x5c,0xde,0xe4,0x8e,0xb5,0xa2,0x6d,0xa4,0x48,0xfc,0xf0,0xdd,0x18, + 0xfb,0x63,0x95,0x3d,0xd2,0xc0,0xfe,0x25,0x89,0xc,0x78,0x75,0xe3,0xf9,0x3,0x5d, + 0x1d,0x98,0xe1,0x21,0x1b,0x71,0xea,0x51,0x26,0xb,0x21,0xea,0x41,0xcd,0x26,0x81, + 0x8c,0x49,0x12,0xaa,0xfb,0xd6,0xc1,0xbe,0x3e,0x8c,0xc,0x34,0x51,0xa9,0xf4,0xe6, + 0x6b,0xc4,0xdd,0x74,0xa7,0x8b,0xd5,0xed,0x7d,0xec,0x7a,0xb,0x55,0xca,0xe6,0x33, + 0xbd,0x72,0xc8,0xa2,0x13,0xb2,0xf3,0xb2,0xd4,0x6a,0x4d,0x7d,0x2f,0x61,0x6a,0x74, + 0x10,0x8b,0xb3,0x23,0x18,0x13,0x4d,0x56,0xaf,0x49,0xd7,0x85,0xfd,0x74,0xf0,0x78, + 0x75,0x7,0xf7,0x9e,0x6d,0x38,0x69,0x5d,0xc6,0xa8,0xe7,0x8c,0xce,0xa9,0x56,0x19, + 0xd9,0xdf,0xab,0xd5,0xa,0xfa,0x1b,0x35,0xf4,0x37,0xab,0xb8,0xb2,0x38,0x85,0x1f, + 0x5c,0x3b,0x83,0x9f,0xbc,0x7d,0xe,0x17,0x4e,0x4d,0x16,0x82,0x7b,0xca,0xa0,0xf4, + 0x9c,0xdd,0x1e,0xbe,0xe6,0xa0,0x75,0x82,0x67,0xeb,0x3b,0xb8,0x79,0x6f,0x99,0xff, + 0xf2,0xe7,0xb7,0xf8,0xb7,0xb7,0x9e,0xb0,0xb5,0x96,0x39,0xa6,0xa,0x7a,0x5a,0x88, + 0x33,0xfa,0x67,0x61,0x93,0x12,0x4c,0x59,0xd9,0x8f,0xb7,0x42,0xa3,0x1e,0xbc,0xd2, + 0x2,0x1a,0xc4,0x21,0x2e,0x83,0xfd,0x6a,0x85,0x9d,0xca,0xc3,0x22,0xb,0xfb,0xe4, + 0x8,0xe1,0xc0,0x4a,0xb,0x26,0x8e,0xdd,0xb0,0x70,0x8f,0xd4,0x5e,0x9a,0x5,0x56, + 0x41,0x36,0x1c,0xa7,0xb5,0x4b,0xd1,0x2b,0x38,0x7d,0x7d,0x35,0xdd,0x34,0x48,0x16, + 0x74,0xc1,0xdd,0xcc,0x18,0xc1,0xa4,0x23,0xd,0x37,0x82,0xb,0xce,0x3f,0x54,0x48, + 0xca,0x96,0x7c,0x5b,0x52,0x11,0x2d,0x39,0xa5,0x93,0x4a,0xe4,0xd,0xda,0x4a,0x96, + 0x4b,0x28,0x5a,0xfa,0x3,0x61,0x52,0x90,0x73,0x93,0x4,0x34,0x5d,0x30,0x49,0x18, + 0x31,0xa2,0x3b,0x49,0x4,0x17,0x7d,0x49,0xf6,0xc5,0xdb,0xb,0xa1,0x42,0x82,0x94, + 0xd8,0x9d,0x27,0x77,0xc8,0x8,0xf7,0xfa,0xda,0x62,0x28,0xdd,0x5e,0x26,0x0,0x77, + 0x24,0x5f,0x17,0xa7,0xb5,0x62,0x21,0x1,0xe2,0x2,0x3f,0x81,0x39,0x1a,0xe8,0xeb, + 0x1d,0x39,0x67,0x3,0x69,0xf9,0xda,0x56,0xab,0xc7,0x25,0x14,0x2a,0x16,0x10,0x14, + 0x96,0x7e,0x8,0x4f,0x83,0x33,0x13,0xa7,0x2a,0x2,0xe9,0x83,0xe5,0x16,0x43,0xb6, + 0x6e,0x81,0x1b,0x5f,0xa1,0x6c,0xb5,0x90,0x42,0x57,0x22,0x54,0xad,0xba,0x33,0x2e, + 0x34,0x83,0x1e,0xb8,0x8c,0x7b,0x42,0x87,0x88,0x84,0x36,0xc9,0x63,0xaf,0x89,0xa0, + 0x48,0x85,0xa9,0x5c,0x61,0xb4,0xe9,0x51,0x74,0x19,0x78,0xb2,0xba,0xcd,0xb7,0x1f, + 0xad,0x61,0x75,0x6b,0x9f,0xce,0xf7,0x4f,0xc4,0xe7,0x9f,0x67,0x6e,0xe7,0x85,0x86, + 0x99,0xd1,0xd7,0xa8,0xe1,0xfd,0xab,0xa7,0x31,0x3b,0x3e,0x8c,0xff,0xfd,0xc3,0x6f, + 0xf0,0x9f,0x7e,0x7d,0x1b,0x4f,0xd7,0xb6,0x4b,0x56,0x4d,0x10,0x8e,0xf,0xd9,0xd8, + 0x62,0x4a,0x18,0x74,0xa1,0xe5,0x34,0xe2,0x7b,0x2,0x3,0xca,0x88,0x35,0x57,0x89, + 0xa7,0x3f,0x95,0xb8,0x80,0x15,0xb8,0x95,0x32,0x99,0xc4,0xb0,0xce,0x99,0xc8,0x5e, + 0x7e,0xca,0xb6,0xfa,0x69,0x33,0x48,0x9a,0xcb,0x2e,0x9b,0xb5,0x38,0xa9,0xba,0x66, + 0xce,0xf5,0x27,0xee,0x7,0xf,0xf,0x34,0x31,0x37,0x31,0x8c,0x69,0x6f,0x5a,0xf2, + 0x32,0x98,0xb4,0xdb,0xb5,0xf8,0xec,0xee,0x12,0x3e,0xfd,0x76,0x9,0xed,0x8e,0x8d, + 0x6f,0x63,0x6a,0x3b,0xa2,0xdc,0x86,0x83,0xf4,0xc4,0x8f,0x55,0x69,0xd2,0xa,0x7c, + 0x77,0xe1,0x70,0x2c,0x41,0x40,0x9d,0x40,0x2d,0x88,0x1e,0x49,0xcf,0x87,0x60,0x85, + 0xc7,0x92,0x75,0x43,0x62,0x3,0x4c,0x22,0x2a,0x43,0xbd,0x1a,0xe1,0xcb,0xc,0x4f, + 0x8c,0xf6,0xd3,0xe4,0xc8,0x0,0x2a,0x3d,0xa0,0x62,0x59,0xe4,0xdb,0x1d,0x8b,0xc7, + 0xcf,0xb7,0xb1,0xb9,0x7b,0x98,0xf6,0xf3,0xdc,0x63,0x2f,0x2d,0xed,0x41,0x65,0x7a, + 0xa2,0x56,0xb,0xa,0x98,0x4c,0x5f,0x6e,0x53,0x23,0x3,0xb8,0x7e,0x71,0x1e,0x13, + 0xc3,0xfd,0x2f,0x9c,0x80,0xe5,0xc7,0x77,0xe,0x8e,0xf1,0x8b,0x2f,0x1e,0xe0,0x9b, + 0x47,0xeb,0x6e,0x35,0x97,0xe9,0xaa,0x88,0x72,0xd2,0xad,0xb8,0xa8,0x4,0x1,0x87, + 0x88,0x71,0x76,0x6e,0xc,0xdf,0x7b,0x6d,0x1,0x3f,0x7c,0xe3,0xc,0xce,0xcd,0x8d, + 0x61,0x72,0x64,0x0,0x83,0xcd,0x5a,0x61,0xe2,0x7e,0x55,0x8e,0xb,0x0,0x1c,0x1e, + 0x9f,0xe0,0xef,0x3e,0xbd,0xc7,0x7f,0xff,0xf9,0x7d,0xfe,0xe8,0xd6,0x63,0xde,0xdc, + 0x3d,0x82,0xf5,0x90,0x79,0xf2,0xd5,0x40,0x9c,0xc2,0x3,0x5,0x8a,0x3d,0xa2,0xe3, + 0x4b,0xb,0x33,0x47,0x67,0x76,0x3f,0xa5,0x3b,0xf7,0x6,0x2,0xb1,0xb5,0x22,0x7e, + 0xc1,0x4d,0xb8,0xec,0x12,0x55,0xbb,0x4c,0x8,0x4d,0x42,0x88,0x2e,0xc,0xe6,0x47, + 0x96,0xbd,0x8c,0x57,0xe0,0xd6,0xac,0x58,0x81,0x92,0xb,0x91,0x5c,0x3c,0x65,0x31, + 0x37,0x4a,0x72,0x29,0x51,0x8f,0x32,0xee,0x54,0x90,0xc7,0x55,0x63,0xa6,0xb7,0x94, + 0x7c,0xab,0xe0,0x2c,0xa3,0xa5,0x6c,0x8a,0x8,0x23,0xa2,0x56,0x23,0x3c,0xa4,0x95, + 0xf0,0xc4,0x54,0x70,0x9d,0x2b,0x10,0x69,0xb4,0x18,0x4b,0x6d,0x9a,0x55,0x5e,0x4a, + 0x96,0x3,0xa5,0xa0,0x66,0x88,0x9d,0xb8,0x1e,0xdf,0xd3,0x38,0x6e,0x42,0x26,0x85, + 0xa1,0x24,0x95,0x4a,0x3b,0xf1,0x8a,0x9f,0x48,0x7c,0x30,0x88,0x49,0x70,0xbb,0x1b, + 0x15,0x3,0x45,0x1,0xc6,0x50,0x1c,0x76,0x4d,0x70,0x6d,0x37,0x71,0x65,0x1d,0xa7, + 0x75,0xca,0x37,0x5b,0x9e,0xde,0x60,0x4c,0x46,0xa4,0x2a,0x4e,0x8a,0x1,0x1b,0xa6, + 0x1e,0x70,0x56,0x8e,0x81,0x8,0xba,0x5d,0x49,0x58,0x86,0x9c,0xc,0x84,0x74,0x91, + 0x2b,0x9c,0x95,0x7f,0xd6,0xeb,0x9a,0xa,0xb4,0xd7,0x3f,0x4,0x43,0x3f,0x9d,0xed, + 0xc6,0x4,0x36,0x11,0xc5,0x41,0x8a,0x84,0x9d,0x2e,0x15,0xfa,0xab,0x4,0xc3,0xb3, + 0x98,0x5,0xf3,0xc2,0x92,0x82,0xb7,0x13,0xc1,0x4e,0x4a,0x2f,0xa2,0x5c,0x8a,0xd5, + 0x6e,0x29,0xb2,0xeb,0x92,0x69,0x83,0xc1,0xc3,0x95,0x4d,0xfc,0xfc,0xcb,0x7,0x5c, + 0xa9,0x10,0x9d,0x9e,0x19,0xeb,0x79,0x60,0xe4,0x6,0x20,0xcc,0x8c,0x81,0xbe,0x3a, + 0x5e,0x3f,0x37,0x83,0x93,0x4e,0x17,0xfd,0xcd,0x3a,0x6e,0xde,0x5f,0xc6,0xbd,0xa7, + 0x1b,0x58,0xde,0xdc,0x43,0xbb,0xd3,0xcd,0xa6,0xa3,0x62,0xfe,0xd,0xca,0x98,0xab, + 0x25,0x3a,0x96,0xb2,0x78,0x45,0x29,0xdf,0xf7,0x10,0x71,0x21,0xb3,0x27,0xec,0xc2, + 0x39,0x1b,0xe1,0xfc,0xe1,0x25,0x13,0x9b,0x3,0x99,0xc7,0x83,0x33,0xe4,0x78,0x64, + 0x16,0xea,0x64,0x17,0xcb,0x15,0x21,0xd9,0xc,0x93,0x5b,0x48,0x56,0xf3,0x11,0xb5, + 0xe1,0x75,0xab,0xb8,0xa,0x37,0xd0,0xac,0xd1,0xc5,0xc5,0x49,0x9c,0x9a,0x1a,0x29, + 0xd5,0x7,0x97,0xfd,0xe9,0x58,0xc6,0x97,0x77,0x56,0xf8,0xb3,0x3b,0xcb,0xdc,0x8d, + 0x9a,0xf4,0x4,0xad,0x53,0x68,0x7a,0x52,0xac,0xa8,0x23,0xc0,0xf9,0x3,0x16,0x86, + 0x99,0xa3,0x6f,0xb6,0xe5,0xb8,0xf5,0xe2,0xc2,0x66,0xcf,0x95,0x45,0x3f,0xa7,0xb9, + 0x79,0x22,0x2a,0x34,0x64,0xe4,0x32,0x27,0x67,0xc3,0x2,0x49,0x37,0xb9,0x92,0x92, + 0x26,0x2a,0x56,0xab,0x15,0xcc,0x8c,0xd,0x62,0x7a,0x6c,0xd0,0xfb,0xd1,0xbc,0x78, + 0xc5,0xb0,0xb2,0xb9,0x87,0xb5,0xed,0x7d,0x74,0xac,0x60,0x1e,0x11,0x95,0x2f,0xc0, + 0x33,0xb9,0xa4,0x41,0x51,0x83,0x6c,0x32,0x9c,0x54,0x2e,0xf5,0xa6,0xc7,0x6,0x71, + 0xe3,0xe2,0x5c,0xd4,0xc8,0xe7,0xc4,0xb7,0xb2,0xc7,0xb7,0xbd,0xdf,0xc2,0x6f,0xbf, + 0x7d,0x8a,0xfb,0xcf,0x36,0xf5,0x2f,0xa5,0x12,0xd4,0x42,0x6,0x93,0x30,0xa3,0x56, + 0x33,0x98,0x19,0x1f,0xc2,0xec,0xf8,0x10,0xe6,0x27,0x86,0x71,0xe5,0xf4,0x24,0xae, + 0x9d,0x9d,0xc1,0xf5,0xb,0xb3,0x18,0xf0,0xa8,0x4d,0x59,0x4e,0x7b,0x19,0x61,0x32, + 0xdf,0xe9,0xef,0x1f,0x1e,0xe3,0xe1,0xca,0x16,0x6e,0xde,0x5b,0xe1,0x5f,0xde,0x7c, + 0xc8,0x9f,0x7e,0xb7,0xc4,0x1b,0x3b,0x87,0xbe,0xed,0x8b,0xd5,0x80,0x7d,0xb,0x14, + 0xb2,0xd0,0x1c,0x74,0xee,0xaa,0x2d,0x13,0xb3,0x25,0xa2,0xc8,0x62,0x7,0x60,0xbd, + 0x9,0xb0,0x37,0xe1,0xf4,0xa1,0xaa,0x6,0xec,0xba,0x84,0x30,0xa5,0xbb,0x17,0x87, + 0x4,0x5f,0x27,0xd8,0x97,0xe5,0xaa,0x25,0x4a,0x53,0x72,0xec,0xd2,0xd3,0x31,0x2a, + 0x1c,0xe4,0xa,0xe6,0x6a,0x22,0x8c,0xc5,0x94,0x46,0x9d,0x95,0xcc,0xee,0x21,0x3e, + 0x95,0x48,0xec,0xfb,0x32,0x2d,0x77,0xb6,0xa0,0x95,0xec,0x5b,0x96,0xbe,0xb3,0x62, + 0xe0,0x4e,0xec,0x5c,0xb1,0x43,0x20,0x2a,0x4c,0x99,0xc5,0xa0,0x7b,0xf9,0xf0,0x62, + 0x6e,0x44,0x89,0xdd,0x66,0xf6,0xdc,0xbd,0x4,0x4d,0xce,0xef,0x4c,0x4c,0x22,0x32, + 0x24,0xa6,0xd6,0xb3,0xdf,0x93,0x1b,0x5,0xa5,0x7,0xe8,0xb6,0x22,0x8a,0x79,0x80, + 0x16,0x89,0x60,0x60,0x1c,0x7c,0x9e,0x52,0xba,0xa3,0x83,0x21,0x85,0xc2,0xee,0x27, + 0x47,0x91,0xdb,0xa9,0x9,0x5e,0x42,0xa3,0xc5,0x2c,0xf0,0x7f,0x56,0x7a,0x7f,0x65, + 0xfa,0x11,0xe0,0x26,0x71,0xc5,0xe7,0xda,0xe5,0xa2,0x60,0xa2,0x87,0xfe,0x53,0x7e, + 0xd,0xe9,0x40,0x5c,0x72,0x62,0x4c,0x21,0x48,0xe3,0xcc,0x17,0x5b,0x2b,0xe,0x74, + 0x87,0x95,0x88,0x6f,0xc2,0x7c,0x25,0xf4,0x74,0xee,0x5f,0xa1,0x43,0x54,0x4,0xd, + 0x23,0x61,0x78,0xe4,0xce,0x3,0x5c,0x4c,0xb7,0xcd,0x46,0x80,0x28,0x8e,0x16,0xba, + 0x67,0x3f,0x9f,0x18,0x29,0x82,0x4b,0x27,0xdb,0xea,0xf6,0x1,0xfe,0xfd,0x2f,0x6f, + 0xf1,0xc4,0x70,0x3f,0xce,0xcc,0x8e,0x93,0xc,0x1,0x79,0xd9,0x24,0x10,0xde,0x86, + 0x37,0x2f,0xce,0xe1,0xca,0x99,0x29,0xdc,0xbc,0xb7,0x82,0x5f,0xdc,0x7c,0x88,0xf, + 0x3e,0xb9,0x8b,0xc7,0xcf,0xb7,0x71,0x78,0xdc,0xc9,0x90,0xa7,0x30,0x41,0x73,0x16, + 0x87,0x9a,0xa7,0x45,0x67,0xa8,0x93,0xec,0x77,0xf2,0x17,0x47,0x2a,0xf,0xa3,0xa6, + 0x42,0x92,0x3d,0x3d,0xc7,0x5b,0xb8,0xa,0x22,0x5e,0xf8,0x16,0x11,0x30,0xb2,0xc6, + 0x77,0x0,0x51,0xa4,0xc1,0xa8,0xc8,0x7e,0x33,0x8f,0x8e,0x11,0x4a,0x83,0xe8,0x27, + 0x60,0x22,0x99,0x35,0x67,0xf5,0xd,0xd,0x34,0xf1,0xd6,0xa5,0x39,0x9a,0x9f,0x1c, + 0xa6,0x5e,0x39,0xe1,0xf2,0x80,0x66,0x66,0xec,0x1d,0x1e,0xe3,0xd6,0xa3,0xe7,0xb8, + 0xbf,0xbc,0x11,0xf9,0x24,0xc,0x99,0xcb,0x99,0xa6,0x70,0xe,0xb1,0xf,0x94,0x18, + 0x1f,0x6e,0x6a,0x42,0xf4,0xdd,0x26,0x39,0xa4,0xc6,0x6f,0x77,0x63,0xbd,0x21,0xcf, + 0x6c,0x22,0xed,0x98,0xec,0x8f,0xd,0x61,0x14,0x15,0x18,0xfb,0xb2,0x33,0xa4,0x88, + 0xb8,0x28,0x53,0x69,0xdf,0xdb,0x8e,0xe,0x36,0x31,0x3d,0x3e,0x88,0xc1,0x17,0x30, + 0xc8,0x89,0x8,0x9d,0x4e,0x7,0x4f,0xd6,0x76,0xf1,0xdd,0x93,0x75,0xec,0x1e,0x9e, + 0x40,0x27,0xad,0x94,0xde,0xb5,0x45,0x49,0x1b,0x65,0x3a,0x66,0x92,0x24,0x59,0x28, + 0x4f,0x75,0x0,0x98,0x9d,0x18,0xc6,0xf5,0xf3,0xb3,0x18,0x1d,0xe8,0x2b,0x14,0xc8, + 0x32,0x86,0x3b,0x33,0x63,0x79,0x63,0x17,0xdf,0x3c,0x5e,0xc3,0xde,0x51,0x3b,0xc5, + 0x78,0xaa,0xf7,0x52,0xc2,0x49,0x89,0xac,0x55,0xaf,0x57,0xb0,0x38,0x3d,0x82,0x1f, + 0x5c,0x3b,0x8d,0xdf,0x79,0xe3,0xc,0x6e,0x5c,0x9c,0xc3,0x48,0x7f,0x23,0x32,0xd7, + 0x15,0xf,0xf9,0x25,0xe,0x75,0x39,0xff,0x62,0xef,0xe0,0x18,0x77,0x9f,0xad,0xe3, + 0x7f,0xfb,0xe0,0x2b,0xfe,0xbb,0xcf,0xef,0xdb,0xcd,0x9d,0x43,0x74,0x39,0x7a,0x27, + 0x25,0xde,0x85,0xe7,0x54,0x70,0x84,0xd2,0x5d,0x3,0xe8,0xaf,0x16,0xcf,0x19,0x65, + 0x76,0x92,0x4d,0xa,0x45,0xdf,0x46,0x8,0xde,0xc9,0x77,0x93,0xb4,0xcd,0x2d,0xda, + 0x98,0xc4,0x2f,0x71,0x1c,0x6d,0x83,0xb8,0x49,0xf,0x6f,0x8e,0xb1,0x2a,0x4a,0x47, + 0xda,0x32,0x92,0xe8,0xc8,0x88,0x65,0x2e,0x3a,0x94,0xbf,0x4a,0xd0,0x41,0xb,0x8b, + 0x81,0xa2,0xba,0x41,0x62,0x30,0xfe,0x12,0xad,0x92,0xd1,0x3f,0x91,0x24,0xc6,0x1f, + 0xf7,0x9f,0xc2,0xb4,0x44,0x25,0x6f,0xa,0x5f,0xf5,0x58,0xda,0x34,0x6,0x48,0xe5, + 0x2b,0x21,0x2d,0xff,0x29,0xcb,0x39,0xcf,0x2c,0x2a,0xf3,0x76,0x50,0x1c,0x37,0x62, + 0xa3,0x9b,0xc0,0xb2,0x24,0x3b,0xb,0x93,0x9d,0x21,0x13,0xaf,0x22,0x26,0x13,0x8a, + 0x31,0x79,0x8b,0x51,0x37,0x55,0x1b,0x4a,0xcc,0xf6,0x24,0x81,0xa,0x41,0x21,0x2a, + 0xaa,0x33,0xe5,0xb0,0x85,0xd3,0xce,0x21,0xe5,0x26,0xc,0x85,0x1a,0x10,0x8e,0xf4, + 0x3d,0x93,0x6c,0xbd,0x3,0xd4,0x22,0xea,0x3f,0x33,0x79,0x89,0xbc,0xd4,0xbb,0x16, + 0xb5,0x8d,0xba,0x0,0x72,0xa1,0xa4,0x53,0x11,0xe3,0x15,0xff,0xdf,0x72,0x54,0x21, + 0xc4,0x89,0x3d,0xc6,0xed,0x25,0xf9,0x92,0x2a,0x4e,0xca,0x6c,0x4b,0xa5,0xf1,0x12, + 0xb1,0x18,0xe9,0xa2,0xff,0x6,0x4c,0x81,0xc6,0x29,0x1c,0x6b,0x33,0xa8,0x81,0x4a, + 0x44,0x9a,0xd1,0x8,0x36,0xfe,0x62,0x43,0x49,0xcb,0x20,0x44,0x73,0xf1,0xae,0xf, + 0xcd,0xa6,0x91,0xb,0xa,0x26,0x2,0xb5,0xda,0x1d,0xbe,0xf3,0x64,0x83,0x7e,0xfd, + 0xd5,0x63,0xcc,0x4d,0xe,0xe3,0xcd,0xf3,0xb3,0x2a,0xf6,0xf2,0x45,0xbe,0xd0,0xf2, + 0x4f,0xa3,0x56,0xc5,0xd5,0x33,0xd3,0x18,0x1d,0xea,0xc3,0x8d,0x8b,0x73,0x78,0xf2, + 0x7c,0x1b,0x8f,0x56,0xb6,0xf1,0xe8,0xf9,0x36,0x9e,0xae,0xed,0x60,0x79,0x63,0xf, + 0xc7,0x9e,0x3c,0x47,0x7a,0xe1,0x59,0x32,0x9b,0x53,0x71,0x75,0x1e,0xc1,0x25,0x2e, + 0xc4,0xd3,0xca,0x43,0x33,0x67,0x26,0x51,0x64,0xd4,0x7,0x9a,0x22,0x53,0x14,0x9c, + 0x53,0x85,0x5c,0xa0,0x4,0xb1,0xf3,0x71,0xf0,0x4b,0xc,0xe,0xab,0x2c,0xef,0x4c, + 0x64,0x98,0x62,0x0,0x84,0x30,0xfa,0x53,0x8b,0x67,0xe3,0xe9,0x60,0x54,0x21,0x75, + 0x93,0x7b,0x74,0x7e,0xa0,0x59,0xc7,0x9b,0x17,0xe6,0xe3,0x84,0xde,0x8b,0xd4,0x14, + 0x8a,0xf9,0xd6,0x5e,0xb,0x37,0xef,0xaf,0x60,0x75,0xeb,0xc0,0xc1,0x86,0x2a,0x29, + 0x45,0xd8,0xb7,0x4a,0xa2,0x9e,0xf3,0x74,0x47,0x88,0x55,0xe1,0x84,0x9a,0x7b,0x23, + 0xc4,0x30,0xa7,0x85,0xdf,0xe5,0xae,0x7,0x36,0xc9,0x10,0x4e,0xea,0xcd,0x52,0xd8, + 0x94,0xc0,0x48,0x21,0x15,0xb0,0x4,0xce,0x41,0x4f,0xe1,0xc9,0xd,0x6,0x46,0x86, + 0xfa,0x70,0xed,0xdc,0x2c,0x4d,0xf8,0x34,0xbf,0xdc,0xf3,0x40,0x5e,0x4b,0x95,0x4a, + 0x5,0x37,0xef,0xad,0xe0,0xd3,0xef,0x9e,0xe1,0xb8,0xdd,0x4d,0x11,0xa8,0x8a,0x6e, + 0x58,0xb2,0x12,0x2f,0xc1,0xe8,0x8,0x7a,0x32,0x2e,0x1,0x29,0x1,0x0,0x33,0xe3, + 0x83,0xb8,0xb4,0x30,0x81,0xc1,0xfe,0xfa,0xb,0xb,0x79,0xf8,0xdc,0xed,0xc7,0xeb, + 0xf8,0xfc,0xce,0x32,0xf6,0xf,0xdb,0x51,0x6,0xab,0x42,0xbb,0x2,0xc4,0xe1,0x1f, + 0x4a,0x5f,0xa3,0x86,0x73,0x73,0x63,0x78,0xed,0xf4,0x14,0x2e,0x2d,0x4c,0xe2,0xf4, + 0xec,0x8,0x66,0xc7,0x86,0x30,0x33,0x3e,0x88,0x89,0xe1,0xfe,0xd2,0xe9,0x3b,0xdf, + 0x93,0xe7,0x51,0xb3,0x72,0x82,0xdf,0xda,0x3b,0xc2,0xa7,0x77,0x9e,0xf1,0xcd,0xbb, + 0xcb,0xf8,0xfa,0xe1,0x1a,0x7f,0xf7,0x64,0x8d,0xd7,0x77,0xe,0x3d,0xc7,0x94,0x52, + 0xe8,0x5e,0x78,0x2a,0x5e,0x5b,0xee,0xfe,0x2f,0x14,0x77,0xb2,0xfe,0x15,0xf1,0x53, + 0x3a,0x2c,0x18,0xd6,0x26,0x6b,0x25,0xf6,0xd6,0x4b,0x9c,0xf2,0xc2,0x2c,0x5b,0xd7, + 0xa,0x2,0xb0,0x6c,0x61,0x18,0x64,0xd9,0xa9,0xad,0x98,0x11,0xec,0xe,0xac,0x5f, + 0xad,0x79,0xb8,0x5d,0x6e,0xfe,0xa2,0xee,0xc4,0xa4,0x46,0x5f,0xba,0x60,0x13,0x97, + 0x10,0x1e,0xa5,0x9f,0x9a,0x28,0xc1,0xf2,0xeb,0x19,0xa9,0x46,0x86,0x7b,0xa6,0xaa, + 0xfd,0x2b,0x95,0xc4,0x5b,0x97,0xb,0xca,0xba,0x9,0x96,0xcd,0xab,0x7b,0x73,0xa9, + 0x64,0xe7,0x9b,0x5b,0xaf,0x27,0xf9,0x49,0x3e,0xf9,0xa7,0x88,0x55,0x99,0xe,0x84, + 0xc2,0xc,0xa0,0x3d,0x63,0xf5,0x52,0x58,0x9a,0x86,0x5,0x1a,0xa0,0x89,0xbb,0x71, + 0xaf,0xae,0x71,0xf2,0x27,0xc9,0x9e,0xe,0x0,0x1a,0xb9,0xfc,0xc3,0x4,0xa3,0x27, + 0x99,0x4e,0x0,0xed,0x9d,0x35,0x19,0x94,0x9,0x2c,0x48,0x18,0x58,0x7,0x6b,0x52, + 0x13,0x47,0xcd,0x62,0xcb,0x2d,0x1d,0x93,0xb2,0x9e,0x25,0xb6,0xb,0x96,0x38,0xac, + 0x2,0xf4,0xfe,0x9c,0x32,0xaa,0x93,0x20,0x4f,0x70,0x96,0x37,0x4b,0x54,0x32,0xaf, + 0x5b,0xaf,0xfe,0x74,0x27,0xa1,0x94,0x3b,0x93,0x72,0x99,0x9,0xb6,0x85,0xa1,0x51, + 0x4b,0xd2,0x9c,0xe4,0x2a,0x9a,0x45,0xa2,0x4a,0xd2,0x9f,0xdc,0xc8,0x94,0x21,0x6, + 0xc2,0x59,0x90,0x95,0xbc,0xa5,0x60,0x5,0x2c,0x8a,0x75,0xf0,0x89,0x4f,0xd,0x66, + 0xfa,0x32,0x13,0x65,0x24,0x44,0x49,0x9c,0x4c,0x42,0x1e,0x79,0xdc,0xee,0xf2,0xa7, + 0x77,0x96,0x30,0x34,0xd8,0x44,0x5f,0xbd,0x4a,0x57,0xcf,0xce,0x14,0x60,0xc6,0xfc, + 0x40,0x91,0x7,0x4d,0x38,0x80,0x6,0xfb,0x1b,0xb8,0xd4,0xdf,0xc0,0xa5,0x85,0x49, + 0x1c,0xb4,0x4e,0xf0,0x70,0x79,0x3,0xb7,0x1e,0xae,0xe1,0xee,0xd2,0x3a,0x1e,0x2e, + 0x6f,0xe1,0xf9,0xe6,0x3e,0x76,0xf,0x8f,0xd1,0xb5,0x16,0xb6,0xcb,0xe8,0x58,0x8b, + 0xae,0xb5,0xe8,0x76,0x19,0x96,0xfd,0xdf,0xbb,0x16,0xd6,0xa6,0xe6,0xac,0x48,0x58, + 0x16,0x1c,0x14,0x12,0xaa,0x8f,0x18,0x68,0x44,0x5,0xd7,0xba,0xc0,0x7f,0x61,0xe9, + 0x1f,0x4a,0x44,0x64,0x1d,0xab,0xd5,0xdd,0xaa,0x26,0x30,0x7d,0x43,0xee,0xa3,0xb7, + 0xb3,0xf6,0x12,0xcf,0xf0,0xfe,0x1a,0x16,0xcb,0x7f,0xe9,0xaf,0xaf,0xf6,0xe8,0xda, + 0xa9,0x9e,0x8,0xe3,0x23,0x3,0x74,0x71,0x61,0x82,0xa6,0x46,0x7,0x7a,0x92,0xe, + 0xe5,0x74,0xf6,0xf8,0xf9,0x16,0x7e,0xfb,0xcd,0x53,0x5e,0xdf,0x3d,0x64,0x49,0x22, + 0xf2,0xae,0x38,0x61,0x72,0xe6,0xa8,0xdd,0x8,0x82,0x22,0xb2,0x4e,0x72,0x44,0x9, + 0x8c,0x70,0x6,0x3a,0xe9,0xef,0xec,0x13,0xcf,0xa3,0x23,0xa4,0x83,0xb,0xf2,0x5b, + 0x92,0x35,0xe7,0x85,0x72,0xd3,0xa4,0x44,0xbb,0x9,0x81,0x1a,0x42,0x7d,0x12,0xb8, + 0x74,0x8b,0x33,0x23,0x78,0xff,0xea,0x22,0x26,0x47,0x6,0x7b,0x12,0xe1,0xc2,0xf3, + 0xdf,0x3f,0x6c,0xe3,0xeb,0x87,0xcf,0x71,0xf3,0xde,0x8a,0x37,0x3d,0x12,0x52,0x2d, + 0xc5,0x93,0xe6,0xb2,0x33,0x50,0xa0,0x9f,0x32,0x2e,0x82,0x91,0x3d,0xf4,0x78,0x5f, + 0x8c,0xd,0x35,0x31,0x3f,0x31,0x84,0x51,0x1f,0x6c,0x52,0x96,0xdb,0x2e,0xaf,0xfb, + 0x93,0x4e,0x7,0x5f,0xde,0x7f,0x8e,0x8f,0x6f,0x3f,0xf3,0x9c,0x6,0x28,0xb6,0x7a, + 0xf8,0xb9,0x7d,0x8d,0x1a,0x1a,0x15,0x83,0xf1,0xe1,0x3e,0x9c,0x99,0x1d,0xc3,0xf5, + 0xf3,0x33,0x78,0xfb,0xd2,0x29,0xbc,0x71,0x6e,0x3a,0xc2,0xea,0xf2,0xb9,0x97,0xc5, + 0xca,0xbe,0x28,0x2c,0xe9,0xa4,0xd3,0xc1,0xee,0x61,0x1b,0x5b,0xbb,0x47,0xf8,0xf6, + 0xf1,0x1a,0xff,0xed,0xa7,0xf7,0xf8,0x37,0xdf,0x3e,0xc5,0xfa,0xf6,0x41,0xa,0x58, + 0xf1,0xe5,0xd2,0x2b,0x10,0x43,0xca,0x3a,0x47,0xdf,0x2,0xe,0x26,0x32,0xb0,0xfe, + 0xa4,0xb5,0x4c,0x96,0x61,0xd9,0x7a,0x52,0x11,0x93,0x13,0x10,0x59,0x26,0x62,0xb2, + 0xcc,0xec,0x72,0xd5,0x7c,0x47,0x6c,0x98,0x60,0xa3,0xb4,0x8d,0xe0,0xa4,0x6f,0x30, + 0x81,0x37,0x4c,0x61,0x89,0x23,0x8a,0xb4,0xe6,0x42,0xa8,0x74,0x35,0x53,0x84,0x9a, + 0xd9,0x94,0x34,0xf5,0x2a,0xb7,0x86,0xa0,0x3c,0x5b,0xa2,0x3f,0x41,0x0,0xcb,0xc, + 0x7c,0xde,0xb4,0x33,0x96,0xd1,0x81,0x88,0x54,0x10,0xb6,0x53,0xc6,0xce,0x92,0x6b, + 0x72,0x52,0x24,0x51,0xe8,0x53,0x9c,0xb2,0xbd,0xa0,0x24,0x83,0x9,0xa6,0x8a,0xa, + 0x75,0xa1,0x8c,0xc7,0x2d,0x31,0x2d,0xf5,0x20,0x88,0x20,0x6,0xc3,0x60,0x11,0x9e, + 0xaa,0x4e,0x32,0x1f,0x9,0x6e,0xdf,0x4,0x43,0x1e,0x40,0xf,0x2c,0x3f,0x32,0xbe, + 0x88,0x47,0xe1,0x7a,0x8,0x4,0x49,0x5b,0x32,0x47,0x7c,0x73,0xdf,0x6e,0xf4,0x82, + 0x24,0x65,0x73,0x7b,0x24,0xd2,0xfb,0x8d,0xa7,0x72,0xcf,0x2a,0xbc,0x91,0x42,0xdc, + 0xad,0xf7,0x35,0x8,0xbf,0xc2,0x72,0x2c,0x6c,0xe1,0x5d,0xac,0x68,0xe5,0x9f,0x61, + 0x88,0x20,0x36,0xce,0xf8,0xef,0xa4,0x38,0xb,0x9c,0xf9,0xf3,0x73,0x8c,0x42,0x63, + 0x30,0x2a,0x14,0x56,0x25,0x24,0xa4,0x6b,0x2c,0xe3,0xe5,0x42,0x6b,0xc8,0x25,0x45, + 0x18,0x81,0xc7,0x25,0xad,0x73,0x59,0xec,0x22,0x85,0x12,0x5c,0xe5,0x4e,0x16,0xd2, + 0x62,0x14,0x69,0xc4,0xa3,0x13,0x1c,0x1d,0xce,0x72,0x82,0x90,0x57,0xac,0x89,0x58, + 0x5f,0x2a,0x4c,0xc1,0xe2,0x82,0x2f,0xe9,0x7d,0x89,0x9,0xb8,0xb7,0xb4,0xc5,0x7, + 0xad,0xdb,0x30,0x64,0x70,0x7c,0xd2,0xa5,0xb7,0x2e,0xcd,0x97,0xba,0x51,0xe9,0x10, + 0x85,0x72,0xd2,0x1c,0x11,0xa1,0xaf,0x5e,0xc1,0xb9,0xb9,0x9,0x2c,0x4c,0x8d,0xe2, + 0x27,0x37,0xce,0xe2,0xb8,0xd3,0xc5,0xc1,0x51,0x1b,0xdb,0xfb,0x2d,0xac,0x6e,0xed, + 0x63,0x6b,0xef,0x8,0xdb,0xfb,0x2d,0x6c,0xed,0x1d,0x62,0xe7,0xe0,0xd8,0xff,0xfd, + 0x8,0x3b,0xfb,0x2d,0x6c,0xee,0xb5,0x70,0x7c,0xd2,0x29,0xf1,0xe,0x28,0xd9,0x8f, + 0x51,0x76,0xf9,0xcb,0x1b,0x4c,0x91,0x5d,0xd,0xb4,0x73,0x3e,0xc9,0xc0,0x2,0x19, + 0xa7,0x90,0x2a,0x40,0xe0,0x46,0x9a,0x0,0x48,0xb1,0x77,0x9b,0x4b,0xaa,0x38,0x13, + 0xd7,0x51,0x14,0xd0,0xf6,0xd0,0xd,0x6,0xe0,0x89,0x9a,0xf5,0x2a,0x4e,0x4d,0xd, + 0x63,0xc2,0xe7,0x6b,0xbf,0x8a,0x3b,0xdc,0xa3,0x95,0x6d,0xfc,0xfc,0xe6,0x23,0x1f, + 0x80,0xe3,0x16,0x96,0x9,0x18,0x22,0x41,0x87,0x8d,0x35,0x8c,0x75,0xc0,0x2b,0x85, + 0x6b,0x37,0x91,0xa,0x81,0x44,0x2c,0x80,0x11,0x67,0x92,0xc9,0xa6,0x23,0x61,0x2d, + 0x49,0x31,0x82,0x4b,0x70,0x8,0x32,0xd6,0xb9,0xa1,0x4c,0x5d,0x1b,0x1e,0x9d,0xc1, + 0xe9,0x99,0x31,0xfa,0xf1,0x8d,0xb3,0x98,0x18,0x6e,0xf6,0x5c,0xe3,0x30,0x33,0x8e, + 0x4f,0x3a,0x78,0xb0,0xb2,0x89,0x3b,0x4b,0x9b,0x58,0xdf,0x3b,0xd2,0x56,0xf9,0x54, + 0xc0,0x6d,0x50,0x8c,0xb9,0x92,0x99,0xe8,0x3a,0xd2,0xba,0x88,0x74,0x12,0x6,0xfa, + 0x6a,0xb8,0x7e,0x61,0x16,0xa7,0x67,0xc6,0x5e,0x98,0x65,0x20,0xdf,0xab,0xf6,0x89, + 0xc5,0xd7,0xf,0x57,0xf1,0xc5,0xbd,0x67,0x38,0xe9,0x48,0xf8,0x38,0x3d,0x8e,0xf1, + 0xe1,0x7e,0xbc,0x79,0x7e,0x6,0xef,0x5d,0x39,0x85,0xd7,0xce,0x4e,0x63,0x7e,0x62, + 0x8,0x23,0x3,0x4d,0xd4,0xab,0x15,0xf4,0x35,0xaa,0xa5,0x8d,0x4c,0xaf,0x6b,0xa2, + 0xec,0x6b,0x98,0x19,0x8f,0x9e,0xef,0xe0,0x97,0x37,0x1f,0xf1,0x87,0x5f,0x3d,0xc6, + 0xed,0xc7,0x6b,0xbc,0x77,0xd4,0xe6,0xd6,0x71,0x3b,0xf2,0x23,0xdc,0x84,0x6c,0x2, + 0xb2,0xce,0x9c,0x7c,0x4,0x9c,0x2d,0x9,0x5b,0x26,0x76,0xa6,0xec,0x7e,0xa,0x70, + 0xd3,0x38,0x93,0x75,0xf8,0xbb,0xb5,0x51,0x35,0xe1,0xde,0x48,0x9b,0x48,0x96,0xd0, + 0xb2,0x36,0x6f,0x21,0x17,0x7,0x60,0xff,0x31,0x25,0x21,0x64,0x66,0x86,0x41,0x16, + 0x4a,0xa9,0xc,0xba,0x90,0xad,0x4f,0x94,0xb,0x25,0x33,0xe4,0x16,0x4b,0x42,0xec, + 0x2c,0xc4,0x3c,0xf9,0x9a,0x4e,0xca,0x66,0xab,0x44,0x54,0x2e,0xbc,0x29,0xa1,0x4d, + 0x2b,0x47,0xb8,0x2c,0xbf,0x94,0x20,0xad,0xe8,0x49,0xf9,0x9,0xc7,0xcc,0xe8,0x10, + 0xc1,0x18,0x8e,0x1a,0xe3,0xf,0x8e,0x94,0x69,0x16,0xed,0xec,0x54,0x47,0xc8,0x81, + 0x0,0x47,0x1,0x79,0xa5,0x48,0xc0,0x33,0x22,0xcf,0x26,0x38,0xb4,0xc7,0x4c,0x6c, + 0xc4,0x22,0x1e,0x8e,0x24,0x3,0x43,0x30,0x64,0x18,0x29,0x61,0xdb,0xb1,0x6e,0x5c, + 0xa1,0xf7,0x66,0xa2,0x86,0x22,0xa1,0x1d,0x9,0x6a,0xcf,0x65,0x3b,0x24,0x65,0x3d, + 0x91,0x29,0x1f,0xfd,0xce,0xc3,0xb7,0x6,0xf4,0x81,0x8c,0x37,0xae,0x8c,0xfb,0x28, + 0x72,0xc5,0x9d,0xc,0x45,0x5a,0xc,0xe5,0xbb,0xd4,0x40,0xc0,0x60,0xa5,0x3b,0xd6, + 0x5a,0xa1,0xf4,0xd,0xaa,0x6b,0x57,0xac,0x67,0x99,0x7a,0x14,0xe4,0x96,0x46,0xa9, + 0x97,0x8b,0xfb,0x91,0xfc,0xee,0x27,0x2a,0x63,0x54,0x33,0x91,0x24,0xc1,0x43,0x4e, + 0xeb,0x79,0xd8,0x4e,0x6e,0x3,0x4c,0x9a,0xc4,0x45,0x88,0xb2,0x90,0x4c,0x6a,0x2b, + 0x7,0x76,0x71,0x1f,0xa9,0x4c,0x60,0x8a,0x96,0x4a,0x9c,0xf3,0x10,0x23,0xd8,0x65, + 0x88,0x9e,0x6f,0xed,0xf3,0xcf,0xbe,0x78,0x80,0x93,0x6e,0x17,0x7,0xc7,0x27,0x74, + 0xed,0xec,0x4c,0x94,0xf2,0x48,0x2f,0xe8,0x30,0x31,0xbc,0x48,0x6e,0x65,0x8c,0x41, + 0x7f,0xd3,0x0,0xa8,0x1,0x68,0xaa,0xcf,0x6d,0xef,0x1f,0x63,0x7b,0xff,0x8,0x7, + 0xad,0x36,0xf6,0xf,0xdb,0xd8,0x3f,0x3a,0xc6,0xee,0x61,0xb,0x7,0xad,0x13,0xec, + 0x1f,0xb5,0xb1,0x77,0x70,0x8c,0xfd,0x56,0x1b,0x47,0xed,0xe,0x8e,0x8f,0x4f,0xd0, + 0x6a,0x77,0x70,0x7c,0xd2,0xc5,0xf1,0xc9,0x9,0x5a,0xc7,0x1d,0x1c,0xb5,0xbb,0x38, + 0x3a,0x3e,0xc1,0xd1,0x71,0x1b,0x47,0xc7,0x27,0xb0,0x10,0xb6,0x74,0x44,0x22,0xc3, + 0x3e,0x9,0x45,0xb4,0xfd,0x64,0x8,0x8c,0x4a,0xe3,0x9f,0x2b,0x8a,0x2,0x8b,0xf5, + 0x53,0x2b,0x2b,0xde,0x41,0x70,0xcb,0xa,0xe2,0x10,0x16,0xe1,0x84,0x2,0x3f,0x49, + 0xe,0xc,0xa8,0x18,0x83,0x73,0x73,0xe3,0x38,0x37,0x3f,0x8e,0xa6,0x3f,0xd0,0xcb, + 0xbc,0xb7,0xe5,0xeb,0xbb,0x7f,0xd4,0xc6,0xc3,0x95,0x2d,0x7e,0xb4,0xb2,0xcd,0x36, + 0xa6,0x5f,0x99,0x78,0x3a,0x12,0x49,0xca,0x67,0x8a,0xe0,0xd4,0xbc,0x43,0x4e,0x36, + 0xc9,0xf2,0x3e,0x8,0x24,0xe,0x75,0xf2,0x49,0xef,0x49,0x11,0x32,0x23,0x3b,0x4e, + 0xa2,0x18,0x6,0xab,0x14,0xa,0x99,0x75,0x74,0xf2,0xbb,0x37,0x98,0x9b,0x1c,0xc0, + 0xb5,0x33,0xd3,0x38,0x33,0x33,0x82,0x5a,0xb5,0xda,0x13,0x6a,0x27,0x22,0x2c,0xad, + 0xef,0xe1,0xd7,0xb7,0x9e,0xe0,0xe9,0xea,0x6e,0xe6,0xa3,0xa4,0x8b,0x99,0x3e,0x7f, + 0x65,0x46,0x45,0x6e,0x43,0x46,0x85,0xc3,0x9a,0x4,0x1,0xab,0xbf,0xaf,0x81,0xeb, + 0xe7,0x67,0xb1,0x38,0x3d,0x52,0x5a,0xcc,0x73,0xe2,0xd9,0x41,0xeb,0x4,0xb7,0x9f, + 0xae,0xe3,0xfe,0xf2,0x26,0x1c,0xdf,0xd3,0x9d,0xe8,0x7d,0x8d,0x1a,0x26,0x86,0xfb, + 0x30,0x3d,0x3a,0x80,0xe9,0xf1,0x41,0x9c,0x99,0x19,0xc5,0xe5,0x85,0x9,0x5c,0x5e, + 0x9c,0xc4,0x99,0x99,0x11,0x54,0x2b,0x95,0xd2,0x46,0x21,0xdc,0x23,0x39,0xe2,0x55, + 0xc6,0x5f,0x21,0x22,0x6c,0xef,0x1d,0xe1,0xd9,0xc6,0x1e,0x1e,0xae,0x6c,0xf3,0xd7, + 0xf,0x9f,0xe3,0xf3,0xbb,0xcb,0x7c,0xeb,0xc1,0x2a,0xbc,0x17,0x7b,0xda,0xaf,0x78, + 0x18,0x9c,0x61,0xd9,0x2d,0xb6,0x3d,0xa3,0x3d,0xfc,0x13,0x24,0x8e,0xee,0xd0,0x65, + 0x27,0xe9,0x21,0x26,0xb0,0x4d,0xcc,0x76,0x62,0x30,0x5b,0x87,0xa1,0xbb,0x1d,0x95, + 0x5,0xd9,0x60,0x2e,0xc3,0x48,0xc5,0x3c,0xfd,0x7c,0x62,0xcd,0x22,0xd7,0x6f,0xb, + 0x95,0x8,0xf3,0x95,0xca,0x42,0x20,0xdf,0x28,0xc4,0xa2,0x66,0x2a,0x19,0x2a,0x59, + 0x49,0x4a,0x8e,0x1a,0x69,0xce,0x24,0xc3,0x38,0x52,0x5c,0xd1,0x20,0x6,0xe5,0xda, + 0x47,0xe9,0x7,0x93,0x99,0xcd,0x48,0xee,0x12,0x67,0xf,0x20,0xfd,0x42,0x1,0x3b, + 0xf8,0x68,0xa9,0x50,0x8e,0x53,0x4,0xaa,0x38,0x58,0x42,0x5e,0xab,0x89,0xe8,0xa0, + 0x4c,0xe2,0x53,0x3,0x74,0xc8,0x95,0x74,0x28,0x4c,0xa8,0xc8,0xa1,0xde,0x19,0xe3, + 0x3f,0x6d,0xdc,0x18,0xe2,0xb7,0xe5,0x50,0x24,0x38,0x83,0xec,0xbf,0x5,0x13,0x48, + 0x4f,0xe3,0x14,0x86,0x71,0x29,0xa1,0x92,0x2f,0xb3,0x49,0x56,0x28,0x9,0x95,0x90, + 0x9b,0x39,0x31,0xee,0x86,0x74,0x1f,0x68,0x57,0xb7,0xf0,0x46,0x99,0xf8,0xdc,0xe2, + 0x24,0x9d,0x4c,0x64,0xb5,0x34,0x24,0x2c,0x9,0x83,0xab,0x2e,0x43,0x58,0xb3,0xb1, + 0xca,0x31,0x27,0xcd,0xdd,0x62,0x4a,0x1e,0xa6,0x32,0x50,0x8f,0xa,0xc,0x7,0xcd, + 0xd1,0x52,0xa4,0x39,0xca,0x90,0x15,0x42,0xf4,0x21,0x57,0x76,0xb,0x82,0xa9,0x4b, + 0x3a,0x76,0x31,0x6c,0x38,0xd,0x65,0x36,0x4,0xac,0x3c,0x3f,0x14,0xa3,0xce,0x8b, + 0x50,0x44,0x9c,0x2b,0xc7,0xa4,0x6c,0xdf,0x44,0xb9,0x5,0x9b,0x51,0x8c,0x8f,0x3b, + 0x4b,0xeb,0xbc,0xb6,0x73,0x80,0x27,0xab,0x3b,0xf8,0xf3,0x1f,0x5f,0xc3,0xef,0xdf, + 0x38,0x4b,0xcd,0x46,0xed,0xa5,0xf2,0x99,0x5e,0x93,0x7b,0x99,0xec,0x67,0x6c,0xa8, + 0x89,0xd1,0xc1,0x46,0x81,0xd1,0x2b,0x51,0x0,0x66,0xc6,0xc1,0xd1,0x9,0x76,0x8f, + 0x8e,0xb1,0xbe,0x73,0x80,0xcd,0xbd,0x23,0x6c,0xef,0x1e,0x62,0x73,0xaf,0x85,0xf5, + 0xed,0x3,0xac,0x6e,0x1f,0xe0,0xf9,0xd6,0x1,0x56,0xb7,0xf6,0xb1,0xba,0x7d,0xe0, + 0xf6,0xf3,0x92,0x4c,0x97,0x67,0x49,0x13,0x44,0x4b,0x69,0x7c,0x28,0x58,0x8,0x1f, + 0x9,0x1a,0xca,0x34,0x5b,0x73,0xc9,0x5c,0x18,0xa7,0xd4,0x54,0xb5,0x0,0x5d,0xb, + 0x29,0xb,0x69,0x22,0x53,0x31,0xb8,0x74,0x7a,0x92,0xae,0x2c,0x4e,0x91,0x21,0xbc, + 0x94,0x78,0xb5,0x7f,0xd4,0xc6,0x57,0xf,0x9e,0xe3,0xc1,0xca,0x16,0xba,0x21,0xee, + 0x9c,0xa8,0xa8,0x6e,0x66,0x1,0x57,0x52,0x59,0xec,0x54,0x9e,0xb6,0xc8,0x10,0x18, + 0x4e,0xb6,0x9b,0xa4,0x74,0x25,0x89,0xdb,0x96,0xa1,0xcf,0x33,0xa7,0x54,0x85,0xe, + 0x88,0x95,0x74,0x1c,0x91,0x28,0x37,0x31,0xd2,0x8f,0x7f,0xf6,0xce,0x5,0xdc,0xb8, + 0x38,0x8b,0x6a,0xa5,0xf2,0x42,0xed,0x39,0x0,0xdc,0x5b,0xda,0xc0,0xdf,0x7e,0xfa, + 0x0,0x1b,0x7b,0x47,0x41,0x40,0x93,0x52,0xd,0x95,0x80,0x5e,0xbb,0xab,0x31,0xa4, + 0x81,0x32,0x43,0x22,0x7a,0xf9,0xc4,0x27,0x77,0xfd,0x3,0xcd,0x3a,0xae,0x9e,0x9d, + 0xc2,0xe2,0xf4,0x48,0xe9,0x7b,0x22,0xb,0x2b,0x33,0xe3,0xe9,0xea,0x36,0x3e,0xfa, + 0xe6,0x29,0xb6,0xf6,0x5b,0x71,0xf0,0x18,0x1e,0x6c,0xe2,0xdc,0xcc,0x18,0xae,0x9f, + 0x9f,0xc6,0xdb,0x97,0xe6,0xf1,0xf6,0xc5,0x39,0x4c,0x8d,0xf6,0x47,0xb7,0xb9,0x5c, + 0xfe,0x99,0xaf,0x55,0x5e,0x76,0xf,0x25,0x4d,0x79,0x1b,0x5f,0x3f,0x58,0xc5,0xcf, + 0x6e,0x3e,0xe4,0xbf,0xf9,0xe4,0x3e,0x3f,0xdb,0xd8,0xd,0x4e,0x9,0xc9,0xbe,0xd5, + 0x1f,0x94,0xe9,0x88,0xa,0xd2,0x31,0xe3,0x89,0x6b,0xe4,0xf6,0x5a,0x9e,0x7e,0xee, + 0x31,0x79,0xeb,0xd,0xd8,0xad,0x27,0x5e,0xc4,0x5d,0xba,0xf3,0xc2,0x6,0x1b,0x22, + 0xb6,0x1c,0xfc,0xc,0x5c,0xc1,0xf7,0x13,0x12,0x6b,0x27,0x9f,0x0,0xd,0x44,0xab, + 0xe0,0xe2,0xfc,0x9b,0x11,0x98,0xa8,0xa0,0x25,0xa5,0xa4,0x52,0xe5,0xe4,0xa8,0xa, + 0x41,0xb2,0x4b,0x1c,0xe5,0xc4,0x86,0xe7,0x3c,0x63,0xd7,0x7f,0x2e,0x69,0x58,0xa8, + 0x7c,0x42,0xef,0x5,0x1,0x6a,0xa2,0x14,0x2b,0x59,0x84,0xdc,0xe2,0x53,0x30,0xc4, + 0x80,0xb6,0x25,0xd4,0x2e,0x23,0xac,0x4c,0x31,0x42,0xce,0x88,0xd2,0x54,0x1a,0x35, + 0xa7,0xf9,0x49,0x96,0xe3,0x9a,0x3a,0xb4,0x4,0x20,0x22,0x36,0x21,0xc2,0xd6,0x24, + 0xb,0x18,0x24,0xf3,0x17,0x12,0x5a,0x72,0x43,0xc6,0x84,0x49,0xdc,0x24,0xb8,0xdd, + 0xc8,0x20,0x10,0xe,0xb9,0x5e,0x1,0x6c,0x14,0x5,0xdc,0x97,0x2a,0x41,0x13,0x16, + 0xbe,0xee,0xb9,0xdd,0xbe,0xa9,0xc8,0x23,0xa3,0x60,0x72,0x5c,0x30,0xb,0x13,0xfb, + 0x30,0x46,0x9,0x9c,0x16,0xa5,0xc9,0x1,0xa6,0x9,0xd7,0x34,0xc1,0x8,0x5b,0x5e, + 0xa2,0xa4,0x57,0x88,0x56,0x57,0x36,0x12,0x47,0x20,0x3d,0xb1,0x22,0x74,0x64,0xc4, + 0xbb,0xcd,0x42,0x4f,0x97,0xb4,0x8e,0xa,0x68,0x24,0x31,0xa2,0x17,0xb4,0xbe,0xa4, + 0x61,0xe2,0x38,0x15,0x6,0xb0,0x86,0xa8,0x68,0xa8,0x43,0xd2,0x4,0x57,0x82,0x14, + 0x99,0xe2,0x42,0x75,0x16,0xd2,0x94,0x3e,0xc5,0x67,0x44,0x67,0xd8,0x80,0xfe,0x27, + 0xf2,0x7c,0x74,0x61,0xdf,0x3e,0x38,0xe6,0xcf,0xef,0x2e,0xbb,0xe2,0x72,0x7f,0x5, + 0x3f,0x7c,0xe3,0xc,0x5d,0x3b,0x33,0x15,0x77,0x8d,0x65,0x44,0xae,0x17,0xfd,0x29, + 0x93,0x2,0xe5,0xd3,0x69,0xbe,0x2f,0x24,0x22,0xc,0xd,0x34,0x30,0xd8,0x5f,0xc7, + 0xe8,0x40,0x13,0xc7,0x9d,0xee,0xff,0xc5,0xda,0x7b,0x36,0x47,0x76,0x66,0x69,0x62, + 0xcf,0x79,0xd3,0x67,0x22,0x91,0x99,0xf0,0xb6,0x0,0x94,0x77,0xac,0xa2,0xeb,0x66, + 0xb3,0xd9,0xd3,0x9c,0x76,0x33,0x3d,0x3b,0x76,0xb5,0xbb,0x1f,0x24,0x6d,0x48,0x21, + 0xe9,0x83,0x7e,0x96,0x36,0x42,0xa,0x4d,0x48,0x11,0x8a,0xd5,0x8e,0xeb,0x9d,0x9d, + 0x76,0x64,0x37,0x9b,0x6c,0x7a,0x56,0x15,0xcb,0x1b,0x14,0xbc,0x37,0x9,0x20,0x13, + 0xe9,0xee,0xd1,0x87,0xfb,0x9a,0xf3,0xde,0x7b,0xb3,0x58,0xb3,0x1a,0x44,0x47,0x13, + 0x85,0x42,0xc1,0xdc,0xbc,0xf7,0x3d,0xe7,0x3c,0xe7,0x31,0x68,0xb7,0xbb,0x38,0xed, + 0x74,0xd1,0x6c,0x75,0xd0,0x38,0x6d,0xe3,0xb4,0xd5,0x45,0xa3,0xdd,0xc1,0x51,0xb3, + 0x8d,0x83,0xa3,0x53,0xec,0xd6,0x1b,0xd8,0xde,0x3f,0xa1,0xad,0x83,0x13,0xac,0x6e, + 0x1f,0xf0,0xe6,0x7e,0x3,0x9d,0x5e,0x2f,0xd4,0xf2,0xb3,0x91,0xd7,0xba,0xd8,0x46, + 0x63,0x91,0x15,0xe,0x2b,0xe1,0xab,0xa5,0x53,0x73,0x65,0xbe,0xb2,0xa5,0xb6,0x28, + 0x21,0x35,0x67,0x72,0xd,0xa0,0x24,0xe0,0x4a,0xc3,0x7,0xe,0xfd,0x1f,0x70,0x71, + 0x66,0x14,0x97,0xcf,0x8c,0x22,0xdd,0x27,0xb9,0x4b,0xa2,0x1e,0x47,0xcd,0x36,0x3e, + 0xba,0xbb,0xcc,0x8f,0x57,0xf7,0xb4,0xb3,0x1f,0x7b,0x36,0x54,0x3e,0xaa,0x23,0xa4, + 0x92,0x2c,0x9a,0x3a,0x12,0x3e,0xdf,0x64,0xa9,0xfe,0xce,0x90,0xc6,0x43,0x93,0x48, + 0xd8,0xc5,0xd8,0xf7,0x49,0x48,0x21,0x49,0x90,0x3,0xc0,0x52,0x2c,0x19,0x3f,0xc, + 0xed,0xd,0x3a,0x3f,0x51,0xc5,0x8f,0x5e,0x3f,0x47,0x57,0xe6,0xc6,0x3c,0x7f,0x83, + 0xa8,0x7d,0x69,0xaf,0xd7,0xc3,0xe1,0x49,0x1b,0x8f,0x56,0xf6,0xf0,0x68,0x6d,0x2f, + 0x54,0x46,0x90,0x3f,0x29,0xc5,0x82,0x7e,0x62,0xac,0x52,0xd1,0x4e,0x5b,0x8f,0x2, + 0x72,0x52,0x68,0xa9,0x3c,0xd2,0x5f,0x6d,0xa4,0x5a,0xc4,0xdc,0x78,0xcd,0x5a,0xf0, + 0xf6,0x93,0xaa,0x99,0xb7,0xa5,0xad,0x43,0x7c,0xfa,0x70,0xd,0xb5,0x72,0x1,0xe7, + 0xa7,0x46,0x70,0x6e,0xba,0x86,0xe9,0x91,0x41,0x8c,0xd5,0x4a,0x18,0xad,0x14,0x31, + 0x52,0x29,0x61,0xa4,0x52,0x4c,0xbc,0x97,0x93,0x62,0x4d,0xa3,0x1c,0x94,0xa4,0x86, + 0xf8,0xf1,0x6a,0xc8,0x41,0xb9,0xfd,0x6c,0x93,0x9f,0xae,0xef,0x63,0x79,0xf3,0x90, + 0xd7,0xf6,0x8e,0xcd,0xd1,0x64,0x86,0x42,0x9b,0x2a,0x64,0x3c,0xfb,0xd9,0xe8,0xcb, + 0xc3,0xd1,0xda,0x98,0xad,0x73,0x28,0x65,0x60,0x46,0x48,0xb4,0xd0,0xc6,0x32,0x8, + 0xf4,0xed,0x12,0xe8,0x7d,0x7b,0x10,0x98,0xfd,0x39,0xd9,0x22,0x1f,0xc0,0x8,0x24, + 0x59,0xa7,0xfd,0x28,0xd6,0x1c,0xe,0xeb,0xfb,0xee,0xac,0x62,0x85,0x1b,0xb3,0x78, + 0x11,0x12,0xc2,0x59,0x10,0x59,0x5b,0xc8,0xce,0x58,0xd4,0x2,0x25,0x88,0x8d,0x14, + 0x31,0x64,0x81,0x33,0x32,0xf2,0x65,0xe4,0x42,0x6e,0x49,0x8,0xb,0xba,0x24,0x5c, + 0xf9,0x76,0x75,0xdc,0xc7,0x79,0xdc,0xdf,0xf7,0x44,0x33,0x65,0xa4,0x19,0x46,0x74, + 0x32,0x31,0x5,0xc6,0x9f,0xa3,0xcc,0x29,0xa2,0x2f,0x1b,0x79,0x11,0x5,0xd6,0x2, + 0x46,0x2a,0x71,0x64,0xad,0xb6,0x4,0x39,0x16,0xee,0x55,0x4a,0xd8,0x85,0xba,0x4c, + 0x6d,0x45,0xd6,0x28,0x46,0x29,0x5d,0xf8,0x95,0x81,0xe6,0x49,0xc1,0xee,0xd3,0xc9, + 0x16,0x76,0xa5,0xc8,0x2e,0xbb,0x5,0xf,0x2c,0x9c,0x9c,0x23,0xb1,0x22,0x4c,0x11, + 0xea,0x88,0xad,0x21,0x4a,0x29,0xa4,0x53,0x84,0x6c,0x2a,0x8d,0x4c,0x26,0xec,0x1d, + 0x7a,0x41,0x68,0xa2,0xde,0xed,0xf5,0xd0,0xed,0x5,0xdc,0xed,0x6,0xda,0x85,0x2c, + 0x49,0x65,0x18,0x99,0x54,0xbd,0x94,0xb5,0xa8,0x96,0x31,0x3c,0xf8,0x52,0x8a,0x90, + 0xcb,0xa4,0x91,0x4a,0x85,0xe1,0x1c,0xa7,0x9d,0x2e,0xf5,0x7a,0x6c,0x53,0xd4,0xad, + 0x74,0xcd,0x7a,0x5a,0x47,0x49,0x6b,0x4e,0xd0,0xed,0xe5,0xca,0x43,0xa0,0xde,0x24, + 0x29,0xd1,0xfa,0x6b,0xe9,0x9f,0x2d,0x9b,0x4e,0x61,0xb0,0x94,0xa3,0x5c,0x36,0x85, + 0x94,0x52,0x50,0x4,0x74,0x3,0x50,0xb7,0xd3,0xc5,0xc9,0x69,0x87,0x1b,0xa7,0x6d, + 0xf4,0x7c,0xeb,0x40,0xd1,0x1a,0x58,0x97,0xfa,0x98,0x93,0xa4,0xf4,0xb1,0x90,0x84, + 0xcd,0xb0,0xe3,0xd5,0xd1,0x9a,0xca,0xc1,0x18,0x24,0x41,0x2b,0xb2,0xe1,0x87,0xc, + 0x80,0xe,0x8e,0x5b,0xfc,0xe9,0x83,0x75,0x3c,0x5e,0xd9,0x43,0xbd,0xd1,0xc2,0x49, + 0xb3,0x85,0x4b,0xb3,0x23,0x34,0x3c,0x58,0x42,0x3a,0x5,0xe4,0x73,0xd9,0xd8,0xe4, + 0x11,0x25,0xc9,0x25,0xc9,0x6c,0x5e,0xc6,0x18,0x43,0xc2,0x9d,0x0,0x50,0x2a,0x64, + 0x51,0x4c,0x70,0x54,0x93,0x7f,0x6e,0xb5,0x3b,0x58,0xdb,0x39,0xc2,0xea,0x4e,0x1d, + 0xcf,0x37,0xf,0xf0,0x6c,0xfd,0x80,0x9e,0x6d,0xec,0xf3,0xd2,0xe6,0x21,0xe,0x4f, + 0x9a,0x68,0x9e,0x76,0xa9,0xab,0xd9,0x76,0xb1,0xa1,0x80,0xed,0x76,0x84,0xa5,0x3d, + 0xb2,0x35,0x89,0x23,0x49,0x52,0x44,0xfc,0x99,0x83,0xf0,0xa,0x94,0x3b,0x40,0x6, + 0x6,0x7,0xa,0x74,0x66,0x7c,0x90,0xa6,0x46,0x6,0x63,0xbf,0x57,0xd2,0xef,0xbe, + 0x7d,0x70,0x82,0xcf,0x1f,0x6d,0x60,0x65,0xe7,0x28,0x5c,0x3d,0x49,0x12,0xad,0x99, + 0x40,0xed,0x59,0xa4,0x5c,0xa4,0x1,0x8b,0x3c,0x59,0x72,0x1e,0xcb,0x80,0xa6,0x3d, + 0x85,0xf2,0xd3,0x24,0x75,0x8d,0xb5,0xe5,0x89,0x98,0x33,0x44,0x8b,0x8c,0x6b,0xda, + 0x4d,0x14,0xba,0xdb,0x3e,0xd8,0xd5,0x9f,0x2,0xd1,0xc2,0x64,0x15,0x6f,0x5e,0x9e, + 0xa1,0xeb,0xb,0xe3,0x28,0x15,0xb2,0xb1,0x15,0x83,0x9c,0x7c,0x8f,0x1a,0x6d,0x7c, + 0xfe,0x68,0x15,0x5f,0x3f,0xdf,0x42,0xe3,0xb4,0xcb,0x4e,0xe5,0xc2,0x9,0xcf,0xb8, + 0x4f,0xd7,0xb3,0xa1,0x60,0x26,0xca,0x20,0xca,0x46,0x11,0xc7,0xd,0x8b,0xce,0xa4, + 0x3a,0x90,0xc7,0xec,0x58,0xd,0x43,0x7a,0x9d,0x94,0xd4,0x70,0x26,0x45,0x8f,0x56, + 0x4b,0x5,0x9c,0x39,0x5b,0xc1,0xf5,0xf9,0x31,0xbc,0xb2,0x30,0x8e,0xb1,0x5a,0xe9, + 0x85,0xe6,0x4b,0x49,0xd3,0x78,0x34,0x50,0x45,0x7e,0x5e,0xb7,0xdb,0x43,0xb3,0xdd, + 0xc5,0x69,0xbb,0x8b,0xe5,0xed,0x43,0x7c,0xf1,0x68,0x1d,0xbf,0xbd,0xb3,0xc4,0x9f, + 0x3d,0x58,0x47,0xb7,0xd7,0x63,0x21,0x80,0x35,0x28,0x85,0x33,0x85,0x31,0xfe,0x3, + 0xae,0xbd,0xd3,0x7f,0x67,0x9,0x70,0x1,0x9,0xeb,0x56,0x80,0x2,0xd,0xb9,0x33, + 0xb3,0x9e,0xc8,0xc3,0x56,0x36,0x84,0xdf,0x35,0xec,0xe,0x3b,0x99,0xc3,0xee,0xd0, + 0x75,0xc1,0x66,0x3,0xc7,0x93,0xe,0x82,0x82,0x5e,0x7e,0x59,0x2f,0x43,0x41,0xb1, + 0x17,0x3f,0x2f,0x8c,0x62,0x24,0x16,0x52,0x16,0x5b,0x52,0xbb,0x21,0x86,0x35,0x9b, + 0x9a,0x3d,0x6d,0x7f,0x14,0x27,0x55,0xe2,0xfc,0x13,0xa,0x27,0x62,0xd,0xb9,0x7b, + 0x23,0xb9,0x92,0x16,0x9c,0x9,0x6e,0x66,0xdc,0xc7,0xe4,0x32,0x9e,0xca,0xe6,0xa1, + 0xd1,0x91,0x5c,0x4d,0x27,0x3c,0x52,0x7e,0x96,0x3a,0xc5,0x95,0x3a,0xfe,0x1,0x62, + 0xe8,0xe6,0xba,0x68,0x3b,0x7c,0x8d,0xac,0xe4,0x2c,0x45,0x64,0x83,0x56,0x42,0x28, + 0xd6,0xc2,0xe9,0x48,0x85,0x9,0xda,0x46,0xae,0xa6,0xff,0x52,0x39,0x6,0x7c,0x88, + 0xd6,0xc3,0x39,0x86,0xeb,0x7d,0xb9,0xb2,0xf3,0x8a,0x8,0x7d,0x77,0x41,0x2d,0x20, + 0xb7,0x76,0xf4,0x72,0xd6,0xc3,0xff,0xc,0x16,0xf3,0x98,0x19,0x1b,0xa4,0x99,0xb1, + 0x2a,0x26,0x87,0xcb,0x54,0xc8,0xa6,0x50,0x6f,0xb4,0x71,0xd4,0x38,0x45,0xfd,0xa4, + 0xcd,0x1b,0xfb,0xc7,0xb4,0xb9,0x77,0x8c,0xfd,0xfa,0x9,0xcb,0x1d,0x7,0x27,0x98, + 0xc4,0x78,0x70,0x34,0x21,0x51,0xa7,0x9a,0x4e,0x2b,0x8c,0xd,0xd,0xe0,0xc2,0xf4, + 0x30,0x55,0x4a,0x39,0x9c,0x76,0x7a,0x78,0xb0,0xb4,0xcd,0xcf,0x37,0xf,0x42,0x80, + 0x9e,0x23,0xf2,0x1b,0xd1,0xea,0xfb,0x3b,0x3c,0xe9,0x4b,0x0,0x7f,0x3d,0xa0,0xb3, + 0x6a,0x28,0xb2,0x23,0x37,0x1f,0x3a,0x3b,0x3d,0x4c,0x7f,0xf1,0xdd,0x4b,0x74,0x71, + 0x76,0x84,0x42,0xc2,0x8c,0xa,0xe3,0x31,0x37,0xf6,0xf9,0xc3,0x3b,0xcb,0xfc,0xe9, + 0x83,0x15,0xde,0x3a,0x38,0x31,0x6c,0x7b,0x7,0xdb,0x73,0xc0,0x70,0x62,0x9e,0x58, + 0x6e,0xa2,0xe8,0x2d,0xe2,0xaa,0x5d,0x4d,0x8f,0x74,0xcf,0x58,0xec,0x1a,0x92,0xb5, + 0xef,0x13,0x54,0x95,0x7a,0xb3,0xcd,0xff,0xf0,0xd1,0x43,0x7c,0xfa,0x60,0x15,0xe7, + 0xa7,0x47,0xf0,0xf6,0xb5,0x19,0xbc,0x75,0x65,0x86,0x16,0x26,0x87,0x12,0x27,0xec, + 0x97,0x99,0xd8,0xbf,0xe9,0xed,0x65,0xe0,0xfb,0xe8,0xa1,0x99,0xcd,0xa4,0x31,0x35, + 0x52,0xc6,0x68,0xb5,0x84,0x6b,0xb,0x13,0xe8,0xf5,0x7a,0x38,0x38,0x39,0xa5,0xa5, + 0xad,0x43,0xbc,0xff,0xe5,0x22,0xff,0xf6,0xce,0x73,0xac,0xed,0x1c,0x41,0x8a,0xb6, + 0x8c,0x8f,0xb5,0x2e,0xcb,0x2e,0x23,0xc7,0x38,0x5,0x2a,0x45,0x9e,0xf1,0x8c,0x34, + 0xb0,0x61,0x63,0x51,0x4d,0x22,0x26,0x97,0xd,0x75,0xe,0x0,0xa1,0x98,0x4f,0xd3, + 0xc2,0x78,0x15,0x23,0xda,0xb4,0xa4,0x5f,0xb6,0xb6,0x69,0x62,0x9a,0xad,0x2e,0x96, + 0xb7,0xe,0xf1,0x7c,0xeb,0x10,0xad,0x4e,0x8f,0xad,0xb6,0xdd,0xba,0x6d,0x91,0x17, + 0x5e,0xe2,0x7e,0x7f,0xcb,0x5b,0x87,0x9,0xbd,0x62,0x25,0xec,0x92,0x94,0x58,0xc2, + 0x20,0x66,0x7a,0x6b,0x75,0x2,0xb6,0x15,0x75,0x59,0xef,0x91,0xaa,0x6e,0x10,0x42, + 0xe5,0x47,0xab,0x9,0xcf,0xc7,0x74,0x26,0x85,0x9f,0x7e,0xfb,0x22,0xfd,0xe9,0x77, + 0x2e,0x22,0x97,0x49,0xbd,0xb0,0xc0,0x11,0x11,0x76,0xea,0xd,0xfc,0xc7,0xdf,0xdc, + 0xc7,0xe7,0xf,0xd7,0x9d,0xff,0x95,0x8,0x67,0x21,0x4a,0x70,0x8a,0x11,0xd6,0x10, + 0x6,0xc9,0xb4,0x76,0x4d,0x7d,0x57,0x42,0xee,0x7e,0xba,0x38,0x33,0x82,0xab,0x73, + 0x23,0x48,0xa7,0xd4,0x4b,0x91,0xd2,0x82,0x20,0xc0,0xb7,0x2f,0xcf,0xe0,0xf2,0x99, + 0x11,0xe4,0x33,0x19,0xe4,0xb2,0x29,0xe4,0x33,0xa9,0x97,0xbe,0x87,0xbf,0xe9,0xf3, + 0xac,0x4,0xed,0xf8,0x14,0x9f,0x3d,0x5c,0xc7,0xef,0xee,0x2e,0xe1,0xeb,0x67,0x5b, + 0xbc,0x5b,0x6f,0xe2,0xf0,0xa4,0x85,0x9e,0x6d,0x44,0xc9,0xc9,0xd1,0x60,0xe1,0x73, + 0x5d,0x2e,0xd9,0x92,0xd1,0x38,0x70,0x5,0x9d,0x81,0x20,0x2c,0xf7,0x8a,0x43,0x59, + 0x39,0x82,0xd0,0x30,0x49,0x8b,0xc8,0x3,0xad,0x43,0xf,0x35,0xbb,0xc,0x26,0xd, + 0xa9,0x7,0x81,0x3e,0x4b,0x2,0xcd,0xe1,0x60,0x4,0x41,0x10,0x28,0xdd,0x14,0x4, + 0x8,0x1b,0x8,0x22,0xfd,0xfd,0x8c,0xc1,0x8c,0xb,0x58,0xf1,0xd3,0x45,0xc9,0x21, + 0xa2,0xe4,0xd8,0x64,0x3e,0x3,0x9c,0x63,0x2e,0x22,0x49,0xef,0x71,0xc4,0x1a,0xd6, + 0xe3,0x91,0x1,0x9e,0xaa,0xd4,0xc8,0xcf,0xd3,0xce,0x24,0x42,0x8,0x97,0x48,0x32, + 0xdf,0x29,0x32,0xab,0xc7,0x95,0xcf,0xe,0x50,0xa6,0x3e,0x4a,0x68,0xdf,0xe8,0x83, + 0x21,0x33,0xd1,0x7d,0x39,0x1c,0xa2,0x12,0x65,0x8f,0x84,0xe3,0x5a,0x4,0x16,0x3b, + 0x6b,0xcf,0xc,0x46,0x3b,0xc2,0xb1,0x66,0xa5,0x87,0xd5,0x5f,0x91,0x5e,0x8b,0x59, + 0xc2,0x1b,0x87,0xef,0xa9,0xd0,0xf1,0x8a,0x43,0xc9,0x1a,0x64,0xa1,0xb7,0xd3,0x38, + 0x19,0xf6,0xba,0x47,0x29,0x94,0x1e,0x90,0x20,0x11,0x8f,0x4a,0xc8,0x66,0x52,0x54, + 0x2b,0x17,0x30,0x52,0x29,0xd2,0xe8,0x60,0x9,0xc3,0xd5,0x2,0x8d,0x56,0x6,0x30, + 0x5a,0x2d,0xd1,0x68,0xb5,0x88,0xa1,0x72,0x1,0xb9,0x6c,0x1a,0x27,0xa7,0x5d,0x34, + 0x5a,0x2d,0x9c,0x34,0x3b,0x74,0xd4,0x6c,0x63,0x65,0xfb,0x80,0x3f,0xbe,0xb7,0x4a, + 0x8b,0x1b,0x7,0x7c,0xdc,0x6c,0xfb,0x3b,0x75,0xa1,0x3,0x4c,0x6c,0xa8,0x74,0x79, + 0xca,0xa4,0x15,0xa6,0x47,0xcb,0xb8,0x36,0x37,0x46,0x97,0xce,0x8c,0x62,0x7a,0xb4, + 0x42,0xc5,0x5c,0x1a,0xad,0x6e,0xf,0xd7,0x16,0xc6,0xf9,0xce,0xd3,0x4d,0xfe,0xf4, + 0xfe,0xa,0xef,0x1f,0xb7,0x34,0x89,0xd3,0x48,0xd3,0xdc,0x29,0x21,0xa7,0x92,0x98, + 0x45,0x2b,0x9,0x58,0x8f,0x25,0xb7,0xdd,0xd0,0x1d,0x8,0xe5,0x62,0x96,0x5e,0x39, + 0x37,0x49,0xef,0x5c,0x9f,0xa5,0x77,0x6f,0x2e,0x60,0x6a,0xb8,0x4c,0xf9,0x9c,0xb3, + 0x79,0x9c,0x1e,0xad,0xd0,0x48,0xb5,0xc4,0xd3,0x63,0x83,0xfc,0xeb,0x2f,0x16,0xf9, + 0xd9,0xc6,0x3e,0xba,0xdd,0xc0,0x76,0x8b,0x64,0xf3,0xab,0x3c,0xdf,0x6a,0x32,0xee, + 0x79,0x91,0xb4,0xd0,0xa8,0x7c,0x9d,0xc9,0x57,0xb,0x47,0xe8,0x0,0x64,0xaa,0x2, + 0xbb,0x43,0x9a,0x10,0x30,0x53,0xe3,0xb4,0xc3,0x8b,0x1b,0x75,0xda,0xad,0x37,0xf9, + 0xf0,0xa4,0x45,0xab,0x3b,0x47,0x7c,0x7e,0x6a,0x88,0x66,0xc7,0x2a,0x18,0x1f,0x2a, + 0x63,0xb4,0x52,0x40,0x36,0x93,0x8e,0x4d,0x1c,0xff,0x5c,0xfb,0xca,0x17,0x7d,0x5e, + 0x3f,0xe7,0x2e,0x59,0x2c,0xb2,0x99,0x34,0x72,0x59,0xf7,0xbd,0x87,0x2b,0x45,0x4c, + 0xe,0x95,0x31,0x90,0xcf,0xd2,0x50,0xa5,0x88,0xdf,0xdd,0x59,0xc2,0xe3,0xd5,0x3d, + 0x9c,0xb4,0x3a,0x6c,0x3,0x6e,0x58,0xda,0x26,0x42,0xd2,0xda,0x23,0xee,0x53,0xca, + 0xb,0x2a,0xf3,0x9d,0x94,0xcd,0x9e,0x4b,0xd9,0xed,0x3b,0x33,0x63,0x7c,0x68,0x0, + 0xd7,0x16,0xc6,0x50,0x1d,0xc8,0x27,0xc2,0xeb,0x72,0xc7,0xda,0xeb,0x5,0x78,0xb8, + 0xba,0x8b,0xaf,0x9f,0x6d,0xf1,0xd1,0x49,0xcb,0x93,0x28,0x5a,0x48,0x91,0x39,0xe2, + 0xc7,0xa4,0x6f,0xc6,0x40,0x23,0xed,0x81,0x48,0xf1,0x33,0xd5,0xdb,0x24,0xee,0x45, + 0x5c,0xef,0x60,0x27,0x78,0x96,0x92,0x34,0x72,0x89,0xc8,0x26,0x3e,0x50,0x69,0xcb, + 0x77,0x45,0xd2,0x96,0x47,0x4,0xa,0x91,0xc9,0xa0,0x1f,0x1d,0x2c,0xd2,0xb7,0x2e, + 0x4f,0xe1,0xed,0x6b,0xb3,0x98,0x9b,0xa8,0xc6,0xa6,0xdf,0xa8,0xc6,0x7a,0x6b,0xff, + 0x18,0x9f,0x3f,0xda,0xc0,0xd7,0x21,0x53,0xdb,0x23,0x35,0xb1,0xcd,0xcc,0xf0,0x30, + 0x4e,0x5b,0x14,0x2c,0x4a,0x0,0x5b,0xdc,0xec,0xc,0x4f,0x1c,0x41,0xac,0x22,0x51, + 0xbd,0xe7,0xa6,0x86,0x70,0x75,0x7e,0xc,0x99,0xb4,0x7a,0xa9,0xa6,0x91,0x99,0x51, + 0x2e,0x66,0x31,0x58,0xca,0xc5,0xf8,0x1e,0x12,0x7d,0xe8,0xb7,0x1f,0x97,0x64,0xb7, + 0xe8,0xb3,0xb1,0x77,0xd4,0xc4,0xfa,0x4e,0x1d,0xab,0xbb,0x47,0x78,0xba,0xb6,0x8f, + 0xbb,0x4b,0xdb,0x7c,0xfb,0xd9,0x16,0xb6,0xf6,0x4f,0xc,0x64,0xc6,0xb0,0xc6,0x9c, + 0x6,0x94,0xb0,0x8c,0x73,0x63,0x78,0xc5,0x42,0x1c,0xc3,0x30,0x9a,0x71,0xb3,0xfb, + 0x36,0x10,0x79,0x10,0x4e,0xe0,0x5a,0xf7,0xc8,0xcc,0x8a,0x89,0x42,0x83,0x77,0x4, + 0xa1,0x7c,0x8d,0x42,0x34,0x3e,0xd0,0x9e,0xd,0x81,0x6,0xef,0xc3,0x71,0x3b,0x94, + 0x89,0x84,0xf,0x81,0xa,0xe5,0x93,0x1c,0xf9,0xde,0x64,0xc8,0x4a,0xcc,0xac,0x24, + 0xa7,0xc9,0x1a,0x96,0xb2,0x6f,0xb8,0xc1,0x6e,0x6,0x14,0xb2,0x9,0xc8,0x15,0x26, + 0xa2,0x84,0xcd,0x28,0x2a,0x8e,0xfe,0x81,0x7a,0x36,0xf,0xdd,0x9,0x95,0x4c,0xff, + 0xaa,0x5c,0x51,0x87,0xb8,0xa9,0x88,0x12,0xba,0x8a,0x88,0xf3,0x95,0xb5,0x4f,0x56, + 0x62,0xf2,0x93,0x1b,0x51,0xc4,0x24,0x71,0x91,0x0,0x9,0x55,0x26,0xdf,0x91,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xc9,0xed,0xf1,0xb4,0x4e,0x8e,0x52,0x46,0xe4, + 0xf9,0xc7,0x3a,0x41,0xb9,0x2d,0xe6,0x60,0x22,0x95,0x52,0x4a,0xf4,0xe1,0xca,0x1a, + 0xc4,0x84,0x5,0xd8,0x4c,0xe9,0xa,0x50,0x44,0x4a,0xc7,0x2e,0x85,0x4b,0x62,0x32, + 0xd,0x83,0x47,0x86,0xb3,0x4f,0x99,0xcd,0x53,0xd7,0xe7,0xf,0x59,0x77,0x5b,0x6, + 0x21,0x97,0x4e,0x61,0x7e,0xa2,0x4a,0x57,0xe7,0xc7,0xe8,0xd5,0xf3,0x13,0x74,0xe3, + 0xdc,0x4,0xe6,0x27,0x6a,0x94,0x4d,0xab,0xc4,0x2c,0x5f,0xe9,0xa6,0xb5,0x5f,0x6f, + 0x52,0x31,0x9f,0xe5,0x5f,0x7c,0xf6,0x14,0xf7,0x97,0xb6,0x99,0x59,0x18,0xd7,0x32, + 0x33,0xf7,0xb1,0x9d,0x90,0x8d,0xd5,0xe4,0x70,0x99,0x7e,0xf2,0xe6,0x79,0xfc,0xd1, + 0xb7,0x2e,0xd0,0xb5,0xf9,0x31,0x6f,0xdb,0xd9,0xed,0x76,0xe9,0xde,0xd2,0xe,0x1f, + 0x35,0xdb,0xfc,0xfb,0x7b,0x2b,0xec,0x8c,0xb,0x14,0x3b,0x7c,0xdb,0xe9,0xe4,0xd8, + 0x92,0xed,0x4,0x2,0xef,0xf4,0xcd,0x12,0x75,0x21,0x7,0x1b,0x67,0x70,0x75,0x61, + 0x9c,0xfe,0xe7,0x9f,0xbe,0x4e,0xaf,0x5d,0x9c,0xa0,0x9c,0x28,0x80,0xe6,0x6d,0x7c, + 0x68,0x0,0x13,0xc3,0x65,0xba,0x71,0x6e,0x92,0x3a,0xbd,0x20,0x68,0xf7,0x7a,0x58, + 0xde,0xaa,0x87,0x7e,0x9e,0x1a,0x25,0x50,0xe6,0x11,0x26,0x84,0x3a,0x6a,0x82,0x19, + 0xb9,0x5d,0x7,0xc1,0x2,0x2b,0x16,0xe2,0x3d,0x8e,0x66,0x92,0x93,0x4f,0x4b,0x85, + 0xb3,0x36,0x26,0x17,0x96,0x65,0xa5,0xca,0x7c,0xd4,0xec,0xd0,0x27,0xf,0x56,0xf9, + 0xb3,0x87,0xab,0x18,0xa9,0x94,0x70,0x75,0x7e,0xc,0xdf,0xbf,0x31,0x47,0xaf,0x5d, + 0x98,0xc0,0xd9,0xc9,0x1a,0x32,0xe9,0x74,0x5f,0x9,0xd0,0xff,0xdf,0xa9,0xfd,0x45, + 0x85,0xbf,0x9f,0xa4,0xce,0xd8,0xd3,0x7e,0xfb,0xca,0xc,0xae,0xcc,0x8d,0xa2,0x52, + 0xca,0xd1,0x3f,0x7d,0xfa,0x84,0x6f,0x3d,0xdb,0xa6,0x6e,0xb7,0xcb,0xca,0x9e,0x32, + 0x9e,0xca,0x15,0x5e,0x1a,0xb2,0xc7,0x92,0x86,0xbc,0xaa,0x62,0xcc,0xd5,0x9e,0x2c, + 0x52,0x56,0x46,0x44,0x93,0xc3,0x83,0xb8,0x71,0x76,0x82,0xca,0x85,0x5c,0xdf,0x55, + 0x84,0xf9,0x6f,0x37,0x60,0x7c,0xf9,0x78,0x3,0x5f,0x3c,0xd9,0x44,0xe0,0xd,0xc8, + 0xfe,0x74,0x6c,0x8e,0x70,0x1b,0x99,0x4c,0xc6,0xf,0x87,0x43,0x7f,0x21,0x67,0xd4, + 0x4d,0x14,0x4,0xae,0xe0,0x29,0x38,0x28,0x82,0xa4,0x5a,0x5c,0x64,0x36,0x93,0xe5, + 0x5a,0x90,0x49,0x7f,0x35,0xb1,0x7e,0xce,0x6f,0x1b,0xce,0xee,0x56,0xc,0x36,0x4, + 0xe0,0xcd,0xcb,0xd3,0xf8,0xf7,0x3f,0xb9,0x41,0xe7,0xa7,0x86,0x12,0xad,0x49,0xe5, + 0x33,0xde,0xe9,0xf6,0xf0,0xe1,0xd7,0xcb,0xf8,0xd5,0x17,0xcf,0xb8,0x7e,0xdc,0x42, + 0x54,0xd3,0xe4,0x13,0xf4,0xfa,0xc8,0x15,0xed,0xa5,0x31,0x5a,0x61,0x49,0x8c,0xf1, + 0xcd,0x48,0xcc,0x67,0x67,0xd2,0xa,0xb,0x93,0x35,0x5c,0x98,0x1e,0x46,0x26,0xa5, + 0x5e,0x8a,0xe4,0x99,0xf4,0x9a,0x45,0x5f,0xbf,0x97,0xbd,0x4f,0xe5,0x35,0x38,0x3c, + 0x3e,0xc5,0xad,0xa7,0x9b,0xf8,0xdd,0xd7,0xcb,0xf8,0xed,0xad,0x25,0xac,0xee,0x1e, + 0x85,0x1,0x3c,0x76,0x1e,0xb7,0xb7,0x95,0x73,0x40,0x74,0x1,0x80,0xae,0xb0,0x8b, + 0x34,0x3d,0x36,0x70,0x39,0x99,0x9,0x5e,0x4f,0xe5,0x1a,0x32,0x27,0x36,0x6c,0x76, + 0x4,0xfa,0xf4,0xd1,0x24,0x38,0xad,0x45,0xf,0xdc,0x54,0xe,0x27,0x87,0xd4,0xb0, + 0xbc,0x6e,0x2a,0x98,0x61,0x2d,0x63,0x35,0x24,0x40,0x50,0xd6,0xb7,0x8a,0x5,0x81, + 0x98,0x84,0x47,0x81,0x78,0x5a,0x1c,0xf8,0x43,0xf1,0xb5,0xb5,0xaf,0xd4,0x50,0x7e, + 0x43,0x96,0x28,0x42,0x44,0x44,0x3c,0x18,0x2f,0xea,0x69,0xff,0x66,0x52,0x5e,0xc4, + 0xa9,0x99,0xc3,0x1d,0x9f,0x29,0xce,0xc3,0xf7,0x3c,0x41,0x94,0x8c,0x72,0xa7,0xbe, + 0xa,0x38,0x24,0x96,0xf7,0x8,0xb7,0x5a,0x47,0x3b,0x46,0x68,0x38,0x82,0xb,0x6b, + 0x36,0xe0,0x9a,0x4d,0xa0,0x6c,0xd2,0x2,0xa9,0x94,0x95,0xa5,0x29,0xa3,0x9d,0x62, + 0x5,0xa5,0x7,0x6d,0xc5,0xa1,0xb2,0x4d,0x59,0x6b,0x57,0xf3,0xb5,0x8c,0x63,0x44, + 0xb8,0x50,0x17,0x32,0x35,0xb6,0x42,0x40,0x56,0x26,0x5f,0xd5,0xc6,0xdc,0x13,0x11, + 0x70,0x76,0xaa,0x46,0xd7,0xe7,0xc7,0xe9,0xca,0xfc,0x28,0x4d,0x8d,0x94,0x31,0x5e, + 0x29,0x61,0xa8,0x52,0xa2,0xe1,0xc1,0x2,0xf2,0xd9,0x74,0xec,0xb7,0x4e,0xea,0x64, + 0x8b,0xf9,0x34,0x6,0x8b,0x79,0x14,0xf3,0x59,0x28,0xa5,0x28,0x60,0xc7,0x6a,0x65, + 0x52,0xf2,0x60,0x8d,0x10,0x11,0xc3,0xd7,0x6b,0xac,0x56,0xc2,0x77,0xae,0x9f,0xa1, + 0x3f,0x79,0xeb,0x12,0x9d,0x9f,0xaa,0xc5,0x1e,0xae,0x54,0x2a,0x85,0xd9,0xd1,0xa, + 0xfd,0xc1,0x8d,0x39,0xb4,0x3a,0x5d,0xdc,0x7a,0xba,0xc9,0x41,0x90,0xa0,0x37,0x93, + 0xa,0x4,0xa2,0xc8,0xd1,0xee,0xeb,0xe1,0x24,0xec,0x32,0x3e,0x32,0x40,0x3f,0x7c, + 0x75,0x81,0x7e,0xf8,0xda,0x2,0xae,0x2d,0x8c,0x51,0x21,0x97,0xed,0xab,0x7b,0x5, + 0x80,0x6a,0x29,0x87,0x77,0x6f,0x2e,0xd0,0x49,0xb3,0x83,0xb5,0x9d,0x7b,0x1c,0x7a, + 0x5a,0x93,0x8b,0xd6,0x50,0x9e,0x6,0x2e,0x34,0x65,0x32,0xd7,0x84,0x8c,0xd1,0x3, + 0x85,0x21,0x32,0x92,0x8a,0x12,0x23,0x62,0x4a,0xed,0x7,0xf9,0x92,0x2e,0x57,0xda, + 0x1d,0xd8,0x63,0x4a,0x9,0x33,0xb6,0xe,0x4e,0xb8,0xf3,0x74,0x93,0xb6,0xf,0x8e, + 0xf9,0x37,0xb7,0x9f,0x63,0x6a,0xb8,0x8c,0xf9,0x89,0x2a,0x9d,0x9d,0x1a,0xc2,0xc2, + 0x44,0xd,0x13,0x43,0x3,0x7d,0x23,0x1d,0x5f,0x44,0x14,0xfa,0x97,0x80,0xe9,0x93, + 0x76,0xb6,0xe5,0x62,0xe,0x3f,0x79,0xe3,0x1c,0xd2,0xa9,0x14,0x6d,0xd7,0x1b,0xbc, + 0xbc,0x75,0x24,0x5d,0xb,0x9c,0xc9,0x94,0x34,0x75,0x15,0x4c,0x19,0xeb,0x34,0x24, + 0xe5,0x95,0xfe,0xbf,0x95,0xab,0x34,0x2,0x80,0xa9,0xe1,0x1,0xbc,0x72,0x76,0x1c, + 0x83,0xa5,0xe4,0x64,0x35,0x39,0xe5,0x35,0x5a,0x5d,0xdc,0x5f,0xda,0xc1,0xc3,0xd5, + 0x5d,0x4,0xbd,0x20,0xb2,0x8e,0xf3,0x55,0x5c,0x2e,0xb5,0xca,0x7c,0x73,0x66,0xe9, + 0x4b,0x4d,0x86,0x32,0xa9,0xa3,0xcd,0x28,0xca,0xb1,0x34,0x37,0x90,0x50,0x67,0x92, + 0x18,0xa,0x44,0xa4,0x3b,0xc1,0x5a,0x37,0x43,0x32,0x29,0x45,0x17,0x0,0xe4,0x73, + 0x19,0xbc,0x7b,0x73,0x9e,0xfe,0xf8,0xcd,0xb3,0x74,0x71,0x66,0x4,0x85,0x5c,0xba, + 0x2f,0xaf,0xc2,0xbc,0xfe,0x1b,0x7b,0x27,0xf8,0xfd,0x83,0x35,0x7c,0xfa,0x68,0x1d, + 0xad,0x5e,0xe0,0xa0,0xf3,0x8,0x61,0xff,0x45,0x77,0x87,0x69,0xa2,0x59,0xec,0xdd, + 0x99,0x44,0xe0,0x5a,0x24,0xee,0x9a,0x99,0x30,0x31,0x54,0xc6,0xe4,0x48,0x19,0xa5, + 0x7c,0xe6,0xa5,0x88,0x9c,0xf2,0x3c,0x4a,0x92,0x1b,0xf6,0x5b,0x9f,0xf4,0x2b,0xf4, + 0xf5,0x93,0x16,0xee,0x3e,0xdf,0xc6,0x83,0x95,0x1d,0x3c,0x5c,0xd9,0xc7,0xda,0x4e, + 0x1d,0xab,0x7b,0x47,0xd8,0xd8,0x3d,0xe2,0x5e,0xe0,0xdd,0xcb,0x9,0xf,0x8f,0xc9, + 0x1b,0xd7,0xe0,0xb8,0x38,0x63,0x34,0xb6,0x16,0x90,0x21,0xc9,0x21,0xcc,0x37,0x87, + 0x76,0x7f,0xf3,0x26,0x77,0x20,0x0,0x14,0x33,0x71,0x10,0x26,0xf2,0x19,0xe9,0x5a, + 0xc0,0x0,0x69,0x63,0x99,0xc0,0x85,0xfb,0x58,0x97,0x33,0xeb,0xe5,0xcf,0xee,0xb8, + 0x1,0x5b,0x22,0x47,0x58,0xa8,0x6d,0xb3,0x29,0x4c,0x60,0x62,0xfa,0x8b,0xa4,0x78, + 0x78,0xaf,0xa5,0x93,0x4c,0xf0,0x88,0x73,0x64,0x4c,0x2e,0x1e,0xfd,0x73,0xa4,0xcc, + 0x5b,0x63,0x19,0x52,0xee,0xb7,0x60,0x2f,0xaf,0x55,0x5c,0x48,0x95,0x2c,0x65,0x8b, + 0x5a,0xd4,0x71,0x5c,0xdb,0x4,0x9f,0x16,0x20,0xf3,0xe0,0xdd,0xd1,0x6a,0xed,0x96, + 0x1,0xcb,0x66,0x27,0xb1,0x80,0xf,0xf7,0xb5,0x66,0x73,0x94,0xd2,0x73,0x37,0x5b, + 0x2,0x1c,0xc,0x6b,0xdd,0x4e,0xd7,0x1a,0x6e,0xa7,0xb0,0xb8,0x2b,0x82,0xd2,0x11, + 0xa9,0xca,0x4a,0xce,0x74,0x51,0xa7,0xd0,0x45,0x4e,0x49,0x56,0xbc,0x10,0x78,0xbb, + 0x85,0x22,0x69,0xc7,0x39,0xfd,0xcb,0xe5,0xd3,0x69,0x2a,0x95,0x32,0x34,0x3f,0x5e, + 0xc3,0xab,0xe7,0x27,0xe8,0xf,0x5e,0x99,0xa3,0x57,0xce,0x8e,0x53,0x21,0x97,0xe9, + 0xb,0x9b,0xbe,0x68,0xf2,0x6a,0xb6,0x7b,0xa8,0x9f,0xb4,0xd0,0x38,0xed,0xf8,0x9d, + 0x8c,0x83,0x8,0x22,0x2b,0x10,0xd7,0x3e,0x15,0xf2,0x59,0x7a,0xe3,0xd2,0x34,0xbe, + 0x7f,0x63,0x9e,0xae,0xcc,0x8d,0x7a,0xf,0xab,0x3c,0x60,0xf3,0xd9,0x34,0xae,0xcc, + 0x8d,0xd1,0xe2,0xe6,0x21,0xee,0x3c,0xdb,0x6,0x2b,0xf3,0x5c,0x40,0xb0,0x67,0xcd, + 0x2e,0x9d,0x2c,0xe5,0x9d,0xc5,0x8,0x40,0xbe,0x39,0x28,0x8,0x8c,0x99,0xd1,0x2a, + 0xde,0xbc,0x32,0x45,0xff,0xea,0x3b,0x17,0xe8,0x8d,0x8b,0xd3,0xde,0xf7,0x95,0xdf, + 0x5f,0x32,0x80,0x99,0x19,0xaf,0x2c,0x8c,0xd3,0xf3,0x8d,0x3,0xfc,0xcd,0x47,0xf, + 0x8,0xed,0x1e,0xcb,0x71,0xc3,0x22,0xf,0x6,0xf0,0x51,0x64,0x2d,0x3f,0x9d,0xa9, + 0xa2,0xb5,0x4b,0x62,0x93,0x6b,0x47,0x1e,0xad,0x88,0xdc,0xee,0x3f,0x3a,0xa9,0x3a, + 0x46,0xbc,0xae,0xe8,0xec,0xec,0x8d,0x6c,0x26,0x1e,0xb0,0x7f,0xd4,0xe4,0xfd,0xa3, + 0x53,0xdc,0x5d,0xda,0x25,0x45,0x84,0x2b,0x67,0x46,0xf8,0xda,0xfc,0x18,0x5d,0x9d, + 0x1f,0xc5,0xd9,0xc9,0x2a,0xc6,0xaa,0x3,0xc8,0x67,0xd3,0x48,0xa7,0x53,0xc8,0x28, + 0x42,0x2e,0x9b,0xb2,0xba,0xdc,0x7e,0x7e,0xf1,0xb2,0xe0,0x7f,0xd3,0xde,0xf9,0x45, + 0xc5,0x3d,0x7a,0x6f,0x31,0x33,0xa6,0x46,0x6,0xf1,0xbd,0xeb,0x67,0x70,0x6f,0x79, + 0x7,0xbd,0xde,0xa,0xad,0xef,0x1d,0x99,0xeb,0x65,0xbc,0xe,0xc4,0xc8,0xa0,0xf1, + 0x5e,0xc9,0x71,0x74,0x44,0x1c,0xa2,0xd8,0x34,0xe1,0x7,0x3c,0xa7,0x55,0xa,0x93, + 0x23,0x83,0x34,0x33,0x3a,0x98,0xa8,0xd3,0x97,0x3f,0xe7,0x69,0xab,0x83,0xe5,0xad, + 0x3,0x2c,0x6f,0xd5,0xb9,0xdd,0x9,0x1c,0xec,0x66,0xa3,0x50,0xd,0xd,0x49,0x16, + 0x3b,0xa5,0x19,0x9b,0x1c,0xe5,0x85,0xb2,0xf3,0x87,0x65,0xdf,0x68,0xc7,0x5f,0xe1, + 0xc1,0xf9,0x17,0x2a,0xcf,0x14,0x4a,0xdb,0x97,0x92,0xc1,0xd8,0x58,0x59,0x93,0x44, + 0x63,0x8e,0x6b,0x37,0x3d,0xb9,0x6c,0x6,0x37,0xcf,0x8d,0xd3,0x9f,0x7e,0xe7,0x2, + 0xbd,0x7a,0x6e,0xc2,0x33,0x4f,0x91,0xaf,0xa1,0x74,0x3e,0x5b,0xde,0xae,0xe3,0xc3, + 0x7b,0x2b,0xb8,0xfd,0x74,0x8b,0x9b,0xad,0xae,0xb7,0x69,0x35,0x5,0xc0,0x77,0xff, + 0xf7,0x2f,0x33,0xb3,0x33,0xe9,0x62,0x9f,0xb1,0xef,0x78,0x8a,0x8c,0x10,0x51,0x16, + 0x1e,0x5,0x43,0x83,0x39,0x9c,0x9f,0x1e,0xc2,0x70,0xb9,0xe0,0x31,0xef,0x5f,0xe4, + 0xa9,0x1f,0x3d,0x8f,0x5e,0x24,0xc9,0x34,0x9f,0x23,0xef,0xed,0x5e,0x2f,0x40,0xab, + 0x13,0xe0,0xe4,0xb4,0x8d,0xfd,0xe3,0x26,0x16,0x37,0xf,0xf0,0xf1,0xfd,0x35,0x7c, + 0xfe,0x68,0x1d,0x8f,0xd6,0xf6,0xd,0x91,0x91,0xcd,0x95,0x77,0x6,0x58,0x62,0x6e, + 0x65,0xb6,0xa8,0xa4,0xd7,0x97,0x87,0x95,0xdd,0xea,0xc1,0x45,0xd7,0xce,0x6c,0x82, + 0x55,0x42,0x48,0x31,0x70,0x91,0xa7,0xa4,0x9d,0xe1,0x82,0x40,0xe7,0xb4,0x4,0xa1, + 0xef,0x71,0xc0,0xc4,0x14,0x32,0xdc,0x29,0xb0,0xf6,0xb0,0xac,0x29,0x95,0x26,0xd1, + 0x8f,0x15,0x6b,0x27,0x42,0x9b,0xda,0x66,0x7f,0x20,0x63,0x93,0x2f,0x87,0x61,0xc1, + 0xe4,0x75,0xcf,0xf,0x47,0xf8,0xe,0x46,0x81,0x61,0x37,0x97,0x32,0x7c,0x85,0xe2, + 0x19,0xf3,0x24,0x88,0x93,0x24,0xc1,0x50,0x86,0x34,0x6a,0x93,0x63,0x5e,0x5a,0x4e, + 0x5d,0x51,0xf6,0xa4,0xef,0x4c,0x15,0x21,0x5e,0x88,0x94,0x15,0x91,0x82,0x6a,0xdf, + 0xa7,0xa8,0x1c,0x2b,0x69,0x27,0x4b,0x2e,0x7d,0x39,0x1e,0x7a,0xaa,0xbc,0xc9,0xdc, + 0xa3,0xe1,0x92,0xe5,0xc0,0x11,0xa7,0x42,0x28,0x9c,0x4c,0x41,0xd6,0xa5,0x5e,0xdb, + 0xaf,0x2b,0xcd,0x6d,0xb1,0x90,0xbb,0x8e,0x39,0x57,0xba,0x23,0x37,0x6d,0x41,0x68, + 0x79,0x23,0x2,0x5b,0x74,0xc8,0xa,0x99,0x1,0xcb,0xac,0x97,0x75,0xe3,0x41,0xf9, + 0x4c,0xa,0x57,0xe6,0xc6,0xe8,0xcf,0xbf,0x7b,0x49,0xdd,0x38,0x37,0x4e,0xa3,0x95, + 0x12,0x4a,0xf9,0xc,0xa,0x9,0x5a,0xe6,0xe8,0x81,0xdb,0x6f,0x57,0xda,0xee,0x74, + 0x71,0x77,0x69,0x1b,0x4f,0xd6,0xf,0x10,0x90,0xf0,0xdb,0xd6,0x87,0x56,0xe8,0xde, + 0x15,0x69,0xb6,0xf4,0xcb,0x54,0x2b,0xe5,0xf1,0xd3,0x6f,0x9d,0xa3,0xb7,0xaf,0xce, + 0x24,0x3e,0x80,0x6e,0xa6,0x61,0xe4,0x32,0x29,0xe4,0xb2,0xa9,0xc8,0xd9,0xec,0x4d, + 0xdd,0x31,0xbd,0xe,0x79,0xc7,0x8e,0xff,0x42,0x9e,0x99,0xa8,0xd2,0xf,0x5f,0x5d, + 0xc0,0xbf,0xfb,0xfe,0x35,0x9a,0x1a,0x1e,0x88,0xfd,0xee,0xdc,0x87,0xb9,0xad,0x94, + 0x42,0xa9,0x90,0x42,0xb5,0x5c,0x80,0xa2,0x94,0xd3,0x8c,0x47,0x48,0x42,0x6e,0x1b, + 0xee,0xfc,0x90,0x5d,0x67,0xe8,0x24,0x77,0x4,0x6,0x2,0x3,0xdf,0xd9,0x75,0x81, + 0x90,0x33,0xfb,0xac,0x68,0x2f,0x9,0x90,0x9c,0x7c,0x82,0xc3,0x4c,0xb1,0x30,0x93, + 0xc9,0x4d,0x69,0xa1,0xc6,0x85,0x81,0x47,0xab,0x7b,0x58,0xda,0x3e,0xe2,0x5f,0x7f, + 0xb5,0x88,0x52,0x31,0x4b,0x23,0xe5,0x12,0x2e,0xcc,0xd4,0x70,0x6e,0x72,0x8,0xb3, + 0x63,0x15,0xcc,0x4f,0x54,0x31,0x51,0x2b,0xc6,0xe,0x50,0xd9,0xe0,0xf4,0xbb,0x3f, + 0xfe,0x6b,0xde,0xe4,0xd7,0x35,0x87,0xec,0x68,0xad,0x84,0xff,0xf6,0x7,0xd7,0xa9, + 0xd3,0xd,0xf8,0xef,0x3f,0x7a,0x64,0x7d,0x50,0x59,0xa4,0xe7,0x59,0x1a,0x84,0xf4, + 0x88,0x88,0x7a,0x4a,0xc7,0x49,0x99,0x96,0x16,0x97,0xcf,0xa4,0x70,0x76,0xb2,0x86, + 0xa9,0xa1,0xf2,0xb,0xf9,0x4,0xe6,0x67,0x5b,0xde,0xa9,0xe3,0xf3,0xc7,0x9b,0x38, + 0x68,0x9c,0x5a,0xab,0x5e,0x69,0x7,0x68,0xae,0x7d,0x98,0x30,0x1c,0xc6,0xc0,0x9, + 0xb8,0x39,0x7c,0xf1,0x2,0xb8,0x50,0x2d,0x83,0x7a,0xb2,0xdc,0x47,0x3,0xf1,0xa0, + 0x49,0x7d,0xe4,0x8a,0x1c,0x5e,0x23,0xad,0x21,0x21,0x44,0xb7,0xa6,0xf4,0xca,0x9f, + 0xb7,0xb2,0xd9,0x34,0xfe,0xe2,0x9d,0x4b,0xf4,0xa3,0xd7,0x16,0xe8,0xfa,0xfc,0x28, + 0xaa,0x3,0x79,0x6f,0x32,0x4f,0x6a,0xac,0x4e,0xdb,0x5d,0xfc,0xee,0xee,0xa,0xfe, + 0xf7,0x7f,0xba,0xc5,0xab,0x3b,0x47,0x90,0xe1,0x21,0x14,0xc1,0x2b,0x89,0xbd,0xcd, + 0x86,0xe8,0x5c,0x1c,0xf9,0x90,0x12,0x64,0x50,0x6e,0xad,0xa9,0x20,0xd,0x3e,0xc6, + 0x6b,0x65,0xbc,0x7a,0x6e,0x2,0xb5,0x81,0xc2,0xbf,0xf8,0xfa,0x27,0x89,0x15,0xcf, + 0xcc,0x38,0x6c,0xb4,0x71,0x67,0x71,0xb,0x9f,0x3e,0x5c,0xc3,0xed,0xa7,0xdb,0x58, + 0xde,0xa9,0xa3,0xd9,0xee,0xa2,0xd9,0xea,0x3a,0x3e,0x95,0xcc,0xac,0xa0,0x88,0xb0, + 0xcb,0x65,0x87,0x58,0x6b,0xa,0x9b,0x92,0x66,0x7d,0xd5,0x49,0x7b,0xb4,0xdb,0xc8, + 0x33,0xed,0x4,0x17,0xa6,0xa8,0xd9,0xf4,0x3d,0x6d,0xef,0x6a,0x24,0x6a,0xe1,0x18, + 0x6e,0xe4,0x66,0x30,0xc0,0xa7,0x6,0xd5,0x35,0xf8,0xe,0x5,0xa,0xc9,0x19,0x1c, + 0xfe,0x5b,0x65,0x3b,0x6e,0x97,0x83,0x4d,0x56,0x61,0x21,0x83,0x9f,0x24,0x55,0x8c, + 0x22,0x6b,0x10,0xc7,0x85,0x10,0xcc,0x4c,0x6f,0xfc,0x66,0x2f,0xd7,0x24,0x9e,0x31, + 0x4f,0x11,0x7f,0x6d,0x19,0xa4,0x45,0x9e,0xd3,0x11,0xb1,0xf4,0x72,0xb7,0xf,0x83, + 0xf,0xdf,0xc4,0xb2,0x9d,0x25,0x1c,0x46,0x11,0x5b,0x3b,0xc9,0x42,0xd2,0xa3,0x80, + 0x95,0x10,0x7a,0x34,0x6c,0x86,0xdf,0xb3,0x38,0xa8,0xc8,0x18,0x84,0x90,0x51,0x51, + 0x99,0x24,0x35,0x49,0x64,0x31,0x16,0x64,0x46,0x4e,0x96,0x52,0x8a,0xcc,0xb2,0x82, + 0xf4,0xfb,0xca,0x4c,0xdf,0xa4,0xf4,0x39,0xad,0xf7,0xe5,0xa1,0x22,0x5d,0x53,0xe2, + 0x48,0xd3,0xee,0xf4,0x5e,0x5d,0x14,0x74,0x67,0xc1,0x22,0xb1,0x37,0xca,0x65,0x14, + 0x16,0x26,0x6b,0x74,0x75,0x6e,0x8c,0x5e,0xbb,0x30,0x41,0x6f,0x5f,0x3b,0x43,0x53, + 0xc3,0xe5,0xd8,0x4e,0x3c,0x2a,0x4b,0x8a,0xea,0x52,0xe5,0xdb,0x49,0xb3,0x8d,0x9d, + 0xc3,0x6,0x3e,0x7b,0xb4,0x86,0x67,0x9b,0x7,0xe8,0x72,0x10,0xe1,0xc8,0xcb,0x46, + 0x87,0x22,0xb4,0x38,0xc6,0x50,0xb9,0x88,0x1b,0xe7,0x27,0x70,0x71,0x66,0x4,0xc5, + 0x7c,0xd6,0x23,0xa8,0xc4,0x27,0x38,0x60,0x65,0xbb,0x8e,0xf5,0xdd,0x13,0x71,0x87, + 0x52,0x4,0x2a,0x62,0x13,0xf4,0x11,0x67,0x62,0x8a,0xf,0x67,0x33,0x29,0x9a,0x1f, + 0xaf,0xe2,0x7,0xaf,0xce,0xe1,0xdd,0x9b,0xf3,0x74,0x66,0xbc,0x92,0x88,0x46,0xc8, + 0xc2,0x26,0x89,0x52,0xe6,0xdb,0x1b,0x96,0x30,0xd9,0xd6,0x57,0xec,0x68,0xad,0x67, + 0x35,0x83,0x35,0xbc,0x26,0x44,0xef,0x4e,0xcb,0x64,0xee,0x35,0x65,0xfc,0x76,0x59, + 0x30,0xf4,0xad,0xb9,0x27,0x33,0xc2,0xf3,0x9a,0xc5,0xfa,0x96,0x85,0x23,0x8b,0x75, + 0x52,0xa3,0x18,0x3d,0xc0,0xaa,0x82,0xda,0x3d,0x46,0xa7,0xd9,0xc6,0x51,0x13,0xa0, + 0xc3,0x26,0x3f,0xdf,0x38,0xa4,0x8d,0xfd,0x13,0x3c,0x59,0x3f,0xc0,0x64,0x6d,0x0, + 0xa3,0xd5,0x12,0x86,0x7,0xb,0x18,0x2a,0x17,0x50,0x2e,0xe6,0x50,0xca,0xa7,0x31, + 0x50,0xc8,0xa1,0x98,0xcf,0xa0,0x98,0x4d,0xa3,0x54,0xc8,0x20,0x97,0x49,0x7b,0xf7, + 0x43,0x12,0x7b,0x3e,0xda,0x0,0xf4,0x83,0x37,0xa3,0xbe,0xd8,0x44,0x84,0x62,0x2e, + 0x83,0xab,0x73,0xa3,0xb8,0x72,0x66,0x84,0x7e,0xf7,0xf5,0x2a,0x1f,0x1c,0x35,0xbd, + 0x2f,0x1c,0x6d,0xa0,0x9d,0x81,0x45,0xbf,0x42,0xee,0xdb,0x5a,0x11,0x42,0x17,0xb2, + 0x8b,0xb3,0xc3,0x34,0x3e,0x34,0xd0,0xb7,0x61,0x95,0x3f,0xfb,0xea,0xce,0x11,0x3e, + 0x79,0xb0,0x86,0xfd,0xe3,0xb6,0x48,0xe3,0x14,0xec,0xf6,0xd8,0xa4,0xed,0x84,0xb9, + 0xa4,0x53,0x5b,0xb4,0xe9,0x10,0x2b,0x10,0x5,0xde,0x81,0xc7,0xba,0xe,0xb3,0xe7, + 0xce,0xcc,0x16,0x65,0x60,0xb1,0x3d,0x52,0xd6,0x51,0x82,0x99,0xc3,0x38,0x63,0x37, + 0xca,0xdb,0x45,0x4c,0x3a,0x45,0x74,0x66,0xac,0x82,0xd7,0xce,0x4f,0xd2,0x8f,0x5f, + 0x3f,0x4b,0x37,0x17,0xc6,0x30,0x50,0xcc,0x7a,0xc8,0x97,0xf9,0x1d,0xe5,0x3d,0x7e, + 0x78,0xd2,0xc2,0x7,0x5f,0x2f,0xe3,0xfd,0x5b,0x4b,0xfc,0x7c,0xab,0x1e,0x9e,0x6c, + 0xe4,0xfb,0x2c,0x24,0x60,0x1e,0x1e,0x9b,0x88,0x5,0x28,0xb,0x19,0x89,0x19,0xdb, + 0xc0,0xfb,0xc6,0x38,0xc4,0xc0,0x58,0xb5,0x84,0x1b,0x9a,0xa4,0x68,0x5e,0x87,0xff, + 0x1a,0x4,0xe8,0x45,0xa8,0xd0,0x51,0xa3,0x85,0xfd,0xe3,0x53,0xec,0xd6,0x9b,0xd8, + 0xd8,0xb,0xd,0x9a,0x1e,0xae,0x86,0x1a,0xfb,0x67,0x1b,0x87,0xa1,0x80,0x82,0x22, + 0x6a,0x27,0x8b,0x32,0xb,0x2b,0x5f,0x57,0xe0,0x4d,0x51,0xb5,0x9f,0x20,0xcc,0xc5, + 0xcc,0x3,0x6d,0xf5,0xe1,0xa1,0xbf,0xb1,0x91,0xb3,0x69,0xa8,0x8e,0x55,0xe8,0x8, + 0x17,0x3e,0xc5,0xa1,0x79,0x8c,0xb6,0x77,0x25,0x36,0x4,0x39,0xed,0xff,0x6f,0xa6, + 0x79,0xdd,0x39,0x99,0x6c,0xb,0x8d,0xcf,0x68,0x8f,0x22,0xcb,0x16,0x77,0x63,0x8c, + 0x45,0x2,0x63,0x91,0xf4,0xce,0xe5,0x33,0x6a,0x93,0xe,0x2f,0x15,0xc1,0xb2,0x38, + 0x95,0x8a,0xec,0x4a,0x22,0x48,0xba,0x3,0xd2,0x94,0xad,0xa1,0x32,0xc4,0x8b,0xe0, + 0xdf,0x53,0xa4,0x2c,0x29,0x8e,0xc0,0x91,0xc3,0x5a,0xba,0xa,0xb2,0x2f,0xa,0x8f, + 0x7,0xc3,0xa9,0x48,0xd6,0x97,0x64,0x6c,0xda,0xdd,0x3c,0x5c,0xe5,0x17,0x39,0x71, + 0x24,0x1e,0x48,0x73,0x90,0x3a,0xe2,0x92,0x70,0x82,0x83,0x95,0xa0,0x85,0x93,0xb9, + 0xb2,0x2d,0xb7,0x2e,0xba,0x29,0x2b,0x43,0xd3,0x9,0xdd,0x3a,0x6c,0x25,0xfc,0xaf, + 0x81,0xdd,0x59,0xc8,0xd5,0xc2,0x2f,0xa5,0xf3,0xce,0xd,0x95,0x94,0x84,0xaf,0x26, + 0xd9,0x10,0x45,0x3b,0xb5,0x9e,0x9f,0x1d,0xa1,0x3f,0x7b,0xeb,0xa2,0xfa,0xfe,0x8d, + 0x39,0x5a,0x98,0xac,0x7d,0x23,0x43,0xb9,0xdf,0x81,0xdc,0xeb,0x5,0x68,0x75,0xbb, + 0x38,0x6e,0xb4,0xb1,0xbe,0x77,0x8c,0xdf,0xdc,0x5e,0xc2,0x7,0x5f,0x2f,0xf3,0xd6, + 0x7e,0xc3,0x5f,0x26,0xc6,0xb8,0x8,0x52,0x61,0x10,0x2,0xcc,0xd7,0xe7,0x47,0xf1, + 0xee,0xcd,0x39,0x1a,0x28,0x66,0x13,0xf,0x18,0x79,0xd8,0x36,0x5b,0x5d,0x7c,0xf1, + 0x64,0x93,0xef,0x2c,0x6e,0x1,0x81,0x5b,0x2e,0x30,0x4b,0xe1,0x32,0xc5,0x64,0x70, + 0x1c,0x53,0x50,0x86,0x2c,0xda,0x1f,0xbc,0x3a,0x87,0xbf,0x7a,0xe7,0x32,0x4d,0x8f, + 0xc,0xbe,0xb4,0x1,0x4b,0xf4,0xc0,0xef,0x6,0x9e,0x47,0xbf,0x7e,0xbe,0xf4,0x2d, + 0xab,0xcc,0x3e,0x26,0xc4,0xdd,0x29,0x30,0x9b,0x52,0x12,0xd4,0x29,0x5,0x97,0xf1, + 0x42,0x7e,0x9b,0xe8,0x49,0xa6,0x15,0xd9,0x65,0x2b,0x91,0x73,0xc1,0x25,0x15,0x4d, + 0x85,0x3,0x47,0xf3,0x50,0xc9,0xef,0x9d,0xbd,0xdc,0x1,0x2,0x56,0x76,0xeb,0x58, + 0xd9,0xad,0xcb,0x79,0x12,0xb5,0x81,0x3c,0xc6,0x6a,0x3,0x38,0x33,0x36,0x88,0xc9, + 0xa1,0x1,0x4c,0xf,0x97,0x31,0x3e,0x54,0xc2,0xd4,0xd0,0x0,0xc6,0x87,0xca,0x18, + 0xc8,0x67,0x90,0x4e,0xa9,0xbe,0xd7,0xa5,0x5f,0x51,0xef,0xf7,0x16,0x25,0x5d,0x12, + 0x11,0xe6,0x27,0xaa,0x78,0xfd,0xc2,0x4,0x3e,0x7d,0xb4,0x8e,0xc3,0x93,0x53,0xc3, + 0xed,0x24,0x4b,0x98,0x96,0x9b,0x9b,0x68,0x6a,0x2d,0xb,0x52,0x5c,0xd4,0xa1,0x8d, + 0x80,0x72,0x31,0x4b,0x17,0x67,0x86,0x31,0x5e,0x2b,0x25,0xae,0xe,0xa2,0xf7,0xc1, + 0xca,0x56,0x1d,0x5f,0x3d,0xdb,0xe4,0xe3,0x66,0x3b,0xe2,0x4f,0xa7,0x24,0xec,0xe8, + 0x9c,0xec,0xec,0x49,0x6e,0xb7,0x6e,0x9a,0x1,0xcd,0xc6,0xc,0x89,0xc8,0xb1,0xbf, + 0x3d,0x7b,0x68,0xb2,0x1e,0xf4,0x24,0x5d,0x35,0xc2,0x7a,0xad,0xcc,0xfe,0xdd,0xb5, + 0xf0,0x96,0x13,0xa0,0x6f,0xf4,0x4c,0x5a,0xd1,0xd4,0x50,0x19,0x7f,0xfa,0xd6,0x5, + 0xfa,0xab,0x77,0x2e,0xd1,0xc8,0x60,0x1,0xe9,0x74,0x2a,0xd6,0x94,0x47,0x57,0x27, + 0x40,0x68,0x94,0xf2,0xd7,0xbf,0xfa,0x9a,0xbf,0x5e,0xdc,0x36,0x96,0x3e,0x16,0x31, + 0x22,0x90,0x47,0x36,0xb5,0xa7,0xbd,0x8,0x7b,0xf3,0x1d,0x21,0x34,0x20,0x41,0x31, + 0x5f,0xce,0x58,0xef,0x65,0xce,0xd2,0x89,0xa1,0x1,0x5c,0x9c,0x1d,0x46,0xb9,0x98, + 0xfd,0x67,0x3d,0x93,0xff,0x9c,0xb7,0xc3,0x93,0x16,0xbe,0x7c,0xbc,0x81,0xdf,0xdd, + 0x5b,0xc5,0xad,0xa7,0x5b,0x58,0xdf,0x3b,0x46,0x2f,0x70,0xc9,0xcb,0xb6,0x2f,0x62, + 0xb9,0x57,0x60,0x1d,0x74,0xa3,0x3c,0x29,0x22,0xb,0x56,0xb5,0x70,0x9e,0x60,0x76, + 0xc1,0x2a,0x32,0x51,0x59,0x17,0x64,0x63,0xf9,0xea,0x1c,0xe0,0xb4,0x40,0xdc,0xb1, + 0xdc,0x39,0xfc,0x38,0x21,0xd0,0xde,0xed,0xa1,0xa5,0xab,0x7e,0x45,0x38,0x80,0xcd, + 0xd9,0xe,0xf5,0xed,0x8a,0x39,0x8,0x2c,0x45,0x87,0x99,0xc8,0x57,0xf1,0x32,0x9b, + 0x4,0x6e,0xc8,0x90,0x33,0x8e,0x12,0xd5,0x64,0x73,0x26,0xce,0x8,0x12,0xd7,0xc6, + 0x1f,0xe7,0x1d,0x81,0x93,0x38,0x42,0x5b,0x27,0x3f,0xd6,0xdc,0x6f,0xf1,0xcc,0x59, + 0xe7,0x9e,0x39,0x4b,0x8a,0x33,0xce,0x9f,0x2a,0xc6,0xb0,0x73,0x18,0xbe,0x47,0x6a, + 0x26,0x27,0x4,0x26,0x16,0x58,0x89,0x35,0x29,0x62,0x38,0x8e,0x99,0x74,0x85,0xb3, + 0xd4,0x5a,0x21,0xf4,0x22,0xeb,0xff,0x66,0x1d,0x2f,0x34,0x2e,0xa2,0x8c,0xf,0xbb, + 0x7e,0xfe,0x94,0xd9,0x73,0xb,0x83,0x18,0x3,0xb3,0x93,0x49,0x68,0x20,0x3b,0x89, + 0x2b,0x63,0x28,0xa3,0x44,0xf8,0x8a,0x2d,0xe6,0x9e,0x53,0x94,0x9c,0xce,0x25,0xd1, + 0x37,0xfc,0xf4,0x5a,0x39,0x47,0x3f,0x7e,0xfd,0x2c,0x7d,0xe7,0xca,0x34,0x5d,0x3e, + 0x33,0x42,0xd3,0xc3,0xe5,0xbe,0x26,0xb,0x49,0xd3,0xc9,0xce,0x61,0x3,0xab,0x3b, + 0x75,0xac,0xed,0x1e,0x63,0x6d,0xf7,0x8,0xdb,0x87,0xd,0xd4,0x1b,0x2d,0x34,0x4e, + 0x43,0xdf,0xee,0xd5,0xdd,0x23,0x6c,0xee,0x9f,0xa0,0xd5,0x9,0x3c,0x6d,0x7e,0x8c, + 0xde,0x68,0xaf,0x67,0xf8,0x39,0x69,0x5,0x5c,0x9d,0x1b,0xa7,0xef,0x5c,0x99,0x45, + 0xa5,0x98,0x8b,0x91,0x90,0x64,0x53,0xd1,0x38,0xed,0xe0,0xe1,0xea,0x1e,0x1e,0xae, + 0xec,0x62,0xa7,0x7e,0x2a,0xc8,0xbf,0xf0,0xac,0x55,0xbd,0xda,0xe6,0x71,0x21,0xc2, + 0x1f,0x2a,0x9b,0x56,0xb8,0x3a,0x3f,0x86,0x3f,0x7e,0xe3,0x2c,0x7d,0xef,0xfa,0x2c, + 0xa6,0xf4,0xb5,0xf8,0xe7,0xe8,0xb4,0x43,0xb8,0x32,0x6c,0x30,0xf6,0xea,0xd,0xaf, + 0xa0,0x7b,0xb8,0xaf,0xe1,0x41,0x69,0x8b,0x44,0x56,0x1,0x9c,0xd3,0x6,0xb1,0xc, + 0x75,0x84,0x4d,0xc3,0x21,0x89,0x50,0xd9,0x7d,0x57,0xd8,0x7c,0x2a,0x9b,0xf8,0x1e, + 0xf3,0x1b,0x25,0x49,0x6c,0x26,0x6d,0x10,0x65,0xb2,0x48,0x49,0xb8,0x79,0x13,0x45, + 0x30,0x69,0xcf,0x2,0xc2,0x74,0xe1,0x7b,0x47,0xa7,0x38,0x3e,0xed,0x60,0xfb,0xf0, + 0x4,0xa5,0x5c,0x16,0xa5,0x42,0x6,0xa5,0x5c,0x6,0xf9,0x5c,0x6,0xa5,0x7c,0x6, + 0x3,0x85,0x2c,0x2a,0xc5,0x1c,0xaa,0x3,0x39,0xc,0x16,0x73,0x18,0x2c,0xe5,0x30, + 0x58,0xc8,0xa1,0x52,0xca,0xa1,0x98,0xcb,0xa0,0x56,0x2e,0x60,0xa0,0x90,0x49,0xe4, + 0x62,0xf4,0xbb,0xb6,0x51,0xa2,0xd2,0xfc,0x78,0x15,0xdf,0xba,0x3c,0x45,0x8f,0xd7, + 0xf7,0xb9,0x7e,0xd2,0x76,0xdb,0x36,0x52,0x8e,0x6d,0x15,0xc9,0x26,0x25,0x44,0x61, + 0x6b,0xb3,0x58,0x96,0x4,0x1a,0x46,0x3e,0x9b,0xc1,0xe5,0xd9,0x11,0x8c,0x55,0x4a, + 0x2f,0xe4,0x89,0x74,0xba,0x3d,0x6c,0xee,0x9f,0x60,0x79,0xe7,0x8,0x47,0x8d,0x76, + 0x3c,0x3b,0x17,0x9e,0x9b,0x50,0x4,0x1e,0xb4,0x96,0x8b,0xfa,0xc7,0x61,0xf7,0x1f, + 0x65,0xc8,0xc6,0xe4,0x1b,0x1d,0x92,0x58,0xb6,0x9b,0xfd,0x82,0x4,0xda,0x3c,0x2b, + 0x2e,0x21,0x44,0xd5,0x3f,0xca,0xf4,0xc8,0x0,0x5e,0x3f,0x3f,0x41,0xdf,0xbd,0x3a, + 0x8b,0x1b,0x67,0xc7,0x68,0x5c,0x18,0xab,0x7c,0x53,0xc0,0xc9,0x7b,0xb7,0x9e,0xe3, + 0x9f,0x3e,0x5f,0xe4,0xa7,0xeb,0x7,0xdc,0xe9,0xb1,0x60,0x74,0x38,0xc6,0x36,0x9, + 0x67,0x2f,0x39,0x3c,0xb1,0x74,0xb0,0x91,0xa8,0xa5,0x16,0xe8,0xc9,0xb6,0x32,0x52, + 0x42,0x18,0x60,0xa4,0x88,0xa8,0x36,0x90,0xc7,0xe4,0x70,0x19,0x95,0x52,0x2e,0x51, + 0x15,0xf1,0x2f,0x5,0xbb,0x2b,0x15,0x2a,0x16,0x16,0xb7,0xea,0x58,0xd9,0x3d,0x6, + 0x18,0xd1,0x55,0xaa,0x54,0x93,0xc0,0xbd,0xa,0x70,0x66,0x41,0x2c,0x86,0x56,0x6d, + 0x61,0xca,0x96,0x4a,0x21,0xdd,0xef,0x5c,0x9c,0xa9,0xf6,0x79,0x61,0xc3,0x20,0xd0, + 0x45,0x3d,0x94,0xc2,0x98,0xec,0x73,0x3d,0xbd,0x87,0x5f,0x8e,0x58,0xef,0xd7,0x99, + 0xc8,0xb1,0xe1,0xd9,0x4c,0xe1,0x6,0xd5,0xf,0x1b,0x2f,0x6f,0x32,0x27,0x29,0x8f, + 0x65,0xf6,0x6c,0x15,0xc9,0x6a,0xbd,0x85,0xbd,0xb5,0x20,0x91,0xa9,0x8,0xdf,0x89, + 0xe4,0x4,0x4c,0x24,0x32,0xcf,0x59,0x24,0x27,0xc6,0x1c,0x33,0x1c,0x91,0x40,0xc0, + 0xea,0xc6,0x32,0xd6,0xd3,0xab,0xdb,0x3c,0x74,0xf2,0x5,0xe0,0x2c,0xe3,0x84,0x2c, + 0xbe,0xaf,0x22,0x50,0x91,0xf9,0x7c,0x3f,0x81,0xdd,0xb7,0x36,0x25,0xb1,0xd3,0x12, + 0xb6,0x15,0x4a,0x79,0x9a,0x66,0xb2,0x8a,0x31,0x44,0x82,0xb2,0x52,0x9a,0x67,0xae, + 0xef,0x80,0x94,0xf1,0xc,0x21,0x6d,0x1e,0x63,0x64,0x67,0x5a,0x6f,0xe,0x41,0x72, + 0x13,0xc5,0x9c,0x28,0x61,0x7f,0xee,0xb2,0x44,0x48,0x3c,0xe9,0x9e,0xfb,0xbb,0x79, + 0xb8,0x33,0xe9,0x14,0x46,0x2b,0x5,0x7a,0xf5,0xfc,0x4,0xfd,0xd5,0x3b,0x97,0xe8, + 0xfa,0xfc,0x18,0x99,0x4e,0x3d,0x6a,0x69,0xe8,0x3b,0x7a,0x75,0xd1,0x68,0x77,0xd1, + 0x38,0xed,0x60,0xef,0xa8,0x81,0xa7,0x6b,0x7,0x78,0xb2,0xb1,0x87,0x67,0xeb,0x7, + 0x78,0xba,0x76,0x80,0xb5,0xbd,0x63,0x74,0x7a,0x3d,0x91,0x27,0x65,0xbf,0x88,0x20, + 0xbf,0x59,0x87,0xc,0x78,0xd6,0xf8,0x9a,0x74,0x9f,0x49,0x2b,0xcc,0x8c,0xc,0xd2, + 0x85,0x99,0x21,0x8c,0xd5,0x4a,0x1e,0x94,0x9d,0x74,0x0,0x3d,0x59,0xdf,0xc7,0x47, + 0xf7,0x56,0xb1,0xb2,0x7b,0x62,0xd,0xdd,0x10,0x63,0x5e,0x46,0x36,0x7c,0x4,0x8f, + 0x84,0x97,0x22,0xc2,0xc5,0xd9,0x61,0xfc,0xf8,0xf5,0x79,0x7a,0xf7,0xc6,0x1c,0x66, + 0xc7,0x6,0x13,0x77,0x6b,0x2f,0x73,0x28,0x74,0x7b,0x3d,0xac,0xee,0xd6,0xb1,0xb1, + 0xdf,0x8,0x3d,0x8c,0x8d,0x59,0x88,0xa4,0x57,0xc0,0xa5,0xc5,0xf9,0xe6,0xb2,0x64, + 0x38,0x71,0x2c,0xf8,0xce,0xb2,0x23,0x65,0x41,0xe6,0x34,0x11,0xa1,0xf2,0x1e,0x63, + 0x6f,0x70,0x37,0xe0,0x87,0x72,0x71,0x5b,0xee,0xf6,0x90,0x50,0x19,0x25,0x38,0xdc, + 0x23,0x62,0xb9,0xe9,0x8a,0x4a,0xbb,0x1b,0x60,0xb7,0xde,0xc2,0x2e,0x5a,0x9,0x82, + 0x13,0xc6,0x40,0x21,0x83,0x91,0x4a,0x9,0xa3,0x95,0x2,0x6a,0xe5,0x2,0x46,0xca, + 0x5,0xd4,0xca,0x79,0x54,0x4a,0x79,0xc,0xf,0xe6,0x31,0x5e,0x1b,0xc0,0x58,0xa5, + 0x88,0x6a,0x39,0x8f,0x6c,0x2a,0xa5,0xd3,0x3f,0xe9,0x1b,0xa7,0x74,0xd3,0xd0,0x8d, + 0xf,0x95,0x70,0xf5,0xcc,0x8,0xca,0xc5,0x3c,0x81,0xea,0xec,0xb2,0xb3,0x25,0x82, + 0x9e,0xb0,0x63,0x93,0x8d,0x95,0x3f,0x76,0xd8,0xbd,0x6d,0xb5,0x9c,0xc7,0xf4,0x48, + 0x19,0x25,0xdd,0x74,0xf4,0x73,0xb8,0x3b,0x6a,0x76,0x70,0xe7,0xf9,0x36,0x9e,0x6f, + 0xd5,0xc5,0xc5,0x57,0x3e,0xc9,0x93,0x3d,0x2e,0xbd,0x3d,0xd3,0xd9,0xa6,0xf1,0xb2, + 0x64,0x32,0xda,0x30,0xb8,0x58,0xc2,0x40,0xd4,0x72,0x83,0x64,0x79,0x24,0x8a,0x4, + 0xd7,0xb8,0x3e,0xf,0x40,0x36,0x97,0xa6,0xf1,0x6a,0x9,0x6f,0x5f,0x9d,0xa1,0xef, + 0x5f,0x9f,0xa5,0xef,0x5d,0x9f,0x49,0x8c,0xf9,0x4c,0x7a,0xb6,0x5a,0x9d,0x1e,0x16, + 0x37,0xe,0xf0,0x5f,0xbe,0x58,0xe4,0xf7,0xbf,0x7a,0xce,0xf5,0x46,0x1b,0x91,0x54, + 0x75,0xf7,0xbb,0x12,0x23,0x9a,0x6f,0xc9,0x90,0xd2,0x60,0x4b,0x54,0x94,0xc,0xe, + 0x93,0xe3,0x20,0xac,0xa0,0xe4,0x34,0x4f,0xc8,0xe7,0xd2,0x38,0x37,0x3d,0x84,0xe9, + 0xe1,0x72,0x6c,0xf5,0x17,0xcd,0x1d,0x4f,0x5a,0x1,0xf6,0xe3,0x78,0x24,0x21,0x48, + 0xf9,0x4c,0x1a,0xe3,0xd5,0x12,0x66,0x47,0xca,0x58,0xdd,0x3e,0xc2,0xd1,0x69,0x3b, + 0xe4,0x9a,0x8b,0x9f,0x47,0xd9,0x4a,0x6c,0xfc,0xa1,0x64,0x8a,0x10,0xb3,0x74,0x3a, + 0x52,0xd6,0xff,0xc0,0x90,0x1c,0x54,0x38,0x51,0x33,0x84,0xc7,0x78,0x10,0xa6,0xab, + 0x5,0x2e,0x5d,0x2d,0xfc,0x82,0x81,0x99,0xd4,0x9d,0x84,0x8d,0xc8,0x34,0x0,0x81, + 0x25,0x24,0x84,0xd6,0x83,0x2e,0x8a,0x17,0x6c,0x21,0x78,0xc7,0x44,0xf,0x23,0xcf, + 0x3c,0x37,0x4d,0xb6,0x56,0xaf,0xf2,0x9c,0xb4,0x16,0xd3,0x1c,0xad,0x89,0xe4,0x42, + 0xc7,0xbc,0x2b,0x61,0xd5,0xa2,0x76,0xdf,0xe4,0x37,0x7c,0x4,0xcf,0x21,0xe,0x88, + 0x36,0x63,0xe4,0x7,0xa,0x4a,0x14,0x95,0x84,0x97,0x3b,0xf7,0x11,0x90,0x59,0xb3, + 0x18,0x92,0xd4,0x29,0xf6,0xb9,0xea,0x76,0xea,0x96,0xbc,0x64,0x65,0x33,0x1a,0x7d, + 0xd6,0xb2,0x18,0x8,0x95,0x7e,0x88,0x95,0x43,0x34,0x59,0x59,0xca,0xbc,0x35,0x8f, + 0x62,0x8f,0x79,0x6e,0x25,0x68,0x66,0xda,0xd6,0x91,0xb0,0x21,0x8c,0xae,0xed,0xe3, + 0x54,0x78,0x77,0x84,0xbc,0x76,0xfd,0x99,0x51,0xa6,0xbb,0x4b,0x51,0xb3,0x39,0x2b, + 0x6c,0xcc,0x6a,0x6c,0xae,0x79,0x4a,0x11,0x16,0x26,0xaa,0xf4,0x97,0xdf,0xbd,0xa8, + 0x7e,0xf8,0xea,0x2,0x85,0x81,0x4,0xea,0x85,0x13,0x93,0xb9,0xd5,0x96,0x77,0xea, + 0xf8,0xe4,0xfe,0x1a,0x3e,0x7f,0xb2,0x81,0xc7,0x6b,0xfb,0x38,0x6a,0xb4,0xd1,0x6c, + 0x77,0xd0,0xed,0x85,0x11,0x8a,0x3d,0x23,0x61,0x61,0x3f,0x4b,0x5e,0x18,0xc4,0x3b, + 0xb3,0xc,0x5b,0xe4,0xd8,0x82,0x6,0x4,0x60,0xb4,0x5a,0xc2,0x1f,0xbc,0x72,0x6, + 0x33,0xa3,0xe5,0x44,0x98,0x36,0xfa,0x10,0x7e,0xfe,0x78,0x3,0x3f,0xfb,0xe4,0x9, + 0xe,0x4f,0x4e,0xe3,0x43,0x66,0xd4,0xc1,0x88,0x7d,0x9b,0x74,0x73,0xec,0xbc,0x71, + 0x69,0x8a,0x7e,0xf8,0xea,0x3c,0xfe,0xf8,0xcd,0x73,0x18,0xad,0x14,0xfb,0x1e,0x76, + 0x2f,0x3,0xb9,0xf7,0x2,0xc6,0xfa,0xde,0x31,0x36,0xf7,0x8e,0xd,0x81,0x82,0x41, + 0x46,0xe6,0x49,0x21,0x51,0x55,0xac,0x6e,0x38,0xa0,0x98,0xcd,0x91,0x34,0x7d,0x77, + 0xd6,0x66,0x48,0x82,0x1d,0x48,0x5c,0x44,0x6f,0x79,0xc4,0xa6,0x4c,0x18,0x9c,0x57, + 0x99,0x48,0x46,0x8,0x67,0x64,0x87,0xe3,0x33,0xa4,0x19,0x94,0x53,0x86,0x40,0x28, + 0x35,0x64,0xc5,0x90,0xbe,0xe,0x10,0xad,0x1a,0x93,0xc2,0xc9,0x69,0xf,0xad,0xee, + 0x31,0x36,0xf7,0x4f,0xa0,0x94,0x42,0x26,0x15,0x82,0x4e,0x69,0x22,0xa8,0x94,0x42, + 0x2e,0x93,0xc2,0xf,0x6e,0x9e,0xc1,0x1f,0xbd,0xb1,0x80,0xb3,0x13,0x35,0xc,0x68, + 0x8b,0xd1,0x97,0xd5,0x4,0xe7,0x33,0x69,0x8c,0x56,0x4b,0xc8,0x66,0x52,0xa2,0x10, + 0x21,0x9e,0x21,0xe0,0x5d,0x46,0x11,0x16,0x11,0xf1,0x44,0x37,0x9f,0x5b,0x2a,0x64, + 0x69,0x6a,0xa8,0x8c,0x1,0x91,0x7b,0xdd,0xef,0xed,0xb8,0xd9,0xc2,0x27,0xf,0xd6, + 0xb1,0xb4,0x7d,0x28,0xe0,0xf5,0xe8,0x2e,0xc7,0xe1,0x30,0x32,0x88,0x85,0xac,0xdb, + 0x95,0x22,0x7,0x7b,0x3a,0x74,0x9a,0x88,0x22,0xf1,0x18,0xc9,0x4c,0x3e,0x7f,0xee, + 0x89,0x7a,0x5b,0x30,0x8a,0xb9,0xc,0xfd,0xc1,0x2b,0x67,0xe8,0x8f,0xdf,0x5c,0xc0, + 0x85,0xa9,0x1a,0x8d,0x55,0x4b,0xb1,0xb5,0xd5,0x8b,0x62,0x76,0x3f,0x7e,0xb0,0x86, + 0xff,0xe7,0x83,0x7,0x7c,0xfb,0xe9,0x36,0x1f,0x36,0x5b,0x6e,0x2d,0x24,0x8f,0x7d, + 0x4b,0x8a,0x93,0x33,0x83,0xc4,0x69,0xc9,0xf3,0xb4,0x83,0x7,0x47,0xd8,0x9f,0x9c, + 0xe5,0xe9,0x2e,0x6f,0x83,0x42,0x2e,0x8b,0xcb,0xb3,0x23,0x98,0x18,0x2a,0xbd,0x70, + 0x55,0xd3,0x4f,0x2f,0x9e,0x64,0x62,0xd4,0x8f,0x14,0x57,0x29,0xe5,0x70,0xf3,0xdc, + 0x38,0x86,0x6,0xb,0xb8,0x3c,0x3b,0x8c,0xbf,0x7e,0xef,0x1e,0xb6,0xe,0x9a,0x31, + 0xaf,0x71,0x37,0xd0,0x45,0x3c,0x4b,0xc4,0x9a,0xd7,0xba,0xc0,0x9,0xfb,0x54,0x69, + 0x6e,0x64,0x18,0xb1,0x6c,0xa2,0x52,0xd,0x57,0x35,0xd0,0x8b,0x7a,0x56,0x1c,0x84, + 0x3c,0x5,0x6,0x98,0x3,0x92,0x96,0xb0,0xfa,0xca,0x7,0x5a,0x96,0xa6,0x34,0xdf, + 0x46,0xbb,0xca,0x19,0xdd,0xbb,0x26,0x61,0xda,0x9d,0xb9,0x48,0xeb,0x66,0x8f,0xc7, + 0x14,0xa7,0xf1,0x79,0xea,0x2d,0xb3,0xbf,0x22,0x19,0x4e,0x22,0x12,0xf0,0xc,0x64, + 0x1f,0x11,0x8b,0xf8,0x13,0x78,0xc,0x1a,0x8d,0xb,0xd5,0xcc,0xf4,0xee,0x40,0x36, + 0xcd,0x72,0xb7,0xd1,0x5c,0x92,0xcd,0x9c,0xb8,0xad,0x85,0x10,0xe8,0x1,0x3e,0x49, + 0xc3,0xc0,0xef,0x22,0x15,0xd,0x11,0x82,0xa,0x27,0x13,0xec,0x9c,0xbd,0xa2,0x15, + 0x7f,0x8a,0x27,0xcd,0x4,0x30,0xeb,0xb9,0xda,0xec,0xc6,0xc3,0xb8,0x34,0xe3,0xec, + 0xa6,0x8b,0xb4,0x49,0x49,0x53,0x26,0xea,0x54,0xbb,0xc4,0x69,0xa6,0x3b,0x19,0xa3, + 0x19,0x3b,0x7b,0x29,0x2f,0x21,0xcd,0xfa,0xca,0x84,0xa7,0x72,0x75,0x20,0x47,0xd7, + 0xe7,0xc7,0xe8,0x3b,0x57,0xa7,0xe8,0xdd,0x57,0xe6,0x68,0x76,0x6c,0xb0,0x6f,0x24, + 0xa2,0xf9,0xd8,0xfe,0xd1,0x29,0x96,0x77,0xea,0x78,0xb2,0xb6,0x87,0x47,0xab,0x7, + 0x16,0xde,0x3e,0x38,0x6e,0x45,0x77,0x62,0x0,0x29,0x93,0xe8,0x64,0xad,0x70,0x9d, + 0x19,0x86,0xd0,0xb4,0x44,0x53,0xea,0xc5,0xc9,0x3b,0x5e,0x2d,0xe1,0xed,0x2b,0xd3, + 0x98,0x19,0xad,0xc4,0xa,0xaa,0xec,0xc2,0x4f,0x3b,0x5d,0x3c,0xdf,0x38,0xc4,0xbd, + 0xa5,0x1d,0xac,0xef,0x9f,0x38,0xbe,0x9f,0xf7,0xfd,0x5c,0x6,0x3a,0x5b,0x84,0xd3, + 0x91,0xd3,0xb2,0xe9,0x14,0x2e,0xce,0xc,0xe1,0xc7,0xaf,0x9d,0xc5,0x3b,0xd7,0x66, + 0x30,0x5a,0x29,0xc6,0xa,0x79,0x74,0x9f,0x98,0x24,0xa9,0x92,0x13,0x4f,0xb7,0x17, + 0x60,0x73,0xff,0x84,0xb7,0xea,0x4d,0x8,0x42,0x8c,0x4f,0xa,0x91,0xe5,0x9b,0x44, + 0x18,0x42,0xe4,0x94,0xd1,0xdf,0x8b,0x23,0x46,0x49,0x6c,0xf0,0x72,0xc4,0xd2,0xc4, + 0xf5,0xdf,0x5b,0x62,0x49,0x68,0x7a,0x6c,0x55,0x9b,0xa,0x2e,0xfa,0x56,0x49,0xe7, + 0x27,0x78,0xf0,0x19,0x47,0x5a,0x55,0x26,0xc4,0xe3,0x6b,0xe5,0xc1,0x28,0x8c,0x79, + 0xcc,0xcb,0xdb,0xed,0x5,0x61,0x54,0x25,0x7a,0x51,0x3d,0x2e,0x0,0xe0,0xa3,0xfb, + 0x6b,0xa8,0xe,0x14,0x30,0xa2,0x95,0x14,0xff,0x5c,0x36,0x72,0x3e,0x93,0x46,0x4a, + 0x91,0xab,0x89,0x81,0x1e,0x4,0x58,0x6e,0x5d,0xc8,0x13,0xfa,0x4a,0x8f,0x69,0x61, + 0xe8,0xe,0x22,0x20,0xa5,0x80,0x99,0x91,0x41,0x9c,0x19,0x1d,0x44,0x26,0xa5,0x12, + 0x35,0xf1,0xf2,0xb9,0xd8,0x39,0x6c,0xe0,0xde,0xd2,0x2e,0x36,0xf6,0x1b,0x36,0x59, + 0x1,0xcc,0x6c,0xd2,0x1,0x85,0x60,0x26,0xe2,0xc,0x68,0x50,0x67,0xe7,0xbd,0xe5, + 0x9d,0xaa,0x94,0x9c,0xf8,0xcc,0xf0,0x51,0x25,0xf2,0x3c,0x17,0x5,0xa5,0x9c,0x80, + 0xb1,0x4a,0x91,0xe6,0xc6,0x2b,0xb8,0x34,0x5d,0xa3,0xb7,0x2e,0x4f,0xe3,0x8d,0xb, + 0x93,0x24,0xd7,0x1c,0xf2,0x39,0x92,0x72,0x2d,0xb7,0x4b,0x3e,0xc5,0x57,0x4f,0xb6, + 0xf8,0xbf,0x7c,0xf1,0xc,0x9f,0x3e,0xd8,0xe0,0xa3,0x66,0x1b,0xe,0xce,0x95,0x21, + 0x70,0x24,0xf,0x61,0xb6,0x26,0x62,0x32,0xf2,0x8e,0x1c,0x63,0x4c,0x46,0x1b,0x9b, + 0x19,0xc3,0xde,0x3a,0x5e,0xa6,0xb0,0xdb,0xd3,0xe6,0xb2,0x69,0x5c,0x98,0x1e,0xb2, + 0xaa,0x83,0xa4,0x9,0x3c,0xe9,0x63,0xcd,0x56,0x7,0xed,0x6e,0xf,0xa5,0x5c,0x6, + 0xa9,0x94,0x8a,0x71,0x7f,0x92,0xa,0x7b,0x2a,0xa5,0x50,0xca,0x67,0x70,0xe5,0xcc, + 0x8,0x32,0x99,0x14,0x9a,0xed,0x1e,0x3e,0xbc,0xb7,0x86,0x87,0xab,0xbb,0x68,0x77, + 0x5,0x13,0xcb,0x79,0x9,0xd8,0x2,0x67,0x76,0x61,0x24,0x55,0x2c,0x66,0x2c,0xd, + 0xe0,0xed,0x96,0x6d,0x5c,0xb9,0x9,0xfe,0x0,0x99,0x1d,0x3c,0xeb,0x50,0x1f,0x3d, + 0x77,0x5b,0xbf,0x38,0x56,0xe1,0xfe,0x98,0x3,0xe3,0x41,0xa3,0x39,0x2d,0xa1,0xdf, + 0x9b,0xc9,0x38,0xb7,0x93,0x3c,0x2c,0x54,0xf,0xc9,0xcf,0x61,0xfb,0xa3,0xb3,0xb4, + 0xbf,0x76,0xad,0xba,0x97,0x9c,0xea,0x3d,0x2f,0x42,0x3c,0xcb,0xb1,0x50,0x71,0x73, + 0xe6,0xaa,0x58,0x52,0x1b,0x93,0xef,0x2b,0xc2,0xbe,0x46,0xd3,0x5d,0xe,0x7b,0xfd, + 0x94,0x9b,0xf4,0x75,0xf,0x9e,0x76,0x9e,0x86,0x7e,0x8c,0x34,0xc5,0x58,0x95,0x7e, + 0x97,0x42,0x71,0x17,0xed,0x98,0x22,0x9e,0x12,0xc2,0x36,0x8d,0x56,0x88,0xbc,0x67, + 0x56,0x7c,0x9,0x4d,0x65,0x63,0x16,0xe9,0x66,0xca,0x14,0x5c,0x63,0xe4,0x42,0x76, + 0x1f,0x2e,0x18,0xeb,0xc6,0x20,0x46,0x19,0xd2,0x1b,0xe9,0xe0,0x95,0xf0,0x9,0xb4, + 0x96,0x3d,0x44,0xd0,0xb2,0x35,0x17,0xea,0x2a,0xac,0x64,0x15,0x15,0xf3,0x69,0xfa, + 0xf6,0xe5,0x29,0xfa,0xa3,0x37,0xcf,0xd1,0xf,0x6e,0x9c,0xa1,0x6c,0x26,0x1d,0x7b, + 0x40,0xa2,0x9d,0x6f,0xb3,0xd5,0xc1,0x97,0x4f,0x37,0xf1,0xeb,0x5b,0x4b,0xf8,0xcd, + 0xed,0x25,0xec,0xd4,0x4f,0x1d,0xa4,0xe8,0x1d,0x56,0xd1,0x13,0x49,0xb4,0x81,0x91, + 0x50,0x72,0x7b,0x63,0x58,0x5,0x85,0x54,0xfa,0x31,0xc6,0x6a,0x3,0xb8,0x3e,0x3f, + 0x86,0x9a,0xb6,0xdc,0xec,0x97,0xa4,0xb4,0xb5,0xdf,0xc0,0x7b,0xb7,0x96,0xf0,0x78, + 0xfd,0x40,0x18,0x79,0xb0,0xff,0xfd,0x28,0x82,0x2,0x58,0xf2,0x78,0xf8,0xa7,0xcb, + 0xb3,0x23,0xf8,0xf1,0xeb,0x73,0xf8,0xd1,0x6b,0x73,0x18,0xab,0x96,0xfa,0xc2,0x75, + 0xfd,0xc8,0x81,0x49,0xa8,0x41,0x10,0x30,0x76,0xe,0x9b,0xd8,0xab,0x9f,0x72,0xe0, + 0x4,0x9d,0xce,0x37,0x43,0xeb,0x5c,0x14,0x52,0x42,0x66,0xce,0x1,0xc9,0x86,0x91, + 0x85,0x69,0xa2,0x48,0x99,0x52,0x1e,0xba,0xc4,0xe2,0x95,0x96,0x7d,0xa9,0xd1,0x31, + 0x29,0xf3,0xfb,0xb3,0xe5,0xe5,0x85,0x10,0x20,0x93,0xb,0xc4,0x46,0x3c,0xa6,0x40, + 0x10,0x4a,0x5d,0xc2,0xad,0xdb,0x8d,0x9a,0x6b,0xcc,0xfe,0x9e,0x4b,0x4e,0xbf,0xa4, + 0x12,0x24,0x2b,0xd2,0x35,0x12,0xc0,0xda,0xee,0x31,0x3e,0x7d,0xb8,0x86,0x77,0xae, + 0x4e,0x63,0x32,0x12,0x94,0xf1,0x32,0x48,0x48,0xab,0xd3,0xd5,0xc7,0x95,0x72,0xe5, + 0x8c,0x12,0xfc,0xc3,0x6d,0xae,0x83,0x8a,0xf9,0x48,0x90,0x73,0x86,0x40,0x8a,0x14, + 0xe6,0x27,0x2a,0x98,0x9f,0xa8,0x40,0xa5,0xe8,0x5,0x56,0xa0,0x8c,0xd3,0x76,0x17, + 0xab,0xbb,0xc7,0x58,0xda,0x3d,0x42,0x37,0x80,0x34,0x61,0xf3,0x24,0xae,0xfa,0x98, + 0x34,0x7e,0x8c,0xb2,0xff,0x31,0xb1,0xf,0x82,0xc6,0x23,0x8e,0x57,0x9b,0x9c,0xea, + 0x8e,0x58,0xb2,0x75,0x48,0xc9,0xfb,0x3c,0xea,0x61,0x4b,0x95,0x62,0xe,0x6f,0x5f, + 0x9d,0xa1,0x3f,0xbc,0x31,0x8b,0xb7,0x2e,0x4d,0x91,0x41,0x1b,0x92,0xdc,0xd3,0xa2, + 0xcf,0x7c,0x10,0x4,0x8,0x2,0xc6,0xfd,0xe5,0x5d,0xfe,0xf,0x3f,0xbf,0xc3,0x77, + 0x97,0xb6,0x75,0xe8,0x8a,0x2d,0x58,0xec,0xc7,0xb,0x31,0xfb,0x26,0x97,0x92,0x38, + 0x6c,0xe0,0x4c,0x5,0x23,0xc1,0x90,0xfe,0x79,0x6c,0x9c,0x60,0xa3,0x3e,0x7f,0x26, + 0x5e,0x51,0x3f,0xa3,0xa5,0x7c,0x6,0xf3,0x13,0x15,0x8c,0xd7,0x8a,0xdf,0x8,0x99, + 0x9b,0xfb,0xb3,0xdd,0xe9,0xe1,0xc9,0xc6,0x1,0x8e,0x9b,0x1d,0x4c,0xd4,0x8a,0x18, + 0x1a,0x28,0xa0,0x5c,0xcc,0x7e,0x23,0xf2,0x23,0xaf,0xc9,0xc2,0x58,0x5,0xff,0xe3, + 0x8f,0xaf,0x63,0x72,0x78,0x0,0xff,0xd7,0x7b,0xf7,0xf1,0x7c,0xab,0x8e,0xd3,0x76, + 0x4f,0xfe,0x7e,0x2,0x84,0x20,0x27,0xc4,0x87,0x67,0x67,0xaf,0x69,0x31,0x2a,0x4c, + 0x3a,0xd,0x3c,0x12,0x9c,0x78,0xd5,0x9d,0x63,0xa6,0x29,0xe5,0x52,0x8a,0xcd,0x70, + 0x5,0x3e,0x7c,0xfd,0x3,0xb6,0x44,0x3a,0xdb,0x50,0xeb,0xc1,0x41,0x5,0x3a,0xd1, + 0x4d,0xa7,0xa5,0x2b,0xc1,0xf9,0x32,0xaf,0x9e,0x82,0x88,0xc0,0x6,0x8c,0x14,0xc4, + 0x86,0x7,0xb0,0xaf,0xaa,0xf0,0x66,0x76,0x46,0x1c,0x32,0x8f,0xb,0x85,0x11,0x63, + 0x8c,0xc8,0x6b,0xcd,0xf1,0x8d,0x58,0x6c,0xb8,0x13,0x4a,0xef,0x74,0xd4,0xd2,0xd5, + 0xcb,0x51,0x14,0xb0,0x80,0xb5,0xee,0x22,0x69,0xb1,0xc5,0x91,0xd8,0x16,0x17,0x5d, + 0xe8,0x63,0x9d,0x10,0xe4,0x17,0xff,0x4f,0x1e,0xbb,0x9f,0x1c,0xcf,0x5d,0xcf,0xd0, + 0x92,0xcc,0x12,0x1a,0xc7,0x68,0x73,0x18,0x37,0xbf,0x2b,0x25,0x2c,0x60,0xad,0xeb, + 0x1b,0x4c,0xbe,0xb9,0xdd,0xa5,0x2b,0x4d,0x98,0xd3,0xb8,0x81,0x89,0x2e,0x62,0xab, + 0x4f,0x25,0x10,0xb0,0x30,0x51,0xa1,0xef,0x5e,0x9d,0xa5,0xef,0x5d,0x9f,0xa5,0x6b, + 0x73,0xa3,0xb6,0x98,0x27,0x11,0xdf,0x4c,0x8a,0xd2,0xed,0xc5,0x6d,0xbc,0x7f,0x7b, + 0x9,0xf,0xd7,0xf6,0xb0,0xbc,0x7d,0x84,0xdd,0xa3,0x53,0x50,0x44,0xe3,0x4d,0xe2, + 0xb0,0xf6,0x6b,0x3,0x79,0xf2,0x6,0x7f,0x8f,0x29,0xcc,0x77,0x4,0xa7,0x30,0x95, + 0x26,0x4c,0xd6,0xca,0x38,0x3f,0x55,0x43,0x29,0x9f,0x7e,0x21,0x49,0x7,0x0,0xd6, + 0xf7,0x4e,0xf0,0xfe,0xd7,0xcb,0x58,0xda,0xaa,0x47,0xa4,0x24,0x72,0x70,0x55,0xae, + 0xf3,0x87,0x33,0x44,0xc8,0xa6,0xd2,0xb8,0x38,0x5d,0xc5,0x4f,0xdf,0x5c,0xc0,0x1f, + 0xde,0x9c,0xb3,0x30,0xbb,0x24,0xde,0x45,0x39,0x4,0xcc,0x8c,0x67,0x1b,0x7,0x8, + 0x18,0x98,0x19,0x29,0x27,0x3a,0xe5,0x59,0x8f,0xe7,0xe3,0x53,0xec,0x37,0x5a,0x7e, + 0x1e,0x91,0xbb,0x48,0x61,0x40,0xa2,0x67,0x4b,0x24,0x7c,0x1b,0x24,0xf6,0x6d,0x3a, + 0x5f,0x56,0xbe,0xc6,0x53,0xe8,0x29,0xc9,0x63,0x4b,0x89,0xd0,0x20,0x67,0x1e,0x61, + 0x13,0x31,0xd8,0x2d,0x73,0xe4,0x82,0x53,0xbc,0x6b,0x3d,0x48,0x1d,0xfb,0x8e,0x28, + 0x8c,0x7e,0x30,0x8d,0x2a,0xf9,0x39,0x5,0xa6,0x31,0xb3,0xcf,0x51,0x94,0x15,0x6b, + 0xaa,0xbe,0x8a,0xbd,0x90,0x0,0xa9,0x97,0x82,0xda,0xa3,0x53,0x58,0xb3,0xd5,0xc1, + 0xd6,0x61,0x3,0xad,0x6e,0x20,0x49,0x32,0x64,0x76,0x9,0x3e,0xad,0xd6,0x17,0xa1, + 0x2b,0x47,0x1,0xf6,0x59,0xee,0x2a,0x64,0xcf,0x2f,0x4c,0x54,0x91,0x4a,0xb0,0x3b, + 0x35,0x6f,0xdd,0x5e,0xf,0xf,0xd7,0xf6,0xf0,0x60,0x75,0x1f,0x2d,0x7b,0xc0,0xbb, + 0x62,0xce,0x88,0x3,0x57,0x10,0x81,0x6f,0x76,0x0,0xa1,0x50,0xa3,0x26,0xd,0xe2, + 0x5c,0x3a,0x9f,0x99,0xc,0xd8,0x71,0x76,0x84,0xea,0x86,0x49,0x45,0x28,0x78,0x44, + 0x73,0xa3,0x65,0xdc,0x38,0x37,0x46,0xaf,0x9d,0x1b,0xc3,0xf9,0xc9,0x2a,0xcd,0x8c, + 0xc,0x62,0xa0,0x90,0xed,0x3b,0xc9,0x46,0x79,0x29,0x0,0xb0,0xb9,0x7f,0x82,0xf7, + 0x6e,0x2f,0xf3,0xfb,0x77,0x56,0xf8,0xc1,0xea,0x1e,0x1a,0xad,0x1e,0xcb,0x94,0x59, + 0x32,0x42,0x3a,0x72,0xd7,0x2c,0x60,0xf6,0x82,0xb3,0x7c,0x6f,0x30,0x43,0xe9,0xb3, + 0x61,0x85,0xce,0x38,0xd4,0x64,0x19,0x53,0xe4,0xd5,0x27,0xff,0x65,0x19,0xad,0x94, + 0x30,0x32,0x58,0x48,0x6c,0xb2,0xa5,0xcf,0x7a,0xb3,0xd5,0xc5,0xc3,0xd5,0x3d,0xdc, + 0x5f,0xdd,0xc3,0xe3,0xd5,0x7d,0xac,0xed,0x9f,0xa0,0xd3,0xe9,0xa1,0x5c,0xcc,0xe2, + 0xb5,0x85,0x71,0x7c,0xf7,0xda,0x34,0x16,0xc6,0x7,0x13,0x99,0xfc,0xd1,0xa8,0x54, + 0xad,0x2c,0xc6,0x40,0x21,0x8b,0xef,0x5d,0x9d,0xc1,0x60,0x31,0x8b,0x5f,0x7e,0xb9, + 0x84,0x4f,0x1f,0x6d,0x62,0xeb,0xb0,0x81,0x58,0xec,0x2b,0xe2,0x19,0xc,0x9e,0x53, + 0xb9,0x87,0x32,0xb3,0xe4,0x34,0x72,0x84,0x7a,0x2a,0x51,0x63,0x31,0x31,0x53,0x24, + 0xbe,0x54,0x81,0x10,0x18,0xc3,0x22,0x67,0x15,0x6b,0x29,0xe0,0xe6,0x36,0xd1,0xd3, + 0xa6,0xe7,0x7f,0x21,0x8c,0x61,0xac,0xbb,0x8b,0xf1,0xbe,0x8a,0x38,0xad,0x51,0x64, + 0x38,0x13,0x82,0xc9,0xe8,0x1a,0xd3,0x4f,0x42,0x89,0x5b,0xba,0x46,0xd3,0xa1,0x39, + 0xa6,0x20,0xa7,0x88,0xff,0xbb,0xfb,0x1a,0x69,0xfb,0x64,0x9,0x27,0x18,0x6b,0xaa, + 0xe4,0x99,0xc7,0xc8,0x7,0x3a,0x29,0x5b,0x4d,0x1f,0xa6,0xd4,0x27,0x4f,0x9d,0x89, + 0x92,0xba,0x11,0xb7,0x33,0x66,0x21,0xd6,0x53,0xe4,0x2,0x14,0x74,0xe2,0x7,0x89, + 0xf8,0xd2,0x30,0x30,0x4d,0x14,0xf2,0x50,0x43,0xce,0x26,0x7c,0x45,0x19,0xf1,0x93, + 0x8b,0x3e,0x35,0xff,0x2e,0x84,0xdf,0x4d,0xa4,0x13,0x81,0x52,0x61,0x81,0x4f,0x29, + 0xc2,0x68,0xb5,0x44,0xef,0xde,0x98,0xa7,0x3f,0x7a,0x63,0x81,0xae,0xcc,0xe,0x93, + 0x81,0x9f,0xa2,0xa4,0x12,0xe3,0xd1,0xbc,0x5b,0x6f,0xe2,0xfe,0xca,0x1e,0x7e,0xf9, + 0xd5,0x73,0xfc,0xe3,0xa7,0x4f,0xc3,0xae,0x94,0xd8,0x6f,0x84,0x90,0xd8,0x86,0xc5, + 0xff,0x26,0x76,0x4e,0x2b,0x24,0x3a,0x7c,0x10,0x90,0x49,0x67,0x70,0x7d,0x7e,0xc, + 0x17,0xa6,0x6b,0x48,0x29,0xe5,0x59,0x4f,0x4a,0xf9,0x50,0xaf,0x17,0xe0,0xf8,0xb4, + 0x8d,0x27,0xeb,0xfb,0x78,0xb0,0xb2,0x8f,0x4e,0x8f,0x23,0x3a,0x57,0xa7,0x44,0x70, + 0x84,0x32,0x16,0x84,0x34,0xc2,0xc2,0x44,0x5,0x3f,0xb8,0x39,0x8f,0x77,0xae,0xcd, + 0x60,0x66,0xc4,0x41,0x79,0x51,0x17,0x30,0x73,0x8,0xb6,0x3b,0x3d,0xac,0xef,0x9f, + 0xe0,0xb7,0x77,0x56,0x50,0x2c,0x64,0x30,0x34,0x10,0xa6,0xac,0x25,0x15,0xa2,0x5e, + 0xc0,0x61,0xe2,0x5c,0xb3,0xed,0xe9,0xec,0x61,0xd,0x45,0xfc,0x2c,0x1,0x8f,0x42, + 0xc4,0xde,0x8a,0xc7,0x6d,0x9f,0x84,0xa4,0x8d,0x62,0xad,0x2d,0x25,0x5c,0x6f,0xdf, + 0xfa,0x58,0xb0,0xa3,0xdd,0x27,0xa9,0x68,0xfa,0xa0,0x68,0x8b,0x5,0x49,0x9c,0x42, + 0xb7,0x31,0x4f,0x4b,0x1f,0xad,0x55,0x7d,0x27,0x1f,0x44,0xf9,0x26,0xee,0xfe,0x18, + 0xab,0x94,0x70,0x7e,0xaa,0x86,0x81,0x42,0xee,0xa5,0xf7,0xe7,0xe6,0x35,0xd9,0x3a, + 0x6c,0xe0,0xee,0xd2,0x2e,0x8e,0x4e,0xdb,0x31,0x64,0xc1,0xa2,0x13,0x49,0xa2,0x44, + 0xc1,0xe0,0x85,0x95,0x66,0x1b,0xdf,0x80,0x34,0x66,0x86,0xcb,0x98,0x19,0x2d,0x5b, + 0x47,0xbc,0x24,0x1d,0x7a,0xc0,0xc0,0xbd,0xe5,0x5d,0xdc,0x5d,0xda,0x45,0x60,0xd0, + 0x8,0xdf,0xe3,0x9a,0x20,0x23,0xa,0x7c,0x60,0x9d,0xed,0x4a,0xc8,0x8,0xcf,0x6d, + 0x54,0x84,0xcb,0x40,0x37,0xc3,0x30,0x94,0xf2,0x5d,0xd,0xd9,0x77,0xde,0xca,0x65, + 0xd2,0x94,0xcb,0x28,0x4c,0x8f,0x94,0xf1,0xda,0xd9,0x31,0xfa,0xfe,0x2b,0xb3,0xf8, + 0xf6,0xc5,0x49,0x92,0x9c,0x98,0x24,0x48,0xda,0x3c,0x4b,0xe6,0xef,0x4e,0xdb,0x1d, + 0xac,0xed,0x9d,0xe0,0xab,0xa7,0xdb,0xfc,0xb7,0xbf,0x7f,0xc2,0x77,0x9e,0xef,0xb0, + 0x98,0xa6,0xd8,0x1,0x5,0x7a,0x25,0x23,0xa4,0x81,0xd6,0x23,0xc1,0x63,0x84,0x47, + 0xd9,0x95,0xae,0x8c,0x5a,0x19,0x90,0xc0,0x4d,0x2c,0x92,0xc8,0x3a,0x78,0x40,0x1f, + 0x84,0x23,0x83,0x79,0x4c,0xf,0xf,0xa0,0x98,0xcd,0x24,0xaa,0x1d,0xe4,0xef,0xb3, + 0x7f,0x7c,0x8a,0xf,0xee,0xad,0xe1,0xfd,0x3b,0x2b,0x78,0xb0,0xb2,0xe7,0x20,0x2b, + 0x6,0xd6,0x76,0x4f,0xd0,0xe5,0x0,0x8d,0xd6,0x38,0x16,0xc6,0x6b,0x28,0xe6,0xd2, + 0x90,0xa1,0x73,0xde,0xeb,0x1b,0x89,0xc9,0x1d,0xaf,0x95,0xf0,0x93,0xda,0x2,0xd2, + 0x2a,0x85,0x54,0x2a,0x85,0xcf,0x1f,0x6f,0x62,0x63,0xff,0x4,0xbd,0xc0,0x71,0x0, + 0x48,0x42,0xc6,0x5e,0xbe,0x3b,0xe2,0xce,0x71,0x5a,0x78,0x4e,0x81,0x1f,0x7,0xe6, + 0xa0,0x70,0xa7,0x5c,0x95,0x83,0x91,0x85,0x33,0x34,0xab,0xe,0x2a,0x9c,0xd4,0x11, + 0x28,0x80,0x2,0x2d,0x7d,0xd,0x5c,0x40,0x18,0xfb,0x50,0x54,0x38,0xc4,0x9b,0xee, + 0x41,0xf9,0xcf,0xa7,0x8c,0x1b,0x67,0x47,0x54,0x83,0x35,0xfe,0x8a,0xa,0x8d,0xc9, + 0x5,0x41,0xab,0x38,0xad,0xc3,0xdf,0xa7,0x73,0x84,0xd,0xe2,0xef,0xe6,0x39,0x26, + 0x73,0xa7,0xd8,0x7a,0x3c,0x2d,0x40,0x67,0xb,0xc4,0x87,0x1,0x2d,0x4e,0xd,0xef, + 0xd4,0x40,0x92,0x90,0xe4,0x33,0x34,0x20,0x8,0xe9,0x49,0x26,0xf2,0x4c,0x11,0xdb, + 0x57,0x87,0xfd,0x92,0x8d,0x2a,0x24,0xab,0x42,0xb6,0x98,0x7a,0x88,0x53,0x99,0xf4, + 0x4,0x3b,0x7d,0xb,0xc8,0x3d,0x84,0xd7,0x39,0x2c,0xea,0x4a,0xf,0xe3,0x8a,0xd9, + 0x5,0xa0,0x92,0x4b,0x5c,0x95,0x60,0x23,0x48,0x69,0x22,0x1c,0x3,0x17,0x67,0x87, + 0xe9,0xdf,0x7d,0xff,0xb2,0x7a,0xfd,0xdc,0x4,0xcd,0x8c,0xc,0x58,0xcd,0x69,0x3f, + 0x28,0xf9,0xe1,0xea,0x3e,0xde,0xbb,0xbd,0x84,0xf7,0x6e,0x2f,0xe3,0xd9,0xe6,0x21, + 0xda,0x7a,0x2,0xf2,0x7c,0x87,0x11,0xd7,0xee,0xfb,0xb7,0xab,0x5f,0xd8,0x23,0xb7, + 0x72,0x8c,0x4c,0x62,0x3e,0x2b,0x9b,0x51,0xb8,0xb1,0x30,0x86,0x4b,0x33,0xc3,0x89, + 0xe4,0x37,0xf3,0x73,0xb7,0x3a,0x3d,0x7c,0xfc,0x70,0x1d,0x5f,0x3e,0xdd,0xd4,0xf, + 0x95,0x13,0x59,0x98,0x31,0x89,0xd9,0xef,0x88,0x1d,0x1e,0xb,0x5c,0x98,0xac,0xe0, + 0x7,0x37,0xe7,0xf0,0x97,0x6f,0x5f,0xc0,0xb8,0x66,0xd1,0x47,0xf7,0xe3,0xd1,0xef, + 0xff,0xc5,0xd3,0x2d,0xfc,0xc3,0x27,0x9,0xe9,0x44,0x0,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x4f,0xf1,0xdb,0xaf,0x97,0x71,0xe5,0xcc,0x8,0xde,0x38,0x37,0x8e, + 0x4a,0x29,0xa7,0x3,0xba,0x38,0xb6,0x22,0x3e,0x6a,0x76,0xd0,0xea,0x6,0xe1,0x61, + 0x17,0x88,0xde,0xcf,0x62,0xd4,0xae,0xe8,0x28,0xeb,0xfd,0xe0,0xb9,0x63,0x11,0x7, + 0xcc,0x82,0x8d,0xaf,0x25,0xbe,0x2e,0xcb,0xd6,0x8f,0x4,0x17,0x39,0x82,0x2,0xba, + 0x77,0x3b,0x56,0xe5,0xb3,0xed,0x3c,0x83,0x7,0x61,0x77,0x2b,0x39,0x2f,0xf2,0x40, + 0x17,0x8d,0x3,0x47,0xe4,0x60,0xb1,0xee,0x2e,0x29,0x7d,0x21,0xe2,0xa8,0x8,0x0, + 0x17,0x67,0x86,0xf0,0xc3,0x9b,0x67,0x30,0x54,0xce,0x7f,0xa3,0x14,0x29,0x4a,0x6e, + 0x7a,0xb6,0x71,0x88,0xf,0xee,0xae,0x21,0x4c,0xd7,0xa3,0x3e,0x3f,0x0,0xc1,0xf7, + 0x3,0x27,0x70,0x2,0x84,0x68,0xfe,0x58,0x1b,0xc8,0x63,0xa2,0x56,0x42,0x21,0x9b, + 0xe9,0xfb,0x8c,0x98,0x3,0xff,0xe1,0xea,0x3e,0xee,0x2f,0xef,0xa1,0x17,0x4,0x88, + 0xe4,0x77,0x4b,0x40,0x24,0x42,0x5b,0x23,0x73,0x29,0xad,0x2e,0xd9,0x73,0x3c,0xf5, + 0x56,0x84,0x21,0x2b,0xd9,0x31,0x47,0x55,0xe8,0x8,0xad,0x9c,0x30,0xa2,0x50,0xc8, + 0xe0,0xda,0xec,0x30,0xde,0xb9,0x3a,0x4d,0x37,0x16,0x46,0x69,0x6a,0x68,0x0,0xd5, + 0xb2,0x7f,0x4f,0x26,0xf1,0x3d,0xa2,0xcf,0x7c,0xbb,0xd3,0xc5,0x97,0x4f,0xb6,0xf9, + 0xe7,0x5f,0x3d,0xc7,0x6f,0xee,0xac,0xf2,0x6e,0xbd,0x61,0x24,0xfd,0xec,0x2c,0x3e, + 0xd,0xc9,0xca,0x77,0x7f,0x73,0xe2,0x4a,0x16,0x9b,0x1f,0xf2,0xee,0xa,0xb6,0x5d, + 0x96,0xf9,0xc7,0x2e,0xbf,0x3e,0x44,0x77,0x85,0xb0,0x5b,0xe6,0x15,0x10,0x61,0x76, + 0x74,0x10,0xb,0x93,0x55,0x2f,0x2a,0x35,0x2e,0x13,0xd,0x7,0x93,0xf5,0xfd,0x63, + 0xfc,0xf2,0xab,0x25,0x3c,0x59,0x3f,0x74,0x56,0x3e,0xfa,0xff,0x1e,0xae,0x1f,0x60, + 0xe7,0x57,0xf7,0xf1,0xc5,0x93,0x6d,0x7c,0xf7,0xea,0x24,0xfe,0xe4,0xf5,0x5,0x54, + 0xb4,0x33,0xde,0x8b,0xc8,0x75,0x12,0xad,0x7b,0xfb,0xca,0x24,0xa6,0x86,0x7,0xb0, + 0x30,0x3e,0x88,0x5f,0xde,0x5e,0xc1,0xd7,0xcf,0xb6,0xbd,0x67,0xc2,0xcf,0x6f,0xa4, + 0xa8,0x6e,0x45,0xf0,0xad,0x44,0x5f,0x67,0xad,0xc9,0x2,0xb7,0x7f,0x31,0x34,0x82, + 0x80,0x6c,0xd8,0x34,0xab,0xc0,0x21,0x5d,0xc2,0x23,0x8c,0xad,0x64,0x40,0x3e,0xdf, + 0xcc,0x50,0xa,0x8,0x2,0x4d,0x64,0x93,0xa2,0x2d,0x19,0x4b,0xea,0xc3,0xfe,0x16, + 0xc1,0x54,0x12,0x6e,0x11,0xeb,0xb3,0x18,0xc,0x41,0x89,0x42,0xc,0x62,0xef,0x98, + 0x41,0x2c,0xea,0xd9,0xd1,0xf1,0x11,0x77,0x24,0xf1,0xbf,0x98,0x37,0xa1,0xbb,0x94, + 0x40,0xbb,0xb7,0xf4,0x7e,0x1e,0x8e,0x20,0xff,0x14,0xb5,0x84,0x95,0x88,0x49,0x4c, + 0x6,0x15,0x97,0x44,0x79,0xc8,0x11,0x6b,0x73,0x37,0x38,0x28,0xc3,0x41,0xae,0xca, + 0x39,0xb5,0x85,0xf0,0x3a,0xc1,0xe8,0xcd,0xed,0xdf,0x28,0x21,0x5b,0xb,0xc9,0x6f, + 0xac,0xed,0x5e,0x5,0x93,0x9d,0x34,0xf2,0x46,0x70,0x43,0x1d,0x81,0x40,0xf9,0x74, + 0x9a,0xae,0xcf,0x8f,0xd2,0xbb,0x37,0x66,0xe9,0xbb,0x57,0x66,0x68,0x7a,0xe4,0xc5, + 0x8c,0xf1,0xed,0xc3,0x26,0xee,0x2e,0x6d,0xe3,0xe3,0x7,0xeb,0xf8,0xf8,0xe1,0x6, + 0x1e,0xae,0xec,0xb,0x13,0x1,0x1,0x6a,0xf4,0x31,0xd1,0xa7,0xe4,0xd9,0xac,0xcf, + 0x7b,0x49,0xb1,0x36,0xa,0xd5,0x52,0x1e,0x67,0x27,0xab,0x98,0x1e,0x1e,0x30,0x72, + 0x96,0x44,0x28,0xac,0xd5,0xe9,0xe1,0xf3,0xc7,0x9b,0xb8,0xf3,0x7c,0xf,0x1,0xf7, + 0xb1,0xf7,0x8d,0x1e,0xa8,0xfa,0x61,0x98,0x19,0x2d,0xe3,0xf,0x6f,0xce,0xe1,0xdd, + 0x1b,0xb3,0x9e,0x71,0x48,0x92,0xcd,0x28,0x11,0xe1,0xa8,0xd9,0xc6,0x9d,0xc5,0x1d, + 0xfc,0xfc,0x8b,0x45,0x7c,0x78,0x77,0x15,0x3b,0xf5,0x53,0xd4,0x4f,0x5a,0xc8,0x64, + 0x52,0xb6,0xc3,0x8f,0x1d,0x30,0xc,0x34,0x3b,0x5d,0x99,0xe9,0x4b,0x1e,0x45,0xd6, + 0x36,0xf3,0x64,0xdf,0x71,0x46,0x24,0x81,0x7d,0x28,0x4d,0xde,0x85,0x9e,0xfa,0x2c, + 0x69,0xdd,0x33,0xf6,0x26,0x26,0x21,0x11,0x21,0x44,0x27,0x62,0x8a,0xe3,0x81,0xb1, + 0x70,0x5,0xef,0xdf,0xf9,0xd1,0x80,0xc2,0xff,0xdc,0x3d,0x31,0x82,0x70,0x1a,0x59, + 0x2,0x43,0x90,0x5,0x90,0x98,0xc0,0x0,0xa0,0x94,0x4f,0xe3,0xda,0x99,0x61,0xbc, + 0x73,0x75,0x1a,0x17,0xa7,0x87,0x50,0xca,0x67,0x5e,0x68,0x30,0x13,0x9d,0x98,0x36, + 0xf6,0x4e,0x70,0x6b,0x71,0x1b,0xf7,0x96,0x77,0x71,0x72,0xda,0x8b,0x4c,0x31,0xee, + 0x59,0x65,0x24,0x70,0x2f,0xe2,0xb,0x20,0x0,0xc0,0x60,0x21,0x8b,0xb9,0xf1,0xa, + 0x2a,0xa5,0xdc,0x37,0x3a,0xd9,0x6d,0x1e,0x34,0xb0,0xba,0x7b,0x82,0x46,0xbb,0x6b, + 0xf9,0x2,0x2c,0xe6,0x50,0x86,0xb1,0x7e,0x63,0xcf,0x4b,0x85,0x85,0x1f,0xad,0xa1, + 0xe9,0x81,0x48,0x70,0xc0,0x58,0xf4,0xc3,0xca,0x81,0xb3,0xca,0xbd,0xdc,0xf9,0x4c, + 0x1a,0xe3,0x95,0x22,0xa6,0x46,0xcb,0x74,0x76,0x7c,0x10,0x97,0x66,0x86,0xf1,0xca, + 0xdc,0x8,0xcd,0x8d,0xd,0x22,0x15,0xc9,0x7,0xf,0xb4,0xdd,0xb7,0xf4,0x26,0x8f, + 0x22,0x4f,0x2b,0xbb,0x27,0xb8,0xbb,0xb4,0xcd,0xbf,0xbb,0xbb,0xc6,0x9f,0x3e,0xda, + 0xc4,0xd6,0x41,0x83,0x59,0x48,0xc7,0xd9,0xcc,0x89,0x3a,0xa3,0x4b,0xa0,0xef,0x1e, + 0x5c,0x2c,0x9b,0xf,0xe7,0x80,0x10,0xd9,0x35,0x7b,0xb1,0x30,0xd6,0x69,0x26,0xec, + 0x45,0xd9,0x28,0xfe,0x9c,0x4,0x8c,0x8,0x98,0x19,0x2d,0x63,0x61,0xbc,0x82,0x74, + 0x8a,0x12,0xbd,0x30,0x4c,0xf3,0xba,0x79,0xd0,0xc0,0xe3,0xf5,0x43,0xac,0xef,0x9d, + 0x44,0xfb,0xdd,0xf0,0x8e,0xc,0x80,0x9d,0xe3,0x53,0x7c,0xfe,0x64,0x13,0xcd,0x76, + 0x7,0xad,0x4e,0x80,0x57,0xcf,0x8e,0x62,0x7e,0xac,0x82,0x41,0xb1,0x5b,0x4f,0x32, + 0xd4,0x31,0xd7,0x30,0x97,0x49,0xe3,0xe2,0x74,0xd,0x44,0x40,0x26,0x9d,0x42,0x3e, + 0x9b,0xa2,0x7b,0xcb,0x7b,0xdc,0x38,0xed,0x44,0xf8,0x5a,0x62,0xcd,0xe4,0xbc,0xfb, + 0xe1,0xac,0x5a,0x92,0x90,0x4e,0x45,0xda,0x54,0xc6,0xec,0x62,0x74,0x13,0x14,0x18, + 0xc3,0x9,0x1d,0xb1,0xab,0x99,0x33,0xa1,0x8f,0xbb,0xe7,0xb0,0x86,0x88,0xd0,0x25, + 0xbc,0x85,0x1c,0x1f,0xdf,0xa0,0x84,0xc,0x99,0xde,0x24,0x80,0x9f,0xa8,0x8f,0x80, + 0x58,0x21,0xc5,0xb2,0x4e,0xc4,0x4a,0x2d,0xb6,0xf3,0x8e,0xef,0xdc,0xbc,0xf3,0xc1, + 0x47,0x31,0x10,0xcd,0x10,0xf7,0xd8,0x42,0xe6,0xba,0xa5,0x65,0xc,0xa6,0xcf,0xae, + 0x76,0x5f,0x47,0xb9,0x73,0x3e,0x2,0xcd,0xb3,0x23,0x3a,0xc0,0x35,0xcb,0x11,0x79, + 0xbc,0x90,0x5,0x9b,0x43,0x4c,0x39,0x5e,0x3c,0xd9,0xec,0x5f,0xc7,0x6a,0x87,0x12, + 0x77,0xa5,0x2c,0xde,0x7a,0x7a,0x27,0xa5,0x98,0x44,0xfe,0xb9,0x99,0xd6,0xc3,0x96, + 0xce,0x9c,0xea,0xb6,0xb,0x30,0x31,0x3a,0xb6,0x77,0x31,0xf8,0x3d,0x29,0x9c,0x9d, + 0x1a,0xa2,0xff,0xfe,0x87,0x57,0xe9,0x5b,0x17,0xa7,0x68,0xb0,0x98,0x8d,0xed,0xc8, + 0xcd,0xfb,0xbd,0x5e,0x80,0xe3,0x66,0x1b,0x1f,0x3f,0x58,0xc3,0x5f,0xbf,0x77,0x1f, + 0x4f,0xd6,0xf6,0xd1,0x68,0x77,0xdd,0x5,0x66,0xf6,0x60,0x19,0x2f,0x9d,0x3b,0xa9, + 0x2e,0x27,0x30,0xfe,0xfd,0xf3,0x3c,0xaa,0x27,0xa,0xbf,0x4e,0x21,0x9b,0xc6,0xcc, + 0xc8,0x20,0xc6,0x6b,0xc5,0x17,0xc6,0x1a,0x12,0x11,0x8e,0x4f,0xdb,0xb8,0xbf,0xb2, + 0x8f,0xb5,0xbd,0xe3,0x17,0xc7,0x39,0x45,0x3a,0xc9,0x89,0xda,0x0,0xde,0xb8,0x30, + 0x89,0x3f,0xfb,0xd6,0x39,0x2c,0x4c,0x56,0x13,0xbb,0xf1,0x28,0xab,0xfd,0xce,0xe2, + 0xe,0xfe,0xc3,0x2f,0xee,0xe0,0xde,0xd2,0x1e,0xea,0x8d,0x16,0x88,0x14,0xaa,0x3, + 0x79,0xd4,0x6,0x5e,0x34,0x55,0x32,0x3a,0xbd,0x20,0xa2,0xa3,0x72,0xe4,0x28,0xab, + 0xb0,0xb4,0x1e,0xd0,0x1,0x87,0xe1,0x2c,0x12,0x5b,0x97,0x4e,0x46,0xa2,0x13,0x88, + 0xc0,0xeb,0x24,0x98,0x51,0x5a,0x9a,0x45,0x92,0xd5,0xc1,0x22,0x68,0xd6,0x8f,0x30, + 0x14,0x7a,0x60,0x8f,0xa1,0x23,0xac,0x6a,0x29,0xa1,0x5f,0x8e,0xb2,0x58,0x38,0x1a, + 0x19,0xa3,0x77,0xf4,0x5a,0xba,0xc9,0xec,0x20,0x70,0x26,0x20,0x45,0xc0,0xf5,0xb9, + 0x51,0xfc,0xf,0x3f,0xba,0x8a,0x6b,0x67,0x46,0x2c,0xbb,0xfd,0x9b,0xcc,0x7a,0x2c, + 0xd4,0x7e,0xd0,0xc0,0x7b,0x5f,0xaf,0xe0,0xf3,0x27,0x5b,0x38,0x68,0xb4,0xb5,0xe9, + 0x13,0xc1,0xeb,0x1f,0x8c,0x8e,0x99,0xbe,0x69,0x21,0xe0,0xb6,0x3f,0x13,0x43,0x3, + 0xb8,0x7a,0x66,0x18,0xc5,0x84,0xcc,0x2,0xf9,0xb6,0xb9,0x7f,0x82,0xfb,0x2b,0xfb, + 0xa1,0xc2,0x83,0x84,0x26,0x97,0x92,0x49,0xea,0x14,0x6d,0x30,0x3d,0x2e,0xad,0x37, + 0xa5,0xb3,0xb4,0xf4,0x75,0x72,0x41,0x77,0x48,0x65,0x52,0x84,0xf3,0x93,0x55,0xfa, + 0xf6,0xa5,0x49,0xfc,0xe1,0x2b,0xb3,0xb4,0x30,0x51,0xc5,0x60,0xc4,0xb2,0xb5,0x5f, + 0x6c,0x68,0x94,0xf0,0xc5,0xcc,0xd8,0x3e,0x6c,0xe2,0x1f,0x3f,0x7b,0xca,0xbf,0xfa, + 0x6a,0x85,0x1f,0xae,0xed,0x73,0xb7,0x17,0x88,0x61,0x8a,0xd8,0x13,0x3d,0x18,0xe5, + 0x4,0x4b,0x97,0x21,0x30,0x47,0x93,0xe7,0xc9,0x3,0x6e,0x5c,0x68,0x9a,0xb4,0x22, + 0x86,0xcb,0x66,0x86,0x48,0x72,0x66,0x4f,0xbb,0xc4,0x48,0x29,0x85,0x99,0xd1,0x4a, + 0xd8,0xac,0xa8,0xfe,0xc8,0x4d,0xc0,0x1,0xee,0x2f,0xef,0xe2,0xee,0xd2,0x5e,0x28, + 0x55,0xf0,0xc4,0xc8,0x10,0x79,0x1f,0x84,0x93,0x56,0xf,0x9f,0x3d,0xde,0xc6,0xdd, + 0x95,0x7d,0x7c,0xff,0xfa,0xc,0xfe,0xf2,0xdb,0xe7,0x70,0x75,0x76,0xc8,0xcb,0x4a, + 0x8f,0x72,0x67,0xa2,0x67,0xc4,0x85,0xa9,0x1a,0x86,0x6,0xa,0x38,0x33,0x36,0x88, + 0xff,0xf3,0xbd,0x7,0xf4,0xc9,0x83,0x75,0xb6,0x83,0xa3,0xd6,0xf5,0x18,0x9e,0xb, + 0x43,0xe,0x87,0x24,0xc8,0xc3,0x81,0xf3,0x1e,0x20,0x3,0x92,0xdb,0x27,0x8c,0xb4, + 0x23,0x8d,0x51,0xc9,0x84,0xc5,0x84,0xa3,0xc4,0x74,0x6d,0xdc,0x4e,0x96,0xab,0xc8, + 0xbe,0x5b,0xba,0xa1,0xc8,0x4b,0xad,0x9c,0xf2,0x92,0x6e,0x63,0xbe,0x2f,0x2a,0xbe, + 0x2e,0x23,0x44,0x86,0xda,0x24,0x77,0x55,0x69,0xbb,0x1a,0x8b,0x40,0x8f,0xa4,0x95, + 0x7a,0x19,0x58,0x52,0xed,0xc3,0x96,0xf3,0xe4,0xf,0x12,0x14,0x16,0x74,0xdb,0xa9, + 0x53,0x4,0xbf,0xa7,0x8,0x51,0x5f,0xf9,0x58,0x32,0x1b,0x4,0xdc,0xe0,0x24,0x9e, + 0x87,0x32,0xcb,0xa1,0x83,0x1c,0xe4,0x1,0x9f,0x54,0xa0,0x77,0xb6,0x24,0x75,0x52, + 0x21,0xcb,0xd8,0xd2,0xd7,0x6c,0x2e,0xb9,0x2,0xe9,0xd0,0x15,0x83,0xc3,0x3b,0x8d, + 0x45,0x58,0xd3,0x95,0xf6,0x93,0x53,0x26,0x4a,0x55,0x8c,0x55,0xb2,0xfd,0xa5,0x74, + 0x8a,0xf0,0xee,0xcd,0x33,0xea,0x27,0xaf,0xcd,0xd1,0xab,0x67,0x27,0x68,0xb0,0x98, + 0xf5,0xf6,0xc3,0xbe,0x49,0x4c,0x7,0x4f,0x37,0xeb,0xf8,0xc7,0xcf,0x9e,0xe1,0x93, + 0x87,0x1b,0x78,0xba,0x7e,0x80,0x46,0xbb,0x17,0x4f,0xac,0xf1,0xe,0x6c,0x8a,0xf, + 0xda,0x56,0x6a,0x6d,0x48,0x57,0x52,0x2e,0x24,0x1a,0x25,0x92,0xcd,0x8f,0xf,0x85, + 0x4c,0xd4,0x4a,0xb8,0x30,0x5d,0x43,0x31,0x9b,0x4e,0x24,0xbf,0x98,0x7,0xea,0xa8, + 0xd1,0xc6,0xb3,0x8d,0x43,0xec,0x1f,0x9d,0x46,0xa6,0xce,0x84,0xac,0x5d,0x71,0xf3, + 0x95,0x72,0x19,0xbc,0xfb,0xca,0x2c,0xfe,0xfc,0xad,0x73,0x98,0x1a,0x2e,0x25,0x22, + 0x15,0xf2,0x7b,0x1d,0x1e,0xb7,0xf0,0x5f,0xbe,0x78,0x86,0xf7,0xef,0xac,0xe2,0xfe, + 0xf2,0x1e,0xea,0xcd,0x36,0x8c,0xc7,0x0,0x29,0x65,0xf,0x98,0x7e,0x91,0x8c,0x64, + 0x21,0xd6,0x8,0x4a,0xc5,0x7e,0x92,0x85,0xf6,0x72,0xb7,0x4d,0x99,0xee,0x1c,0xc3, + 0x23,0x54,0x85,0xa9,0x29,0x6,0x77,0xe3,0xc8,0xfe,0x1a,0x62,0xa8,0xb3,0xbb,0x1e, + 0x86,0x49,0xce,0xa4,0x8,0x73,0xdd,0xde,0xa5,0x2a,0x4a,0x47,0xa5,0x58,0x5a,0xb5, + 0xb0,0x2a,0x71,0xd3,0xa6,0xd7,0xd0,0x89,0xa0,0x18,0x44,0xa1,0x7e,0xc1,0x91,0xd0, + 0xe,0xc4,0xa1,0x94,0x6a,0x30,0x8f,0x1f,0xdd,0x3c,0x83,0x77,0xae,0x4e,0xe3,0xda, + 0xdc,0x8,0xaa,0xa5,0x9c,0x37,0x4d,0x46,0x8b,0x50,0x14,0x1e,0xde,0xad,0x37,0xf1, + 0xc9,0xa3,0xd,0xfc,0xec,0xd3,0x45,0x3c,0x5c,0xd9,0x83,0xcf,0xf1,0x8e,0xae,0x82, + 0xa2,0xeb,0xeb,0x38,0x7e,0x14,0x5a,0x60,0xb2,0x26,0x5e,0x15,0x70,0x69,0x66,0x8, + 0x3,0x85,0x8c,0x77,0x1f,0x44,0x7f,0xae,0xf5,0xfd,0x63,0x7c,0xf5,0x6c,0xb,0x87, + 0x8d,0x96,0xd3,0x23,0x47,0xd6,0x51,0xf6,0x5e,0xc,0x8d,0x21,0x21,0x47,0x11,0x52, + 0xc2,0xaf,0xda,0x41,0x35,0x9a,0x39,0x6b,0xe5,0xd9,0xcc,0x96,0x14,0x43,0x38,0x37, + 0x55,0xa1,0x4b,0x33,0x35,0x5c,0x9c,0xac,0x61,0x76,0xb4,0x4c,0x33,0xa3,0x65,0x4c, + 0xd,0xd,0x78,0xcd,0x50,0x3f,0xc2,0x58,0xbf,0xa6,0xe4,0xf3,0x27,0x9b,0xfc,0xe1, + 0xbd,0x75,0xbe,0xb7,0xba,0x87,0x95,0xed,0xe3,0x30,0xc7,0xdb,0x12,0xa4,0x4c,0x66, + 0x53,0xc0,0x96,0xb8,0x15,0x28,0xe3,0x48,0x6a,0xac,0x50,0xd8,0x37,0x22,0x12,0xc2, + 0x6b,0xc4,0x7c,0x1,0xc8,0xd9,0xbc,0xba,0xf2,0xc6,0x3a,0x56,0x32,0xc9,0x5e,0x1, + 0x44,0x9c,0xcb,0x66,0x68,0x6a,0xa8,0x84,0x19,0x81,0x2e,0x26,0x11,0x79,0x53,0x4a, + 0xe1,0xf1,0xc6,0x21,0x6e,0x3f,0xdf,0x41,0xa7,0xd3,0x13,0xa4,0x50,0xb6,0x5c,0xf1, + 0x28,0x32,0xdb,0x68,0x75,0xf1,0xfb,0xfb,0x1b,0x38,0x38,0x6e,0xd1,0xeb,0xe7,0xc6, + 0xf0,0xc6,0xf9,0x31,0xbc,0x7e,0x6e,0x3c,0x71,0x4a,0x4f,0x8a,0x5e,0x1d,0x1e,0xcc, + 0xe3,0xc6,0xfc,0x28,0x3a,0xbd,0x0,0x63,0xd5,0x2,0xfd,0xea,0xab,0x65,0x6e,0xb4, + 0xba,0x9e,0xe6,0xda,0xbd,0xf4,0x4a,0xd0,0xa5,0xad,0x76,0xc4,0x75,0xf9,0x46,0x63, + 0xcb,0x76,0x57,0xa2,0x57,0xb4,0x4c,0x8,0x98,0x8,0xca,0x8e,0x98,0x8,0x33,0x1f, + 0x42,0x16,0x43,0xc0,0x4c,0x1e,0xd,0x51,0xff,0x8d,0x81,0xe9,0x3,0x8a,0x51,0xe9, + 0xfc,0xfb,0xdf,0xeb,0xdd,0x45,0x2e,0x9,0xbb,0x35,0xbb,0x2c,0xd4,0xe4,0xd3,0xd6, + 0x48,0xac,0xf0,0xac,0x64,0x8d,0x11,0x9f,0xc0,0xe5,0xeb,0x6a,0x55,0x20,0xca,0x1f, + 0xf2,0xe4,0xb1,0xa1,0xa4,0xec,0x4f,0x43,0xee,0x24,0x86,0x9c,0xa8,0xc5,0xac,0x81, + 0xdf,0x5d,0x8f,0x23,0xa5,0x6c,0x82,0xf9,0xaa,0x84,0x10,0xce,0x5e,0x8,0xe5,0x82, + 0x35,0x84,0x25,0x5e,0x38,0x65,0x8b,0x63,0x51,0x59,0x7b,0x34,0x92,0x3c,0x77,0x39, + 0xa9,0xeb,0x7f,0x23,0xd2,0xd4,0x48,0xec,0xd2,0x25,0x4,0xef,0xc8,0x73,0x8e,0x19, + 0xaf,0x8f,0x5d,0x72,0xb1,0xa8,0xe5,0x42,0x96,0x2e,0xcc,0xd4,0xe8,0xa7,0x6f,0x2c, + 0xd0,0xf,0x6f,0x9c,0xb1,0xce,0x6f,0x49,0x85,0xab,0x71,0xda,0xc1,0xa3,0xb5,0x7d, + 0x7c,0x78,0x6f,0xd,0x7f,0xf7,0xc9,0x33,0x6c,0x1f,0x36,0xe1,0x59,0xda,0x79,0x19, + 0x88,0x7a,0x79,0xa6,0x84,0x56,0x34,0x7a,0x9d,0x8c,0x26,0xd1,0x9b,0xe2,0x15,0x4c, + 0xb8,0x8f,0x70,0xd4,0xd1,0x15,0x47,0xb0,0x77,0x89,0x30,0x5e,0x2b,0x61,0x7e,0xbc, + 0x82,0x5c,0xb6,0xff,0x84,0xc4,0xcc,0xd8,0x3c,0x38,0xc1,0x93,0xcd,0x3,0x34,0xbb, + 0x3d,0x2f,0xf1,0x5a,0xf2,0xec,0xa2,0x2c,0xcb,0xc1,0x52,0x16,0xd7,0xe7,0x46,0xf0, + 0xee,0x2b,0xb3,0xb8,0x3e,0x37,0xf2,0x42,0x9b,0xcb,0x20,0x8,0xb0,0x7b,0x74,0x8a, + 0x5b,0x8b,0xdb,0xf8,0xbb,0x8f,0x9f,0xe1,0xd6,0xe2,0xb6,0x67,0xb,0x6c,0xa9,0x5d, + 0xfc,0x4d,0x7e,0xe4,0x86,0xa6,0xec,0xec,0x73,0xb4,0x35,0x13,0xec,0xc0,0x62,0xd8, + 0x15,0x6c,0x12,0x13,0xbd,0x69,0x3b,0xbc,0xc5,0x52,0x7a,0xd,0x20,0x26,0xd,0xc1, + 0x43,0xd1,0x29,0x9c,0x51,0xed,0x88,0x75,0x37,0x24,0xf2,0x59,0x4a,0x1e,0x4b,0xdd, + 0xa3,0x5e,0x27,0xb2,0x42,0x3c,0x39,0x94,0x73,0x7b,0x92,0x76,0xca,0x62,0x19,0x1a, + 0xa5,0x74,0x9b,0x7,0xbf,0x90,0x4d,0x61,0xa2,0x56,0xc2,0x2b,0xf3,0x23,0xf8,0xf3, + 0xb7,0xce,0xe1,0xda,0xdc,0x88,0xd7,0xc,0xf5,0x2b,0xe4,0xf2,0x30,0xad,0x9f,0xb4, + 0xf0,0xf9,0xd3,0x2d,0xbc,0x7f,0x67,0x15,0xb7,0x16,0x77,0x90,0x64,0x8d,0x47,0xae, + 0x72,0x33,0x13,0x49,0x53,0x4e,0x48,0x3b,0x66,0xfb,0x3c,0xc0,0xc9,0x26,0xc7,0xaa, + 0x25,0x9c,0x9d,0xa8,0xa0,0x98,0x4b,0xf7,0x8d,0xd2,0xc,0x95,0x15,0xd,0xdc,0x5e, + 0xda,0xc5,0x51,0xb3,0x1b,0x93,0xe3,0x48,0x7b,0x59,0x7b,0xf5,0x14,0x49,0x9b,0x6a, + 0xf6,0xd6,0x43,0xd2,0xbd,0x12,0x6e,0xf1,0x98,0xc9,0x2a,0x2a,0x64,0xd2,0x28,0xe4, + 0x32,0x98,0x1e,0x2e,0xe1,0xb5,0x73,0xa3,0xf8,0xd6,0xf9,0x49,0xba,0x76,0x66,0xc8, + 0x1a,0xf0,0xf4,0x6b,0x38,0x92,0x9a,0x4c,0xd6,0xaa,0xe5,0x66,0xbb,0x83,0xf5,0xfd, + 0x13,0xdc,0x59,0xdc,0xe5,0x9f,0x7f,0xf5,0x9c,0x3f,0xb8,0xbb,0xa6,0x35,0x10,0xb6, + 0x5e,0xb0,0xce,0x7,0xb1,0xc6,0x26,0xa1,0x91,0x48,0x18,0xbb,0x69,0xa7,0x72,0x10, + 0x14,0x2,0x17,0xe6,0x21,0x3c,0xdc,0x49,0xbc,0x26,0x1c,0x65,0xa,0x1b,0xc7,0x42, + 0x7b,0x6e,0x93,0x33,0x4d,0x8c,0x30,0x3b,0x89,0x8,0x23,0xd5,0x2,0x46,0x6,0xb, + 0x31,0x62,0x5f,0xb4,0x89,0xa9,0x9f,0xb4,0xb0,0xb8,0x55,0xc7,0xf3,0xed,0xe3,0xf0, + 0x65,0x15,0x26,0x2a,0x49,0x4e,0xf1,0x7a,0x53,0x85,0xfd,0x46,0xb,0xbf,0x7f,0xb8, + 0xc1,0x9b,0x7,0xd,0x3a,0x6c,0xb4,0x91,0x52,0xa,0xf3,0x63,0x83,0x28,0xe5,0xd2, + 0xd6,0x68,0x4b,0xee,0xe8,0xa3,0xe4,0xb9,0xda,0x40,0xe,0xdf,0xbb,0x32,0x85,0x72, + 0x21,0x8b,0x83,0xe3,0x16,0xee,0x2c,0xed,0xa1,0xde,0x68,0x4b,0x18,0xc6,0x99,0x3a, + 0x28,0x68,0x44,0xdd,0xf0,0x61,0x8c,0xd5,0xa9,0x4e,0x42,0x64,0x43,0xf6,0x67,0x93, + 0xa5,0x68,0x2c,0x3c,0x2c,0x65,0x2d,0xac,0xe4,0xca,0xb8,0xc0,0x6b,0x5c,0x57,0xd7, + 0x23,0xcf,0x1,0xce,0x20,0x80,0xac,0xbf,0x3b,0xc7,0xf6,0xd9,0xec,0xf7,0xe6,0xa2, + 0x6e,0x9,0xf9,0x25,0x25,0x8d,0xed,0xec,0x79,0x4d,0x38,0x54,0x9b,0x84,0xe2,0x45, + 0x9,0xbc,0x9e,0x23,0xcf,0x7,0xc5,0xa6,0x2f,0xa2,0x88,0x4c,0x8a,0xe3,0x24,0xdf, + 0x74,0xd4,0x68,0x89,0x15,0xbc,0xe0,0x9,0xfb,0xd8,0x9,0xeb,0x67,0xbb,0xd1,0x91, + 0x7,0x98,0x80,0xed,0x59,0xc0,0x4,0x51,0x4e,0x80,0x99,0xcc,0x49,0x60,0x47,0xb6, + 0xbc,0x9b,0xf9,0xda,0xaa,0xb5,0x94,0xe6,0xa9,0x1b,0x80,0x1c,0x12,0x62,0x77,0x45, + 0x5a,0xe9,0xec,0x73,0x17,0x9f,0x4a,0x36,0xe7,0xdc,0xd0,0x3d,0x84,0x99,0xe7,0xcd, + 0xf3,0x63,0xf4,0xbf,0xfc,0xe4,0x3a,0x9d,0x9b,0xac,0x51,0x3a,0x9d,0xea,0xb,0x5b, + 0x1e,0x37,0xdb,0xb8,0xb3,0xb4,0x8b,0xbf,0xf9,0xe8,0x31,0x7e,0x7b,0x77,0xd,0x47, + 0x8d,0xb6,0x25,0x8f,0x40,0xb4,0x6b,0x96,0x58,0x4d,0x62,0xa7,0x41,0xf0,0xad,0x35, + 0x4d,0xd3,0xe3,0x64,0x4f,0x8e,0xd9,0x41,0x88,0xeb,0xfa,0xd,0x1a,0x62,0x47,0xd2, + 0xf0,0xc5,0x1c,0x1e,0x2c,0x60,0x76,0x64,0x0,0x99,0xc8,0x1e,0x30,0xfa,0xb6,0x5d, + 0x3f,0xc5,0xd2,0xd6,0x11,0x5a,0x9d,0x9e,0xcd,0xb5,0x91,0xf4,0x5a,0xdf,0xaf,0x3d, + 0x5c,0xc9,0x5d,0x9e,0x19,0xc6,0xff,0xf4,0xe3,0x6b,0xb8,0x3c,0x33,0x9c,0x58,0x30, + 0x64,0xe1,0x68,0xb4,0x7a,0xf8,0xd9,0xa7,0xcf,0xf0,0xb7,0x1f,0x3f,0xc3,0xca,0x4e, + 0x3d,0xa1,0xf8,0x19,0x61,0x28,0x7b,0x93,0x65,0x62,0x3d,0x57,0xae,0x61,0x61,0xf8, + 0x6b,0x69,0x8,0xbf,0x29,0xf6,0x43,0x83,0xdd,0xe0,0xb,0x61,0xba,0xcc,0x1c,0x93, + 0x7b,0x98,0xde,0x40,0x66,0x6,0xc1,0xda,0x7e,0x8a,0xf8,0xae,0x98,0xd8,0x3c,0xd2, + 0xb3,0x7b,0xf,0xa8,0x6f,0xc8,0x24,0xc4,0xed,0x24,0xfd,0xac,0x29,0x42,0x65,0xa6, + 0x3e,0x1c,0x89,0x7c,0x36,0x8d,0xd7,0xcf,0x8d,0xe1,0x87,0x37,0xcf,0xe0,0x3b,0x97, + 0x26,0x30,0x32,0x58,0x78,0x69,0x1f,0x6e,0x67,0xb1,0xda,0xc6,0xad,0xe7,0xbb,0xf8, + 0x8f,0x1f,0x3e,0xc1,0x67,0x8f,0x37,0x19,0x91,0xe7,0x94,0x24,0xc9,0xc3,0x99,0x67, + 0x70,0xd4,0x42,0xce,0x47,0xd2,0x24,0xe9,0x87,0x31,0x52,0x29,0x60,0x6e,0x74,0x30, + 0xc6,0x8b,0xf0,0x8b,0x27,0x63,0x65,0xf7,0x8,0x8f,0x56,0xf,0xf5,0x4a,0xa5,0x1f, + 0x1f,0x84,0x7c,0x77,0x3d,0xd2,0xa6,0x9b,0xc2,0xfe,0x4f,0xc6,0x6d,0xca,0x9,0x97, + 0x40,0x98,0x1f,0xab,0xe0,0xf5,0x73,0x63,0x78,0xf3,0xfc,0x18,0x9d,0x9d,0xa8,0xa2, + 0x5c,0xc8,0xa2,0x94,0x4b,0x23,0x9f,0x4d,0x7b,0x4d,0xe4,0x8b,0xae,0x63,0xf4,0xe3, + 0xcd,0x76,0x7,0xbf,0xbe,0xbd,0xc2,0x1f,0xdc,0x5b,0xe3,0xaf,0x9e,0xed,0x60,0xe7, + 0xb0,0xc1,0x6c,0xd3,0x93,0x8d,0x37,0x81,0x2d,0xae,0x76,0xcc,0x13,0x5e,0x70,0x66, + 0x8b,0x61,0x16,0x96,0xc6,0xa1,0xdc,0xd2,0x0,0x3c,0xa2,0xa6,0x15,0x72,0x58,0x6b, + 0x29,0x93,0x28,0x67,0x97,0xaa,0xe1,0x8f,0x2f,0x27,0x35,0xb7,0xb9,0x1f,0x2a,0xe7, + 0xe9,0xe2,0x64,0xcd,0xdb,0x6f,0x27,0xbd,0x2e,0xcd,0x76,0x17,0x8b,0xdb,0x75,0x6c, + 0xed,0x37,0xd,0x2a,0x62,0x29,0xf8,0xd1,0x15,0xa9,0xbb,0x36,0xbe,0x9f,0xc8,0xf2, + 0xce,0x31,0xff,0xe7,0xcf,0x17,0x71,0xe7,0xf9,0x2e,0x7e,0x74,0x73,0x96,0x7e,0xfa, + 0xfa,0x9c,0xd7,0x48,0x44,0x51,0x1,0xf9,0x56,0xc8,0x65,0x70,0xed,0xcc,0x30,0xfe, + 0xd7,0x3f,0xb9,0x41,0xff,0xf0,0xe9,0x22,0xff,0xa7,0x8f,0x9e,0xa0,0xd9,0xe9,0xb9, + 0x25,0xb4,0xfd,0xe6,0x21,0xc2,0x21,0x21,0x6c,0xe,0x34,0x5e,0xa6,0x39,0xdb,0xa2, + 0xf1,0x93,0x72,0x6f,0x72,0x91,0x30,0x76,0xca,0xd7,0x4f,0x61,0x4a,0xe6,0x8c,0x7a, + 0xe9,0x2a,0x60,0x62,0x65,0x88,0x76,0x22,0xef,0x31,0xbc,0xdd,0x89,0x59,0x88,0x66, + 0x4c,0xe6,0x23,0xc1,0x33,0x79,0xf7,0x14,0x21,0x2e,0x50,0x54,0x9,0x35,0x7,0xc7, + 0x39,0x4b,0x4c,0x82,0xdc,0xe7,0x88,0xc8,0xde,0x75,0x24,0x3f,0x97,0xd5,0x23,0xc9, + 0x11,0x83,0xa3,0x1e,0xd6,0xc,0xa4,0xa1,0x28,0x12,0xf7,0x26,0xe8,0x77,0xe4,0x3f, + 0x54,0x9e,0xce,0x42,0x79,0x78,0xba,0xc7,0xc,0x96,0x9f,0x6f,0x8b,0xb3,0x27,0x51, + 0xb3,0x7,0x39,0x59,0x2c,0x5e,0x1e,0xa8,0xfa,0xe3,0xa4,0xdc,0x44,0xee,0x4f,0xe5, + 0x32,0x42,0xd5,0x8d,0xe4,0xb0,0x30,0xbb,0xd1,0x31,0x39,0x27,0x19,0x6,0x21,0x93, + 0x22,0xbc,0x7e,0x6e,0x5c,0xfd,0xf8,0xe6,0x1c,0x5d,0x9f,0x1b,0xa1,0x6c,0x26,0xdd, + 0x97,0x21,0x6c,0xa6,0xcf,0x5f,0xdf,0x5a,0xc6,0x27,0xf,0x37,0x71,0x64,0xf6,0x90, + 0xba,0x9b,0x32,0xdb,0xe,0xd6,0x1e,0xc5,0x96,0xfb,0x4f,0xec,0xfb,0x54,0x4b,0x2b, + 0x50,0x99,0x6c,0x17,0xe1,0x7a,0x32,0x92,0xfc,0x4b,0x84,0xc2,0x5f,0xff,0xfa,0x83, + 0xc5,0x1c,0x46,0x2a,0x45,0x64,0xd2,0xc9,0x6,0x37,0xe6,0x63,0x7b,0x47,0xa7,0x58, + 0xdd,0x3b,0x41,0x5b,0x48,0xd5,0xe4,0x1a,0xc0,0x13,0x2a,0x29,0xc2,0xcd,0xf9,0x61, + 0xfc,0xe0,0x46,0x38,0x99,0xcb,0x4c,0xf7,0xa4,0xa2,0xbe,0xb2,0x7b,0x8c,0x8f,0xee, + 0xaf,0xe1,0x57,0xb7,0x57,0xf0,0x78,0xfd,0x20,0xe1,0x28,0x70,0x3b,0x5a,0x49,0xa0, + 0xeb,0xbb,0xf7,0x85,0x2f,0x31,0xa,0x7b,0x6a,0x66,0x6f,0x73,0x25,0x14,0x76,0x7e, + 0xaa,0x34,0x3b,0x82,0x36,0x8b,0x3d,0x31,0xc7,0x95,0x69,0xf6,0xb1,0x54,0x4c,0x5e, + 0x2b,0x64,0x98,0x1c,0x64,0x4b,0x9c,0xc7,0xb7,0x88,0xb5,0x4d,0x9e,0xac,0x4d,0x90, + 0x77,0x98,0xbc,0xe9,0x93,0x45,0xc7,0x2e,0x7f,0x11,0xf9,0xa,0x67,0xd2,0xa,0x67, + 0x46,0x6,0x71,0x7d,0x6e,0x8,0xdf,0xba,0x30,0x8e,0xd7,0xcf,0x8d,0x63,0x72,0xc8, + 0x5f,0x75,0xc4,0xa7,0x48,0x8e,0xc9,0xa9,0xb6,0xf,0x9b,0xf8,0xfc,0xc9,0x26,0xde, + 0xbb,0xb3,0x8a,0x3b,0x8b,0x3b,0x1c,0xf6,0x71,0xe4,0x11,0x6c,0x84,0xab,0x72,0xa4, + 0xcb,0x37,0x9,0x38,0x7a,0x15,0x69,0x36,0x8b,0x2,0x27,0x49,0xa5,0x80,0xb1,0xc1, + 0x22,0x46,0x2b,0x5,0x3b,0x95,0x25,0x21,0x4,0xad,0x4e,0x17,0x6b,0x7b,0x27,0x58, + 0xdb,0x6d,0x84,0x32,0x49,0x22,0x4b,0x44,0x72,0x7d,0xa9,0xf2,0xf8,0x8a,0x1c,0x2b, + 0xd5,0xd6,0xec,0x14,0xc2,0x82,0x7,0xd5,0x81,0x1c,0x46,0xcb,0x5,0x1a,0xaf,0x16, + 0x78,0xbc,0x56,0xa2,0xf9,0xf1,0x41,0x5c,0x98,0xac,0xe0,0xf2,0x74,0xb8,0xdb,0x8d, + 0xed,0x8c,0x5f,0xb0,0x9e,0x88,0x23,0x5a,0xd,0x3c,0xdf,0xaa,0xf3,0xc3,0xd5,0x3, + 0x7c,0xf2,0x68,0x93,0xef,0x2e,0xef,0xf2,0xee,0xf1,0x29,0x10,0x68,0x83,0x12,0x98, + 0x28,0x31,0xeb,0xcc,0xc3,0xcc,0x9a,0x90,0x69,0x5c,0xc7,0x5d,0x4f,0xca,0xee,0xf0, + 0x64,0x20,0x20,0x76,0x16,0xb0,0xd6,0xe9,0xc8,0x8d,0x80,0x4e,0x58,0x4b,0x1a,0xc1, + 0x63,0x8f,0xbc,0xa9,0x44,0x77,0x43,0x9e,0x25,0xd,0x86,0x7,0xb,0xb8,0x38,0x5d, + 0x45,0x39,0xe2,0x20,0x18,0x5d,0x23,0xec,0x1c,0x36,0x71,0xfb,0xf9,0x2e,0x76,0x8e, + 0x9b,0x2,0xa7,0x61,0xcf,0x91,0x4c,0xa7,0x91,0x2,0x51,0x77,0x32,0xfd,0x7e,0x8f, + 0x81,0xdd,0xa3,0x36,0xf6,0x8e,0x77,0xc1,0xcc,0xdc,0xee,0x6,0xf4,0xda,0xd9,0x11, + 0x9c,0x9f,0xa8,0xa1,0x5c,0xcc,0x24,0x9e,0x47,0xf2,0x4c,0x2d,0x17,0xb2,0xb8,0x7e, + 0x66,0x18,0xa7,0xed,0x2e,0x75,0xba,0x3d,0xfe,0xf8,0xd1,0x16,0xad,0xec,0x1c,0xb3, + 0x97,0xe8,0x12,0xda,0x18,0x5a,0x52,0x6b,0x38,0xc0,0xea,0x28,0x36,0x97,0xe3,0x23, + 0x7c,0xf7,0x34,0xe1,0x26,0xc5,0xa4,0xa3,0x5a,0x48,0x60,0xe2,0xa4,0xbd,0x21,0x6c, + 0x6d,0xd1,0xe0,0xa,0xb3,0x87,0x8f,0x28,0x32,0xd2,0x18,0x2,0xc9,0x72,0x1b,0xf1, + 0x55,0x31,0xba,0x4,0x81,0xcd,0x19,0x62,0xb0,0x52,0xfe,0x99,0xa3,0x64,0x2d,0xa5, + 0x38,0xb7,0x46,0xd8,0xb6,0x42,0x4,0xae,0x58,0x79,0xb8,0x4a,0x6e,0x3a,0x29,0xc2, + 0x67,0xf6,0x82,0x20,0x15,0x90,0x86,0x6d,0x7b,0x64,0x27,0x2c,0x1a,0x76,0x6b,0x68, + 0x1d,0xd9,0x2e,0x90,0x8b,0x91,0xb4,0x16,0x98,0x66,0x77,0xaa,0xc9,0x36,0x91,0x9c, + 0x19,0x37,0x24,0x29,0x31,0x7b,0x91,0xdb,0x33,0xda,0x58,0x4b,0xd2,0x36,0x95,0x21, + 0x35,0x9d,0x4c,0x26,0xac,0x22,0x7f,0xda,0x86,0xa,0xf1,0x7a,0xf6,0x48,0x70,0x6e, + 0xdf,0x4e,0x22,0x7f,0x94,0x40,0x34,0x35,0x3c,0x40,0xff,0xf6,0x7b,0x17,0xe9,0xdb, + 0x17,0x27,0x28,0x1a,0x5b,0x29,0xdf,0x4e,0x4e,0x3b,0xf8,0xfd,0x83,0x75,0xfc,0xd3, + 0x97,0xcf,0xf1,0xfe,0x9d,0x55,0xbb,0x94,0x95,0x7,0xba,0xf9,0xcd,0x28,0xe6,0x12, + 0x44,0x11,0x30,0x35,0xce,0x6f,0xa7,0x4,0x6c,0xcb,0x4b,0x9c,0xe6,0xf8,0xee,0xdd, + 0x7c,0xbc,0x94,0xcf,0xa0,0x5a,0xca,0x23,0xdd,0xa7,0x40,0x9a,0x7,0xea,0xb0,0xd1, + 0xc6,0xe6,0x7e,0x13,0xdd,0xe,0x27,0x12,0xee,0x8,0xae,0x4b,0x1d,0xab,0x14,0xf0, + 0x57,0xdf,0x39,0x8f,0x77,0xae,0x4e,0x21,0x2b,0x22,0x22,0x63,0xba,0xf1,0x5e,0x80, + 0x23,0x7d,0x6d,0xfe,0xb7,0x9f,0xdf,0xc3,0xfa,0xfe,0x89,0xb3,0xaf,0xb4,0xcd,0x9d, + 0x6f,0x5f,0xfb,0x12,0xe3,0xa5,0xb5,0xfa,0x35,0xfe,0x4c,0x1e,0xaf,0xc3,0xf5,0xaa, + 0x6c,0x73,0x26,0x95,0x98,0x8f,0x94,0xf3,0x6e,0x14,0x38,0xa1,0x6b,0xae,0x9c,0x6, + 0x58,0xba,0x3b,0x90,0x62,0x92,0x97,0x96,0xd8,0x4,0x7,0x90,0xf7,0x4,0x91,0x67, + 0xee,0x43,0xee,0x3e,0x76,0xfa,0x78,0xe5,0x9,0x4,0x22,0x23,0x83,0x98,0x47,0xe3, + 0x42,0xb0,0x4c,0x9a,0x30,0x37,0x56,0xc1,0xbf,0xfe,0xce,0x39,0x7c,0xf7,0xf2,0x4, + 0xa6,0x86,0x4a,0x48,0xa7,0x52,0x7d,0xbd,0xf8,0x13,0x1f,0x70,0x22,0x6c,0x1f,0x36, + 0xf0,0xe1,0xfd,0x75,0xfc,0xc3,0x67,0xcf,0xf8,0xe3,0x47,0x5b,0x62,0xa5,0x42,0x1e, + 0x1c,0x68,0x25,0x43,0x24,0x90,0x37,0x8a,0xac,0xb,0x6c,0xeb,0x44,0x16,0x8d,0x22, + 0x0,0x3,0x85,0xc,0x2e,0xce,0xd4,0x30,0x5e,0x29,0xbd,0xf0,0xe7,0x3a,0x6a,0x76, + 0xf0,0xe5,0xd3,0x6d,0xac,0xee,0x9d,0xf8,0x8e,0x74,0x88,0x6,0xd7,0x44,0x9e,0x5, + 0x16,0x87,0x9c,0xf7,0x1c,0x84,0xc0,0xf5,0x44,0xad,0x48,0x57,0x66,0x86,0xf0,0xfa, + 0xf9,0x51,0xbc,0x32,0x37,0x4c,0x17,0x26,0xab,0xd6,0xb0,0x28,0xc9,0xa6,0x34,0xaa, + 0x25,0x7f,0xd1,0xdb,0xd6,0x41,0x3,0x1f,0xdd,0x5f,0xe7,0x5f,0xde,0x5e,0xe1,0xdf, + 0x3f,0xdc,0xe4,0x76,0xb7,0xa7,0xb9,0x41,0xc4,0xb6,0x98,0xb2,0x9e,0xce,0xd9,0xb2, + 0xf0,0x38,0xcc,0xf4,0xa,0xcc,0x7a,0x40,0xb,0x9f,0xad,0xff,0x10,0x1b,0xe8,0x27, + 0xd0,0xb1,0xa0,0xac,0x44,0x5f,0x15,0x39,0x95,0xb5,0x34,0xcb,0x92,0x33,0x6d,0xef, + 0xc5,0x11,0x84,0x82,0x7c,0x93,0x92,0xe1,0x72,0x1,0xe7,0x27,0x6b,0x24,0x3d,0xfe, + 0xa3,0xd7,0x83,0x99,0xb1,0xb6,0xdf,0xc0,0x57,0x8b,0x3b,0x38,0x38,0xe9,0x98,0xf0, + 0x11,0x7b,0xef,0x92,0xaf,0xe1,0xb0,0x8c,0x15,0x42,0xd4,0x8b,0xdc,0x29,0xf1,0x6e, + 0x2f,0xef,0xd3,0xe3,0x8d,0x23,0xfe,0xa3,0xd7,0x66,0xf1,0xa3,0x1b,0x3d,0x7a,0xfd, + 0xec,0x8,0x8a,0xf9,0x6c,0x8c,0x0,0x9b,0xf4,0x1a,0xbc,0x7e,0x76,0xc,0xd3,0xc3, + 0x3,0x94,0x4d,0xa7,0xf8,0xe7,0x5f,0xad,0x60,0xef,0xe4,0x34,0xb4,0x65,0x37,0x84, + 0xa,0x61,0xbf,0x2a,0xa6,0x59,0xb2,0xeb,0xa,0xf3,0x48,0x6,0xc2,0xd8,0x92,0xad, + 0x9f,0xb3,0xa6,0xc1,0x83,0x10,0xe8,0x7d,0x92,0xdb,0x0,0xea,0x52,0xa5,0x1b,0x6, + 0x17,0xe5,0xcd,0x8c,0x20,0x2e,0x19,0x26,0x10,0x82,0x4,0x7,0x15,0x12,0xc4,0x35, + 0xd1,0x23,0xc7,0x26,0x66,0x81,0x70,0x78,0xe3,0x87,0x40,0x66,0x4d,0x31,0xf7,0xa0, + 0x7b,0x69,0xf9,0xad,0xa4,0x76,0x1f,0x7d,0xa5,0x70,0x6,0x19,0x4f,0x4b,0xa3,0x9, + 0xa9,0x40,0xf5,0x74,0x7c,0x88,0x49,0x7a,0x63,0x32,0x1b,0x5f,0xf5,0xe3,0x24,0x24, + 0xc4,0x14,0xd5,0xea,0x46,0x71,0x1d,0x67,0xcd,0xa8,0x9c,0xe8,0xc8,0xad,0xc1,0xf5, + 0x97,0x53,0x2e,0x21,0x8d,0x48,0x85,0x3b,0x13,0xc1,0x7e,0x37,0xe3,0x30,0x91,0x74, + 0xfc,0x70,0xc7,0xf2,0xd5,0xd9,0x61,0xfa,0xd1,0xcd,0x59,0x75,0x6d,0x6e,0x84,0xaa, + 0xc2,0x2a,0x35,0x7a,0x10,0x2c,0x6e,0x1e,0xe2,0xf7,0xf,0x37,0xf0,0xcb,0x5b,0xcb, + 0xb8,0xb7,0xb2,0xe7,0x35,0x2f,0xec,0xc5,0xa,0xf8,0xee,0xf7,0x42,0x38,0xe8,0x35, + 0x32,0xa,0xc9,0xe,0x40,0x89,0x1d,0x97,0x79,0x10,0x85,0xa7,0x8c,0x7,0x1f,0x2b, + 0x20,0x9b,0x49,0xa3,0x98,0x4b,0x79,0xbb,0xab,0xa4,0xc3,0xbe,0x7e,0xd2,0xc2,0xf6, + 0x51,0x33,0xcc,0x1a,0xb7,0x12,0xf,0x1,0x47,0xeb,0x1b,0xe9,0xfc,0x64,0xd,0x3f, + 0xbc,0x3e,0x83,0x57,0xcf,0x8e,0x5a,0x7f,0x76,0x9,0x91,0xcb,0x83,0x71,0xeb,0xb0, + 0x81,0xbf,0xfd,0xe4,0x29,0xde,0xbb,0xb3,0x8a,0x4d,0xe3,0x2,0x45,0x11,0x2b,0x4b, + 0x2f,0x95,0xf2,0xa5,0x2a,0xba,0x34,0x2d,0x72,0x97,0x47,0x8b,0x84,0x49,0x3f,0x54, + 0x61,0xec,0x69,0xe0,0x5a,0x1b,0xa5,0x75,0x6f,0xb0,0x99,0x2e,0xd2,0xd5,0xc0,0xad, + 0x3f,0x84,0xa8,0x55,0x8e,0xf8,0x7e,0x27,0x46,0x4e,0xa0,0xe2,0x21,0xe2,0xce,0x6c, + 0xd8,0xde,0x2f,0xb2,0xa1,0x25,0x5f,0x86,0x65,0xfb,0x70,0x17,0xe1,0xe2,0x91,0xe0, + 0x4c,0x3,0x3c,0x50,0x48,0xe3,0x95,0xb9,0x11,0x5c,0x3f,0x33,0x8c,0x2b,0xb3,0x43, + 0x38,0x37,0x59,0xc1,0x44,0xb5,0x88,0x74,0x4a,0x25,0x12,0x33,0xfb,0x91,0xe1,0x82, + 0x80,0xf1,0xd5,0xe2,0x36,0x3e,0x7e,0xb0,0xc1,0x1f,0x3e,0xd8,0xc0,0xe3,0x8d,0x43, + 0xf9,0x44,0xda,0x9e,0x5a,0xf0,0x1,0x61,0x68,0x8,0xd1,0xae,0xdf,0x16,0x3,0x41, + 0x49,0x92,0x60,0x48,0x31,0x9b,0xc1,0xc5,0xa9,0x21,0x8c,0x55,0xa,0x89,0x64,0x28, + 0xf3,0x73,0x9f,0x9c,0x76,0xf0,0xe5,0xb3,0x1d,0xac,0xec,0x1e,0x87,0xc8,0x15,0xf9, + 0x51,0xcc,0x48,0x92,0xc3,0xb1,0xd8,0x49,0xea,0xcf,0x1f,0xaf,0x16,0x31,0x3d,0x5c, + 0xc2,0xf4,0xd0,0x0,0xcd,0x8e,0xe,0x60,0xb2,0x56,0xc4,0x44,0xb5,0x84,0xd1,0xc1, + 0x2,0x86,0x7,0xf3,0xc8,0x67,0xd3,0x7d,0xc3,0x43,0xe2,0x16,0xb4,0x41,0xac,0xc0, + 0xf4,0x7a,0x1,0x16,0xb7,0xeb,0xf8,0xea,0xd9,0xe,0xdf,0x7e,0xbe,0x8b,0x27,0xeb, + 0x87,0xbc,0xb4,0x7d,0xc4,0xda,0x7c,0xc9,0x16,0x6d,0x3b,0x1b,0xda,0x9b,0x4b,0xec, + 0xc8,0x55,0x18,0xf0,0xa1,0x33,0x3f,0x75,0xb1,0x37,0x77,0x32,0x33,0x3b,0x5f,0xe9, + 0xc8,0x6d,0xc5,0xf6,0x79,0x26,0x37,0xa1,0xbb,0xb0,0x15,0xa1,0x7b,0x32,0x70,0x3e, + 0x45,0x2d,0x68,0x42,0xa9,0x15,0x86,0x7,0xf3,0xb8,0x38,0x5d,0x43,0xa5,0x98,0x4d, + 0xb4,0x65,0xb5,0x4,0xbf,0xc3,0x26,0xee,0x3c,0xdf,0xe3,0xfa,0x49,0x5b,0x38,0x2c, + 0x7b,0x44,0x3d,0xf6,0x4d,0x8d,0xc8,0xf7,0x8b,0x8f,0xb3,0x43,0xf9,0xb4,0xd3,0xc5, + 0x7,0xf7,0xd7,0x69,0xef,0xb8,0xc5,0x8b,0x5b,0x75,0x7c,0xfb,0xe2,0x4,0x5d,0x9c, + 0xaa,0xf6,0x85,0xde,0xcd,0xc7,0x53,0x29,0x85,0x89,0x6a,0x9,0x7f,0xf1,0xd6,0x59, + 0x1a,0xab,0x96,0xf0,0xf7,0x9f,0x2e,0xf2,0xb3,0xad,0x7a,0x18,0x8d,0xc2,0xec,0xd4, + 0x89,0xe4,0x94,0x54,0x82,0xfb,0xc3,0x16,0x9c,0xd6,0xfc,0x2b,0xe,0x8c,0xde,0x81, + 0x4c,0xd1,0xf,0x27,0x42,0x15,0x10,0x3,0x4a,0x11,0x5,0x41,0xa0,0x97,0xb8,0xf6, + 0x65,0x32,0xd3,0x3a,0x73,0x0,0x2,0x21,0x15,0x7e,0x5c,0x2b,0xe2,0x64,0x36,0x83, + 0x19,0x78,0x39,0x26,0xf2,0x8b,0x1e,0x5b,0x5e,0x6c,0x94,0x17,0x23,0xe5,0x73,0xe6, + 0x48,0xf0,0x7c,0xfc,0x26,0x57,0x92,0xee,0x3c,0xb1,0x13,0x9,0x8d,0x7c,0xa2,0xbe, + 0x34,0x3c,0x77,0xd2,0xc2,0xf6,0x2d,0xf2,0x98,0xf9,0xbc,0x7c,0xbb,0xc5,0x54,0x14, + 0x59,0x83,0xf9,0x1a,0x13,0xcf,0xdc,0x8c,0x9d,0x4f,0x1b,0xcb,0x4e,0x42,0x9f,0xb5, + 0xca,0x46,0x12,0xd8,0x94,0x72,0xa1,0x51,0x57,0x2e,0xa9,0x58,0x85,0x7c,0x64,0x29, + 0x65,0xb3,0xe6,0xaf,0x26,0xb8,0x56,0x59,0x1d,0x32,0xe9,0x8e,0x57,0x6f,0xf7,0x15, + 0x55,0x4b,0x19,0x7a,0xe7,0xca,0x14,0xfd,0xe8,0xe6,0x19,0x1a,0xaf,0x16,0x12,0x77, + 0xe6,0x0,0x70,0xd4,0x68,0xe3,0x93,0xc7,0x9b,0xf8,0xd9,0x67,0xcf,0x71,0xe7,0xf9, + 0xe,0x7a,0x7a,0x2,0x93,0x31,0x78,0x72,0x9,0xc1,0xec,0xdb,0x10,0xca,0x28,0x3c, + 0x4a,0xb8,0xe6,0x9e,0xac,0x21,0xe1,0x85,0x71,0xa6,0x67,0x9,0x45,0x4f,0x9f,0x31, + 0xd9,0x74,0xa,0x39,0xb1,0x2a,0xe8,0x3b,0x4d,0x33,0xa3,0xd7,0x83,0x75,0xc2,0x8d, + 0x86,0xbc,0x90,0x62,0x54,0xa,0x39,0x7c,0xef,0xea,0x14,0x7e,0xfc,0xda,0x19,0x4c, + 0xf,0xf,0xf4,0x8d,0x5b,0xec,0x76,0x43,0xf7,0xb7,0x4f,0x1e,0x6f,0xe1,0x67,0x9f, + 0x2d,0xe1,0xf9,0x76,0xdd,0xfd,0x4c,0xc2,0x5d,0xd0,0xb3,0x64,0x64,0x4a,0x30,0x32, + 0xe9,0xb3,0x43,0x97,0x2d,0x10,0xc9,0x6,0x89,0xbc,0xa4,0xcd,0xf0,0x26,0x61,0xfb, + 0x9c,0x23,0x61,0xd7,0x4b,0x42,0x7a,0x93,0xd0,0x7e,0x11,0x39,0xaf,0x5,0x91,0xae, + 0x19,0x6e,0x46,0x43,0x15,0x99,0x79,0xc,0x8d,0x37,0x82,0x88,0x73,0x53,0x2a,0x59, + 0x99,0x6e,0xb9,0x8b,0x2a,0xd2,0x31,0x1b,0xb6,0x3c,0x21,0x97,0x56,0x28,0xe4,0xd2, + 0x28,0xe5,0x32,0xb8,0x30,0x55,0xc5,0x1f,0x5c,0x9d,0xc2,0x9b,0xe7,0xc7,0xb4,0x97, + 0x0,0xbc,0x46,0x2a,0x4a,0x2c,0x8a,0x6a,0xa4,0x9b,0xad,0xe,0x8e,0x5b,0x5d,0x2c, + 0x6d,0xd5,0xf1,0x8b,0x5b,0x2b,0xfc,0xe1,0x83,0xd,0x2c,0x6e,0xd5,0xf5,0x66,0x4b, + 0xee,0x9f,0xed,0x99,0xcd,0x14,0x63,0xe5,0x93,0xb3,0x10,0x87,0x8b,0x7d,0xd4,0x50, + 0x3b,0xeb,0xf8,0x63,0xfb,0x74,0xf,0x14,0xb3,0xb8,0x30,0x55,0xc5,0x68,0xa5,0x10, + 0x2b,0x8e,0xf2,0xd0,0xde,0x3b,0x3e,0xc5,0xa3,0xf5,0x43,0x6c,0xd5,0x4f,0xdd,0x23, + 0xcc,0x11,0x88,0x51,0x9c,0x1f,0x29,0x2,0xb2,0xd9,0x14,0xb2,0x29,0x85,0x6c,0x26, + 0x85,0x5c,0x3a,0x85,0xf1,0x5a,0x1,0xb,0x63,0x83,0x38,0x3b,0x51,0xc1,0xc5,0xa9, + 0x2a,0xce,0x4d,0xc4,0x75,0xef,0xd2,0xa9,0x2c,0xba,0xd2,0x49,0x72,0x49,0x23,0x22, + 0x74,0xbb,0x3d,0xb4,0xba,0x3d,0x34,0xda,0x1,0x96,0xb6,0xe,0x71,0x77,0x79,0x9f, + 0x7f,0x71,0x6b,0x99,0xef,0x2e,0xed,0x71,0x2f,0x8,0xf4,0x48,0xed,0x18,0xc0,0xe4, + 0x4c,0xed,0x4c,0x45,0x67,0x2d,0x24,0x33,0x7e,0xe1,0x7a,0x30,0xb3,0x6c,0x2b,0x53, + 0x59,0xd8,0x62,0xd,0x3a,0x34,0xc8,0x7,0xf0,0x5c,0x28,0x8d,0x43,0x76,0x8,0x91, + 0xbc,0x6d,0x3b,0xa3,0x44,0x0,0x2d,0x66,0x61,0x9b,0x30,0x32,0x58,0xc4,0xa4,0x96, + 0xb0,0xca,0xb3,0x40,0x5e,0xa3,0x46,0xab,0x87,0xf5,0xdd,0x63,0x6c,0x1c,0x36,0x85, + 0xf4,0x2d,0xe2,0x5a,0x4e,0xca,0xdb,0xc5,0x3a,0x14,0x40,0xb9,0xd5,0x8b,0xd8,0x24, + 0x1b,0x1e,0xc9,0xce,0x51,0x9b,0x7f,0x7b,0x6f,0x3,0x5b,0x87,0x4d,0x6a,0x76,0xba, + 0x9c,0x4e,0x11,0x8d,0x57,0x8a,0x28,0x64,0x53,0xf6,0x3e,0x96,0xfc,0x19,0xf3,0x73, + 0x29,0x45,0xb8,0x34,0x5d,0x43,0xa5,0x98,0xa3,0x7a,0xb3,0x8d,0x4c,0x3a,0xc5,0xcf, + 0xb6,0xea,0x68,0x77,0x7a,0xce,0x2a,0x41,0x87,0xec,0x89,0xc,0xb,0x1d,0xaf,0x0, + 0x10,0x1b,0x47,0x18,0x52,0xa4,0x2,0x33,0x47,0x87,0x4d,0x7e,0x88,0xd9,0x12,0x2, + 0xa5,0x42,0x65,0x3d,0x93,0x49,0x5e,0x62,0x62,0xa2,0xc0,0x44,0xd1,0x6,0x21,0x4f, + 0xcb,0xc2,0xed,0x66,0x2,0x53,0xd6,0xe3,0x95,0x14,0x13,0xb4,0x4b,0x11,0x71,0x5c, + 0x16,0x1f,0x17,0x5e,0xfa,0x5c,0x11,0x73,0x7e,0x58,0x22,0xbc,0x6c,0x9,0x54,0x2, + 0xb1,0x4d,0x32,0xd8,0x25,0xf9,0x9d,0xe2,0xc6,0x32,0xce,0xf0,0x8a,0xad,0x50,0x3e, + 0x6d,0xed,0x18,0x13,0x88,0x11,0x12,0xfd,0x4f,0xb2,0x20,0x4d,0xfc,0x43,0x42,0xb0, + 0x14,0x0,0x50,0x4a,0x7e,0x29,0xf3,0x83,0x28,0x2f,0xc,0x84,0x64,0x4a,0xaa,0x72, + 0x9a,0x74,0x22,0x33,0xc6,0xb9,0xbd,0xb9,0xbd,0x33,0xb5,0x8c,0xc1,0xcc,0xea,0xe, + 0x4d,0x8,0xdf,0x19,0xaf,0x16,0xf0,0x83,0x57,0x66,0xe9,0x9d,0x6b,0xd3,0x34,0x27, + 0x12,0xd3,0xe4,0x41,0x9,0x0,0x7b,0x47,0xa7,0xf8,0xe2,0xe9,0x16,0xde,0xbf,0xb3, + 0x86,0xdb,0x4b,0x7b,0xe,0xc1,0x89,0x4d,0x9e,0xc,0xea,0xeb,0x49,0xfc,0x32,0xd5, + 0x8b,0xa3,0xa1,0x69,0x88,0xd6,0x2f,0x39,0xda,0x47,0x3,0x6e,0xd2,0x8a,0x5e,0xca, + 0xcf,0xbb,0x5c,0xc8,0xa2,0x56,0xce,0x61,0xeb,0xf0,0x54,0xf8,0x11,0x3b,0x7d,0xcc, + 0x64,0xb5,0x84,0x3f,0x7b,0x73,0x1e,0x7f,0x70,0x7d,0x1a,0x67,0xc7,0x2b,0x5e,0xce, + 0x76,0x14,0xb9,0xd8,0x6f,0xb4,0xf1,0xf,0x9f,0x3d,0xc7,0xdf,0x7d,0xba,0x88,0xcd, + 0xfd,0x86,0x7f,0xf0,0x70,0xdc,0x34,0xc1,0x39,0x80,0xd1,0x37,0x4f,0xe7,0x3a,0xca, + 0x4c,0x64,0xa,0x90,0x48,0xc7,0xb6,0xcc,0x3a,0x6d,0xfd,0x69,0x49,0xd0,0x6,0x93, + 0x71,0x1e,0xe8,0xc2,0x26,0x41,0x53,0x63,0x94,0x21,0xc4,0xbb,0xcd,0x18,0x39,0x8d, + 0xab,0x5,0xf1,0x42,0x5f,0x4,0x57,0xe0,0xed,0xb7,0x37,0xb7,0x9f,0xc5,0xe6,0xe1, + 0x5,0xa8,0x7a,0x2f,0xba,0xd2,0xc6,0xe7,0x4c,0x32,0x41,0x83,0x35,0xef,0x21,0x8b, + 0xab,0x33,0x35,0xbc,0x7a,0x76,0x14,0xd7,0xcf,0xc,0x63,0x66,0x64,0x0,0xe5,0x7c, + 0x6,0xc5,0xdc,0x37,0xc3,0xeb,0xd1,0x62,0xde,0xeb,0x5,0x78,0xbc,0x71,0x88,0xf7, + 0xee,0xac,0xf1,0x7,0xf7,0xd6,0xb0,0x79,0xd0,0xe0,0xe3,0xd3,0x8e,0xf6,0x5d,0x4f, + 0xda,0xd7,0x24,0x48,0xed,0xec,0x11,0x0,0x2f,0x2f,0xdc,0x19,0xf8,0x90,0x88,0xe0, + 0xe,0x7f,0xa4,0x52,0x2e,0x83,0xf3,0x93,0xd5,0x44,0xb2,0x9e,0x9,0xda,0x69,0xb4, + 0x3a,0x58,0xdd,0x6b,0x60,0xe3,0xa0,0xe1,0x9b,0x58,0xca,0xbc,0x67,0xf6,0x80,0x1d, + 0xd4,0xca,0x79,0x2c,0x4c,0xc,0xe2,0xfc,0x44,0x5,0x67,0xc7,0x6,0x71,0x6e,0xa2, + 0x82,0x6a,0x29,0x87,0x62,0x2e,0x8d,0x4c,0x5a,0x21,0x9b,0x4e,0x21,0x9f,0x49,0xf5, + 0x85,0x6f,0xfb,0x35,0xb4,0x51,0x2f,0x9,0x66,0x46,0xbd,0xd9,0xc1,0x9d,0xe7,0xbb, + 0xfc,0xfe,0xdd,0x55,0x3c,0x58,0x3d,0xe0,0xcd,0x83,0x26,0xd7,0x1b,0x6d,0xf4,0x58, + 0xeb,0xe4,0x2c,0x43,0x4b,0xd9,0x9,0xdb,0xa4,0xa3,0xd9,0xdd,0xb7,0x2d,0xdc,0xe1, + 0xa8,0xc7,0x60,0xe,0xf4,0x2e,0x43,0x53,0xe4,0x64,0xf4,0x88,0xdd,0xb9,0x7b,0xd6, + 0xbe,0xee,0xd9,0x92,0x7d,0xb0,0xcf,0xf8,0x24,0xb9,0x8e,0x62,0x2f,0xe8,0x83,0x10, + 0x1a,0xb6,0x4c,0xd6,0x8a,0x9e,0x1f,0x45,0xd2,0xb5,0x69,0xb4,0xba,0xb8,0xb3,0xb4, + 0x8b,0xa5,0xdd,0x23,0xb6,0x2e,0x88,0xc,0x9b,0x40,0x2f,0xa9,0x20,0x2e,0x85,0xde, + 0x1f,0x48,0x54,0x44,0xf9,0x20,0x58,0xf1,0xf6,0x3b,0x3f,0xdd,0x38,0xe2,0xc3,0xc6, + 0x33,0xdc,0x59,0x3a,0xc0,0x7f,0xf3,0xd6,0x2,0x7d,0xeb,0xfc,0x28,0x8a,0xf9,0x6c, + 0xcc,0x78,0x26,0xda,0x78,0x8c,0xe,0xe6,0xf1,0xdf,0x7d,0xff,0x22,0x4d,0xf,0x95, + 0xf0,0xff,0x7e,0xbc,0xc8,0x8f,0xd7,0xf,0xa8,0xdd,0xd,0x98,0x24,0xcc,0xe0,0x8, + 0xa6,0xc4,0x76,0x7f,0xcd,0x0,0xa5,0x8,0x1c,0x98,0xbd,0x1b,0x1,0x50,0x9c,0xa2, + 0x80,0x82,0xc0,0xc4,0x59,0x6a,0xb7,0x19,0xfd,0x77,0x8,0x2,0x2,0x11,0xa5,0xf4, + 0xa3,0xc9,0xca,0x23,0x7c,0x22,0x20,0x30,0x5,0x20,0x22,0x8d,0xd,0xea,0xfc,0x75, + 0x8d,0xbb,0xb0,0x8a,0x21,0xe2,0xa2,0x74,0x73,0x2,0x22,0x49,0x31,0x53,0x65,0xdf, + 0xda,0x5d,0x6,0x77,0x99,0x73,0x5f,0x5e,0x9f,0x8,0x1f,0x81,0x10,0x63,0xe1,0xdb, + 0x41,0x53,0xab,0xa4,0xd2,0x24,0x27,0xf4,0xc8,0xf,0xa9,0x38,0x61,0x2f,0x90,0x50, + 0xa0,0xa2,0x3d,0x89,0xf,0x3c,0x8,0x69,0xe,0x9,0xd1,0x29,0xc9,0x5d,0xbc,0xb2, + 0xb8,0x92,0x11,0x95,0xfa,0xbc,0x60,0x63,0xee,0xa1,0x5c,0x2,0x9b,0x25,0xc7,0x39, + 0x5b,0x29,0xcb,0x81,0x67,0x45,0xc,0x50,0x29,0x9f,0xa6,0x9b,0xb,0x63,0xea,0x47, + 0x37,0x67,0xe9,0xfc,0x44,0x85,0xa2,0x10,0x9c,0x3c,0x28,0x9f,0x6e,0x1c,0xe0,0xe7, + 0xb7,0x56,0x70,0x77,0x65,0x4f,0xd8,0xdc,0xc2,0x4f,0xc9,0x82,0x14,0x23,0xc6,0xd6, + 0x81,0x9e,0x7d,0x26,0x43,0x38,0x72,0x81,0x90,0xcb,0xa4,0x30,0x3d,0x5c,0xc4,0xdc, + 0xd8,0x20,0x4a,0xd9,0x34,0x2,0x6d,0xcd,0xba,0xb2,0x7b,0x8c,0x7,0xab,0x7,0x9, + 0xbb,0x76,0xd7,0x7d,0xc9,0xef,0xa2,0x52,0xea,0x1b,0xad,0x3f,0x1,0xe0,0xc2,0x74, + 0xd,0xef,0x5c,0x99,0xc2,0xef,0x1f,0x6f,0x61,0x6d,0xf7,0xd8,0xde,0x6c,0xa5,0x7c, + 0x1a,0xf3,0xe3,0x83,0x78,0xeb,0xe2,0x78,0x58,0xcc,0x85,0x73,0x56,0x14,0xd6,0x65, + 0x66,0x3c,0xdb,0xac,0xe3,0x37,0x77,0xd7,0xf0,0xfe,0xdd,0x35,0xac,0xee,0x9d,0xc4, + 0xbf,0xa1,0x22,0x2f,0xf1,0xcc,0x73,0x6f,0x79,0x99,0xb7,0xf0,0x35,0xd7,0x23,0x6e, + 0x84,0x89,0x63,0xb5,0xfb,0x52,0x9a,0xcf,0x20,0x12,0xa5,0xda,0x46,0x65,0xb3,0x4b, + 0x33,0xb5,0xc4,0x4d,0x6d,0x43,0x41,0x2e,0x79,0xd,0x66,0x93,0xc3,0x62,0xd5,0x23, + 0x4a,0x7c,0xa8,0x81,0xb6,0x52,0xba,0x44,0x9b,0x73,0x99,0x8c,0xc7,0x7e,0x5e,0x20, + 0x32,0x2a,0x85,0x4a,0x31,0x8b,0xa1,0x81,0x5c,0x48,0xe2,0xaa,0x14,0x30,0x51,0x2d, + 0x62,0x61,0x3c,0x2c,0x5a,0xf3,0x63,0x65,0x64,0xd2,0x71,0xff,0xf3,0xe8,0xc1,0x67, + 0xa,0xb9,0x79,0x9d,0x3b,0xdd,0x1e,0x9e,0xef,0x1c,0xe3,0xd1,0xea,0x3e,0x7f,0xf5, + 0x7c,0xf,0x9f,0x3d,0xde,0xe2,0xa7,0x9b,0xf5,0x78,0xd9,0x26,0x5,0xb6,0xb0,0xa1, + 0x30,0x97,0xe2,0x88,0x84,0x82,0x5d,0x58,0x8d,0x29,0x2f,0x92,0xa3,0x23,0x88,0xb9, + 0xac,0x14,0x61,0xac,0x5a,0xa2,0xa1,0x81,0x9c,0x57,0x58,0xe5,0x24,0xdc,0xb,0x7a, + 0x58,0xdc,0x3e,0xc2,0xe3,0xf5,0x3,0x34,0x5a,0x3d,0xb7,0xb3,0x17,0xd7,0xaf,0x98, + 0x4d,0xa1,0x56,0xca,0xa3,0xa6,0xaf,0xcd,0x70,0x39,0x8f,0xb1,0xc1,0x2,0xa6,0x86, + 0x4a,0x98,0x19,0x2e,0x61,0x6a,0x68,0x0,0x13,0x3a,0x29,0x2c,0x89,0x5c,0x15,0xf5, + 0x59,0x57,0x4a,0xd9,0x9f,0x21,0x69,0x45,0x64,0x56,0x0,0xdb,0xf5,0x26,0x56,0x76, + 0x8e,0xf9,0xe9,0x46,0x1d,0xf7,0xd6,0xf6,0xf9,0xd6,0xb3,0x1d,0xde,0x3c,0x6c,0x4a, + 0x1f,0x61,0x1d,0xce,0x43,0x6,0x54,0x84,0xe,0x5,0xf2,0xa,0xb9,0xa9,0x24,0x7a, + 0x95,0x6b,0xe8,0xd0,0x4c,0x61,0x84,0x10,0xb3,0x17,0xc1,0xc9,0xae,0xbc,0xfb,0xa3, + 0x80,0xd6,0x47,0xbb,0xa6,0x52,0xac,0x2a,0x5d,0xb2,0xab,0x78,0xc0,0x5d,0xaa,0xb4, + 0x4b,0xcb,0xcb,0x67,0x53,0x38,0x3b,0x59,0xa1,0xb1,0x4a,0xe1,0x85,0x32,0xc6,0x46, + 0xab,0x8b,0x5b,0x4b,0x7b,0x58,0xdc,0x3e,0x71,0xeb,0x62,0x33,0xa5,0x5b,0xa6,0xb7, + 0x62,0x47,0xcc,0xf3,0x2c,0xfb,0xac,0x68,0xd1,0xcb,0x20,0x21,0x8f,0x85,0x3,0x6, + 0xa8,0xcb,0x8c,0xad,0xc3,0x53,0x1c,0x9d,0x6e,0x71,0x3e,0x93,0xc2,0xde,0x71,0xb, + 0xaf,0xcc,0xf,0xd3,0xcc,0x70,0x9,0x39,0x7d,0xbf,0x47,0xa5,0xc1,0x44,0x84,0x54, + 0x4a,0x61,0xb8,0x9c,0xc7,0x5b,0x97,0x26,0xa8,0x13,0x30,0xde,0xff,0x3a,0xc3,0x5f, + 0x2f,0xef,0xd1,0xc9,0x69,0x2f,0x6c,0x95,0xec,0x18,0x4b,0x22,0x39,0x4f,0x93,0x14, + 0x41,0x6,0xed,0x20,0x50,0xa0,0x48,0xbb,0xd0,0xe8,0x74,0xcd,0x0,0xc,0xa,0x2, + 0x3b,0x22,0x42,0x27,0xe4,0x58,0xf,0x8a,0xc0,0x28,0x64,0x4d,0x7e,0x1a,0x59,0xeb, + 0x67,0x3d,0x3c,0x28,0x27,0xc4,0x62,0x31,0x4b,0x3b,0x43,0x55,0xe1,0xb5,0x26,0x7, + 0x45,0x80,0xa8,0xcf,0x90,0xe7,0xad,0x24,0x65,0xdb,0xeb,0x46,0x72,0x8a,0xc6,0x10, + 0x26,0x94,0x70,0xbf,0xee,0x3a,0x24,0x2a,0x2d,0xc9,0x33,0x3e,0xa9,0xc7,0x6f,0xdf, + 0xfa,0xd4,0x7c,0x1f,0x1b,0x48,0xd8,0x30,0x47,0x25,0x3f,0x96,0x29,0xae,0x9c,0x56, + 0xc8,0x14,0x70,0x9b,0xb5,0xe6,0xf8,0x70,0x5e,0x8e,0x1a,0x83,0xac,0x3c,0xd3,0xe8, + 0xdb,0xb5,0x9c,0x21,0x34,0x1b,0x70,0xe9,0x59,0x94,0xcf,0xa6,0xe9,0xe6,0xc2,0x28, + 0xbd,0x73,0x75,0x8a,0x5e,0x3b,0x3b,0xe6,0x85,0x30,0x48,0x78,0xae,0x17,0x4,0xd8, + 0x3b,0x6a,0xe1,0xab,0xe7,0xbb,0xf8,0xf5,0xed,0x55,0xb4,0xbb,0x81,0x85,0x99,0x5c, + 0x9c,0x24,0x7c,0xc9,0x17,0x39,0x12,0x18,0x4b,0x25,0x71,0x94,0x50,0xa8,0xaf,0x44, + 0x26,0xad,0x70,0x76,0x62,0x10,0x3f,0x78,0x65,0x6,0xff,0xea,0xf5,0x33,0x98,0x1c, + 0x1a,0x40,0xaf,0x17,0x60,0xbb,0xde,0xc4,0xdf,0x7d,0xba,0x88,0xc7,0xeb,0x75,0x74, + 0x83,0xa8,0x80,0x84,0x23,0x5,0x92,0xc5,0x83,0x4d,0x2f,0x4c,0x58,0x63,0x66,0xdc, + 0x98,0x1b,0x42,0x21,0x9b,0x42,0xb7,0x17,0x9e,0x34,0x7b,0x47,0x4d,0x64,0xd2,0xa, + 0x97,0xa6,0xaa,0xf8,0xb7,0x6f,0x9f,0xc7,0x1b,0xe7,0xc7,0x30,0x34,0x90,0x17,0xc3, + 0xb6,0x8f,0x5c,0xf4,0x82,0x0,0xfb,0xc7,0x2d,0x7c,0xf8,0x70,0x3,0xff,0xc7,0xaf, + 0xef,0x63,0xf7,0xa8,0xe5,0xd9,0x3d,0x44,0x77,0xff,0xd2,0x94,0x44,0xea,0xd1,0x5f, + 0x62,0x83,0xee,0xb1,0xc6,0x49,0x3a,0x30,0x5a,0x87,0x2d,0xb2,0x54,0x17,0x52,0x5e, + 0xfd,0x25,0xe1,0x9d,0x6f,0xa1,0x48,0x8e,0xe8,0xc2,0xed,0xde,0x52,0x2e,0x93,0xc9, + 0x3f,0x68,0x25,0x80,0xcf,0x3a,0xbd,0xcb,0xf3,0x36,0x26,0xdf,0x54,0x59,0x66,0xc0, + 0x19,0xff,0x81,0x5c,0x3a,0x85,0x89,0x5a,0x11,0x17,0xa7,0xaa,0xb8,0x32,0x5b,0xc3, + 0xb5,0xd9,0x1a,0xe6,0xc6,0x6,0x31,0xa4,0xbd,0xec,0xfb,0xed,0x14,0x93,0xe0,0x6b, + 0x39,0xc9,0xb4,0xda,0x1d,0x2c,0xef,0x9e,0xe0,0x6f,0x3f,0x5e,0xe4,0xf,0x1f,0x6c, + 0xf0,0x62,0xb8,0x6f,0xb4,0x30,0xa4,0x1c,0xb6,0x6d,0x43,0xe2,0xfd,0xf8,0xcc,0x88, + 0x22,0xb7,0x14,0x23,0x69,0xb2,0x80,0xc9,0x6c,0x45,0x57,0x4,0xcc,0xc,0xf,0xd0, + 0xec,0xc8,0x80,0x87,0xe2,0x44,0x21,0xed,0x6e,0x8f,0x71,0x7f,0xf5,0x0,0xf,0xd6, + 0xe,0x5,0x69,0x31,0x7c,0x6d,0x53,0x14,0x92,0xea,0xe6,0xc7,0x7,0x71,0x65,0xba, + 0x8a,0x4b,0xd3,0x55,0x5c,0x98,0xa8,0x60,0x6e,0xac,0x8c,0x42,0xc4,0x20,0xa9,0x9f, + 0x14,0xb3,0x9f,0x52,0x42,0xda,0xf,0x47,0x77,0xc7,0x27,0xa7,0x5d,0x3c,0xdd,0x3a, + 0xc2,0x47,0xf,0xd6,0xf9,0x83,0xfb,0x9b,0xfc,0x74,0xa3,0xce,0xcd,0x76,0xd7,0x3c, + 0xb5,0x66,0x44,0xd,0x6f,0x69,0x4d,0x93,0x34,0x39,0x0,0x9a,0x4d,0xa5,0x73,0xb6, + 0x8d,0xc2,0x4b,0x85,0x25,0x5a,0x4c,0xe7,0x61,0xb5,0x51,0xc,0x32,0xf,0xb0,0xa3, + 0x2d,0x90,0xe3,0xb,0x1b,0x26,0x39,0xb9,0xdf,0xcf,0xdd,0x4c,0xb6,0x66,0x29,0x67, + 0xef,0x21,0x8d,0xc1,0x59,0xaf,0x43,0x58,0x8c,0x69,0x85,0x5c,0x1a,0xe7,0x27,0x6, + 0x31,0x5e,0x29,0x50,0xd4,0xa3,0x40,0x5e,0xc3,0xe3,0x56,0x17,0x77,0x9f,0xef,0xf3, + 0xca,0xce,0x89,0x21,0xf2,0xc5,0xf2,0x7,0xc4,0xb2,0x96,0xa3,0x1c,0x12,0x2f,0x3c, + 0x84,0x23,0xbc,0x2e,0x77,0x3c,0xd9,0xc3,0xb1,0xd9,0xe,0xe8,0x17,0xb7,0x57,0xf9, + 0xfe,0xea,0x3e,0xfe,0xe2,0xcd,0x5,0xbc,0x73,0x65,0x82,0x2e,0x4d,0xf7,0x77,0x9b, + 0x34,0x1f,0x9b,0x1e,0x2a,0xe1,0x5f,0x7f,0x7b,0x81,0x34,0x54,0xcf,0x5f,0x3e,0xdb, + 0xc1,0x69,0x47,0x37,0xf0,0x36,0xc5,0x41,0x1a,0x48,0x2a,0x45,0x1,0x7,0x20,0x5, + 0xa6,0x80,0xcc,0x1a,0x8d,0xc0,0x8a,0x3,0xa,0xc2,0x71,0xdb,0xd4,0xe,0x56,0x8, + 0x38,0xb0,0x26,0x34,0x8a,0x81,0x40,0x53,0x3,0xd,0x2a,0x1e,0xa4,0x40,0x29,0x6, + 0x7,0x30,0x69,0x2f,0x1a,0x37,0xd4,0x2e,0xb3,0x91,0xc6,0x9e,0x92,0x6,0x3a,0x24, + 0xd4,0x61,0x39,0xc,0x82,0x22,0xff,0x8f,0x8,0x6a,0xa6,0x10,0x4d,0x8d,0x93,0xf5, + 0x25,0x9a,0xb9,0x1e,0xd,0x66,0xe1,0xd0,0x29,0xce,0x11,0x31,0x8,0xe8,0x13,0x4a, + 0xd5,0xcf,0x6f,0x3c,0x5a,0xde,0x9,0xb1,0xbd,0x63,0x84,0x68,0x44,0x72,0x51,0xae, + 0xdf,0x65,0x81,0xa0,0xb3,0x9d,0xcf,0xc9,0x4e,0xf4,0x86,0x55,0xa4,0x48,0xda,0xc0, + 0x6a,0x16,0x9d,0x8d,0xa4,0x35,0x85,0x3d,0xfc,0xea,0xe3,0xd5,0x2,0xfe,0xf8,0xf5, + 0x33,0xea,0xed,0x4b,0x93,0x14,0x3d,0x4c,0xe5,0x61,0x71,0x72,0xda,0xc5,0x2f,0xef, + 0xac,0xe0,0xa3,0x7,0x9b,0x68,0x77,0xd9,0xbb,0x4b,0x1d,0xfc,0x25,0x63,0x61,0xa3, + 0xf,0x64,0xc2,0xb1,0xa8,0xdf,0xcd,0x66,0xd2,0xb8,0x34,0x55,0xc5,0xcd,0x85,0x61, + 0xdc,0x9c,0x1f,0xc1,0xc5,0xa9,0x1a,0x26,0x87,0x6,0xf4,0xe1,0x44,0x18,0xaf,0x16, + 0x8d,0x8e,0x93,0x65,0x90,0xbd,0xdf,0x46,0x79,0x18,0x25,0x5,0xdf,0xa0,0xab,0x35, + 0xbf,0x63,0x29,0x9f,0xc5,0xb9,0x89,0x2a,0xfe,0xcd,0x77,0xcf,0xe1,0xfb,0xd7,0xa7, + 0xd0,0x6c,0xf7,0x90,0x52,0x84,0x6a,0x29,0x87,0xf3,0x93,0x15,0xc,0x8b,0xa0,0x8f, + 0xa4,0xc9,0x7c,0x75,0xf7,0x4,0x7f,0xff,0xe9,0x12,0x7e,0x7b,0x7f,0xd,0xbb,0x27, + 0xed,0x30,0xc4,0xf6,0xb7,0x50,0x27,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x20, + 0xf2,0xbc,0xc7,0x46,0x71,0x4b,0x68,0x48,0x6e,0xfd,0xfa,0x4d,0xe8,0x24,0xcd,0x14, + 0xfc,0xdf,0xc6,0xa7,0x9e,0x98,0x24,0xcc,0xd0,0x6d,0x49,0xe,0xd0,0x22,0x5a,0x92, + 0xbd,0x70,0x6,0x19,0x38,0x43,0x71,0x46,0x22,0xc9,0xfd,0x16,0x3c,0xf7,0x5e,0xb9, + 0xcb,0x57,0x96,0x34,0x41,0x62,0xc7,0x39,0x51,0x2d,0xd2,0x44,0xad,0x84,0xc9,0x6a, + 0xb8,0xc7,0x1c,0xad,0x16,0x30,0x5a,0x2e,0x60,0x68,0x20,0x87,0x4a,0x29,0x8b,0xe1, + 0x81,0x7c,0x62,0xb6,0xb4,0xbc,0xee,0x51,0x39,0x9a,0x84,0x8a,0x83,0x80,0x71,0x77, + 0x65,0xf,0xb7,0x16,0x77,0xf8,0xf3,0x67,0x3b,0x78,0xbc,0x76,0xc8,0x5b,0x87,0xd, + 0x83,0x3,0x8b,0x20,0x19,0x17,0x10,0xe2,0x6c,0x3c,0x5,0x52,0x66,0x12,0x26,0x7c, + 0x35,0x10,0x62,0x3e,0x52,0x82,0xac,0x6b,0xf6,0x19,0x8a,0x14,0x26,0x6b,0x45,0x4c, + 0xd,0x95,0xb4,0x9a,0x97,0x13,0xc9,0x70,0xed,0x6e,0x80,0x2f,0x9f,0xed,0xe0,0xce, + 0xf3,0x3d,0x14,0x73,0x59,0xd4,0x4a,0x39,0x4c,0xd6,0xc2,0xe9,0x7b,0xbc,0x52,0xc4, + 0x64,0xad,0x80,0xa1,0x81,0x3c,0x2a,0xa5,0x2c,0x86,0x6,0xf2,0x18,0x2c,0x64,0xbc, + 0x58,0xdd,0xe8,0xb3,0x19,0x8d,0x2c,0x7d,0x91,0xc6,0x59,0x16,0x88,0x76,0xa7,0x87, + 0xc5,0xed,0x3a,0x1e,0xac,0x1e,0xf0,0xa3,0xf5,0x43,0x3c,0xdf,0x3e,0xe2,0x95,0x9d, + 0x13,0x6c,0x1e,0x36,0xf8,0xb4,0x1d,0xc0,0x52,0xdb,0x4c,0xe,0xb6,0xc9,0x2e,0xd3, + 0x1,0x3f,0x7a,0xcd,0xca,0x96,0x13,0x17,0x52,0x33,0x35,0x83,0x9d,0xd9,0xc9,0xd2, + 0xc0,0x7a,0xe1,0xa4,0xb,0xbb,0x32,0xbe,0xa2,0x6,0x8d,0x66,0x79,0x75,0x49,0x46, + 0x6f,0x4a,0x2a,0xb1,0x54,0xfa,0x32,0xc9,0x84,0x54,0x1b,0xfb,0xe7,0xb6,0xb0,0x6e, + 0x13,0x98,0x4b,0xa7,0x71,0x61,0xaa,0x86,0x89,0x5a,0x29,0xf1,0x2c,0x30,0xd7,0x6f, + 0xeb,0xb0,0x81,0xa5,0xbd,0x13,0x34,0x3a,0x3d,0x67,0x20,0x43,0xec,0x8a,0xb7,0x72, + 0x85,0xdc,0xba,0x3b,0xf9,0x36,0x1,0x3e,0xfb,0x9a,0xe3,0x7e,0x63,0x62,0xcd,0x69, + 0xbf,0xf2,0xfa,0x41,0x93,0x7e,0xf6,0xe5,0x12,0xaf,0xec,0x9d,0xe0,0xcd,0xf3,0x23, + 0x78,0xeb,0xc2,0x38,0xd,0x97,0xf3,0xb1,0xfb,0x5f,0x36,0x66,0xd9,0x4c,0xa,0xdf, + 0xbb,0x32,0x45,0xe5,0x7c,0xe,0x3,0xf9,0x34,0xbe,0x78,0xb6,0xc7,0xbb,0x47,0x4d, + 0xf8,0xc6,0xbe,0x76,0x6d,0x11,0x2a,0x99,0x98,0x34,0xe4,0xe,0x67,0x2d,0x18,0x6, + 0xd9,0x90,0x26,0xcc,0x2b,0xe,0x60,0xc8,0x16,0xc4,0xca,0x19,0xf2,0x85,0xdb,0x36, + 0xd,0xfe,0x91,0xb0,0x92,0x37,0x1b,0xb6,0x80,0x98,0x28,0x70,0xd7,0x40,0xfe,0x0, + 0x8a,0xa2,0x97,0x2a,0xb9,0xa2,0xb,0xcd,0x3b,0xc5,0x60,0x78,0x6f,0xb1,0xe1,0x6a, + 0xb,0x4b,0x1d,0x23,0x47,0x34,0x54,0x2a,0xe1,0x10,0x73,0x5f,0x2d,0x6d,0x49,0x6e, + 0x94,0x44,0x8f,0x97,0xf2,0x26,0x7,0xce,0xf9,0x12,0x21,0x82,0x67,0x5f,0x2a,0x64, + 0x70,0x96,0x94,0xc4,0x32,0x52,0xd4,0xb4,0x37,0x29,0x92,0x6c,0x61,0x48,0xd2,0x80, + 0x67,0xe7,0xa,0xb7,0x8f,0x95,0x52,0x14,0xc1,0x1e,0xf3,0xe2,0x2e,0x9,0x18,0x2c, + 0x66,0xe9,0xfc,0x64,0x8d,0xde,0x38,0x37,0x46,0xa3,0x95,0x42,0xdf,0x5d,0x9b,0x49, + 0x24,0xfb,0xec,0xf1,0x36,0xee,0xad,0xec,0xdb,0x93,0xdd,0xda,0x12,0x68,0x66,0xb8, + 0x95,0x6c,0x98,0xa2,0xce,0x91,0xfc,0x10,0xeb,0x72,0x40,0xc8,0x64,0x8,0xf9,0x4c, + 0xa,0x95,0x52,0x1e,0x33,0xb5,0x22,0xbe,0x7d,0x69,0x2,0x6f,0x5d,0x18,0xc3,0xa5, + 0xe9,0x9a,0x77,0x0,0x1d,0x37,0xdb,0xd8,0xaa,0x9f,0x62,0x75,0xf7,0x24,0xe2,0xfd, + 0xe8,0xed,0xd8,0x20,0x8d,0xfb,0x15,0x88,0x5b,0x9d,0x80,0x7a,0x41,0x60,0x63,0x2b, + 0xfb,0xd9,0x3c,0x32,0x33,0x6,0xf2,0x69,0xdc,0x98,0x1f,0x79,0x61,0x88,0x46,0x74, + 0xf2,0x69,0x77,0xba,0x58,0xd9,0x6b,0xe0,0xe3,0x47,0x9b,0xf8,0xc7,0xaf,0x96,0xb0, + 0xb2,0x7b,0xcc,0x88,0xca,0xae,0x88,0x23,0xc1,0xb9,0x92,0x94,0x6b,0xd6,0xcd,0xca, + 0x53,0x49,0x24,0x65,0x4a,0x7b,0x5a,0x4a,0x8f,0x74,0x3,0x88,0x2e,0x87,0x3d,0xe5, + 0x0,0x31,0x11,0x87,0x5a,0x5d,0x37,0x6c,0x38,0xc1,0xba,0x89,0xd9,0x72,0xd1,0x8a, + 0x42,0xfb,0x1f,0xf9,0xf6,0x1e,0xf7,0xc7,0x9b,0xe6,0x1,0xa5,0x14,0xa5,0x15,0x21, + 0xad,0x42,0x58,0x30,0x93,0x4a,0x85,0x2c,0xd2,0xb4,0x42,0x3e,0xad,0x30,0x32,0x98, + 0xa7,0x99,0x91,0x32,0xe6,0x47,0x7,0x30,0xaf,0x77,0xbf,0xe3,0x95,0x82,0x4d,0xf0, + 0x8a,0x92,0xda,0xa2,0x70,0x70,0x94,0xbc,0x24,0xff,0x7c,0xda,0xee,0xa2,0xd9,0xee, + 0xe1,0xd9,0x56,0x1d,0xbf,0x7f,0xb4,0xc5,0xef,0x7f,0xbd,0xc6,0x8f,0x36,0xea,0x76, + 0xef,0xa9,0x8d,0x78,0x3c,0xb3,0x54,0x97,0x65,0x22,0x9e,0x53,0xfb,0x35,0x35,0x96, + 0x21,0xed,0xe,0x3c,0x12,0xad,0xd0,0x4a,0xd9,0x70,0xce,0xf0,0x55,0x4c,0xa5,0x8, + 0x93,0x43,0x25,0x4c,0xd6,0x1c,0xb,0x3f,0xa9,0x80,0x74,0x3,0xe,0xf7,0xba,0x43, + 0x25,0x2c,0x8c,0xd,0x62,0x66,0xa4,0x84,0x33,0x23,0x3,0x58,0x18,0x2b,0x63,0x6e, + 0xb4,0xec,0x19,0x9f,0x44,0x77,0xdb,0x49,0xc,0xfe,0xe8,0x34,0x2e,0xf3,0xbc,0xa3, + 0x7b,0xd8,0xd3,0x76,0x17,0xa7,0x9d,0x1e,0x1a,0xad,0x2e,0x96,0x77,0x8e,0xf8,0xeb, + 0xa5,0x7d,0x7c,0xf4,0x68,0x93,0xef,0xaf,0x1e,0x72,0xa3,0xd5,0x91,0x40,0x68,0x38, + 0x7e,0xb9,0xfb,0xcd,0xfc,0x8f,0xa1,0xc4,0x15,0x35,0x96,0x84,0xac,0x9d,0xc1,0x9d, + 0x7f,0x7c,0xa0,0xbf,0x8e,0x65,0xbb,0x87,0x65,0x81,0x59,0x6b,0x27,0xd9,0x68,0x3, + 0x1d,0xdf,0xcd,0xb,0xb,0xf5,0x21,0x26,0xc1,0x6b,0x67,0x87,0x0,0xd9,0x30,0x4a, + 0x23,0xc0,0x17,0xb6,0xd9,0xf6,0x3e,0x2f,0x17,0xb3,0x98,0x1d,0x19,0xb0,0x45,0x32, + 0xfa,0x8c,0x5,0x41,0x18,0x9d,0xbb,0xbc,0x7d,0xc2,0xfb,0x27,0x2d,0x7b,0x86,0x86, + 0x3d,0x7,0x59,0x83,0x40,0xe7,0xa4,0xa2,0xc3,0xe5,0x2d,0xf3,0xda,0x86,0x6d,0xf8, + 0xc2,0x4b,0x8f,0x90,0x4d,0x2e,0xd2,0x8e,0x94,0x26,0x86,0x86,0x97,0x2a,0x60,0xf0, + 0xe2,0xd6,0x31,0xb6,0xeb,0x2d,0x6c,0xd7,0x4f,0x91,0x52,0xa,0xdf,0x3a,0x37,0x46, + 0xe5,0x42,0x1a,0x99,0x74,0x2a,0x76,0x66,0x99,0x67,0x64,0x68,0x20,0x87,0xb7,0x2f, + 0x8d,0x51,0xc0,0x8c,0x94,0x4a,0xe1,0xc3,0x87,0x9b,0xa8,0x37,0x3b,0x8e,0x3b,0x13, + 0x93,0x57,0x11,0x14,0x93,0x62,0xe2,0x30,0xad,0x29,0xa0,0x20,0xdc,0x9a,0xa4,0x94, + 0x7e,0x6d,0x3,0x4a,0x11,0x71,0xa0,0x3d,0x7b,0x18,0x4a,0x6b,0xd4,0xc8,0x48,0x5e, + 0xc1,0x60,0xa4,0x40,0x8,0x44,0x5c,0x33,0x9c,0xed,0x24,0xf9,0x44,0x2,0x4d,0x8f, + 0x11,0xf2,0xda,0x58,0xe2,0x91,0x7,0x55,0xfa,0xc8,0xad,0xf8,0x7c,0x1b,0xbb,0x4c, + 0xf1,0x25,0xb5,0xc7,0xd5,0x11,0x86,0x65,0xac,0xfd,0x2e,0x38,0xc9,0xca,0x19,0xac, + 0x9d,0xe2,0x1c,0x9b,0x8,0x32,0xbc,0xcf,0x4b,0x9d,0x88,0xe5,0x28,0x5b,0x4b,0x1c, + 0x13,0x76,0x11,0xc5,0xfc,0xcd,0x36,0x2a,0x14,0xdd,0x4b,0x46,0x80,0xc4,0xd9,0xe5, + 0x6e,0xd3,0x1c,0x4c,0x32,0x93,0xc5,0x16,0x78,0x67,0x31,0x63,0xba,0x2c,0xf7,0xef, + 0x85,0xbe,0x8d,0x40,0x57,0x66,0x87,0xe8,0x9d,0x2b,0x93,0x4a,0xa6,0x53,0xf5,0x9b, + 0x6a,0xbb,0x1,0x63,0xf3,0xb0,0x89,0xd3,0x4e,0x20,0xe0,0x2f,0xc7,0x4,0x37,0x19, + 0x99,0x12,0xfe,0x20,0x22,0xab,0xe9,0x95,0x1e,0x27,0x85,0x6c,0xa,0xe7,0xc6,0x2b, + 0xb8,0x39,0x3f,0x8c,0x57,0xe6,0x86,0x71,0x71,0xaa,0x8a,0x6a,0x29,0x87,0x6c,0xc6, + 0x87,0x5,0x9b,0xad,0xe,0x1e,0xae,0x1f,0xe2,0xff,0xfe,0xe0,0x9,0x7f,0xfe,0x74, + 0x3b,0x54,0x5f,0x29,0x88,0x17,0x8a,0x62,0x49,0x9a,0xe6,0xbb,0xd5,0x9b,0x1d,0x6c, + 0x1c,0x34,0x31,0x36,0x98,0x47,0x36,0x93,0x4e,0x94,0xad,0x49,0x22,0x55,0x3f,0xbf, + 0xe5,0xa4,0xb7,0x6e,0xb7,0x87,0xf5,0x83,0x26,0xfe,0xe6,0xe3,0x67,0xf8,0xcf,0x5f, + 0x2e,0xf3,0xde,0xd1,0xa9,0x78,0x5d,0xfd,0x89,0xdb,0x35,0x36,0xd1,0x4,0x37,0xcb, + 0x55,0x13,0x5e,0x42,0xf4,0x82,0xd7,0x40,0x39,0x79,0x18,0x93,0x7d,0x50,0xe0,0x22, + 0x18,0xb4,0xf4,0x57,0x7b,0x64,0xbb,0x34,0x40,0x99,0xe8,0xc2,0xc2,0x91,0x89,0xec, + 0xf4,0x6a,0x24,0x80,0xde,0x31,0xc0,0xbe,0x98,0x3c,0xe1,0xb1,0x28,0x17,0xb2,0x54, + 0x1d,0x8,0xa7,0xcc,0xe1,0x72,0x1e,0x43,0xe5,0x3c,0x46,0xca,0x79,0x1a,0xe,0xff, + 0x8b,0x91,0xc1,0x1c,0x6,0xf2,0x19,0x64,0xd3,0x29,0x64,0x52,0xa,0xd9,0x8c,0x42, + 0x36,0xa5,0xbc,0xf5,0x45,0x3f,0x18,0x38,0x69,0x5a,0x97,0xd7,0xe6,0xb4,0xdd,0xc5, + 0xc3,0xf5,0x43,0xfc,0xe2,0xd6,0xa,0x7f,0xf5,0x6c,0x8f,0xd7,0xe,0x4f,0x70,0x74, + 0xd2,0x61,0x72,0x9d,0x12,0xbb,0x38,0x2f,0xab,0xca,0xf5,0x64,0x2e,0x46,0xd5,0xc3, + 0xc6,0x31,0xd7,0x76,0x61,0xce,0x2a,0x9d,0xac,0xe5,0x19,0x5b,0xc7,0x62,0x4b,0x0, + 0x74,0x0,0x2b,0xa5,0x34,0x92,0x34,0x5e,0x2d,0xf6,0x7d,0xd,0x7b,0xbd,0x0,0xb9, + 0x8c,0xc2,0xbf,0xff,0xfe,0x5,0x74,0x7b,0x8c,0x72,0x21,0x83,0xac,0x26,0xb4,0x65, + 0xd3,0xca,0x12,0x39,0x5f,0x44,0x60,0xfb,0x66,0xbb,0x2,0x8a,0x15,0x73,0xcb,0x7f, + 0xd9,0x3c,0xc2,0x97,0xcf,0x76,0xf8,0xb3,0xa7,0x3b,0xbc,0xbc,0x7b,0x8c,0xfd,0x93, + 0x16,0x37,0x4f,0xbb,0x38,0xed,0xf6,0xe0,0xd8,0x3,0xae,0x4a,0x89,0xf3,0x98,0xdd, + 0x83,0x1c,0x32,0xd8,0x11,0x84,0xd7,0x54,0x6b,0xc7,0x8d,0x9e,0x9c,0x8d,0x64,0x8d, + 0xad,0x1b,0x9,0x19,0xf2,0x9b,0x7d,0x9f,0xc9,0xd2,0xc1,0x19,0x1e,0x77,0xd2,0x99, + 0x5a,0x5a,0xca,0xb6,0xf9,0xa3,0x35,0xda,0x24,0xa7,0x8a,0x22,0x69,0x50,0x44,0x4e, + 0x61,0xad,0xbf,0x78,0x5a,0x29,0x8c,0x55,0xa,0xa8,0x8a,0x30,0xa9,0xe8,0x35,0xa, + 0x38,0xc0,0xd3,0xad,0x63,0xdc,0x5f,0x3f,0x40,0xaf,0x67,0xef,0xe,0x87,0x4c,0x18, + 0x87,0x62,0x16,0xd1,0xc3,0x76,0xda,0x56,0xd6,0xf,0xc2,0x86,0xa7,0x68,0xa7,0x74, + 0x8e,0x45,0x88,0x39,0xcf,0x6b,0x32,0x4,0x1,0xfd,0xc8,0x42,0x31,0x9d,0xb4,0x7a, + 0x7c,0x7b,0x69,0x8f,0x76,0x4f,0x5a,0x7c,0x7f,0xf5,0x10,0xff,0xe6,0x3b,0xb,0x34, + 0x3b,0x32,0x90,0xf8,0x5a,0x9a,0xdf,0x23,0x9f,0x4d,0xe3,0x7b,0x57,0x26,0xa8,0x5a, + 0xca,0xa2,0x32,0x90,0xa5,0x5f,0xdd,0x59,0xb,0xb6,0xeb,0xa7,0xd6,0x87,0x34,0x44, + 0x9,0x94,0x43,0xc6,0x4d,0xcb,0xca,0x3a,0x6c,0x95,0x10,0x12,0xd8,0xb5,0xc4,0x84, + 0x3,0x76,0xde,0x25,0xa6,0xa3,0x61,0xd2,0xd4,0x7,0x63,0xcd,0x67,0xfc,0xf7,0xa3, + 0xe4,0x36,0x72,0x9e,0xd2,0x81,0xb3,0xa2,0xb1,0x68,0xa1,0x34,0x68,0xf2,0xa8,0x3f, + 0x51,0xc2,0x9b,0x5f,0x4b,0x63,0x26,0x5f,0xec,0xf2,0x2c,0x98,0x1c,0x43,0x9e,0x3d, + 0x28,0x84,0x22,0xa9,0x83,0xe2,0xdb,0x1a,0x96,0x7b,0x2c,0x8e,0x8d,0x9c,0xe9,0x81, + 0xce,0x29,0x37,0x27,0x88,0xf8,0x66,0x32,0xf,0x5a,0x85,0x2f,0x74,0x8c,0xba,0xcd, + 0x76,0x17,0xc4,0x31,0x18,0xc2,0xfd,0x42,0x96,0x7c,0xac,0x19,0xc5,0x2c,0x27,0x19, + 0x57,0xcc,0xed,0x4d,0x2e,0x21,0x2c,0x3,0xdf,0xbb,0x40,0xa2,0xf0,0x2f,0xe7,0x46, + 0xcb,0xb8,0x3c,0x53,0x45,0x3e,0x9b,0xfa,0xc6,0x43,0x22,0xa5,0x8,0xa3,0xd5,0x2, + 0x32,0xeb,0x87,0xe8,0xf4,0xd8,0xc9,0x9,0x8c,0x19,0x87,0xd4,0x11,0xc2,0x1,0x11, + 0x29,0xa5,0x50,0xce,0x67,0x31,0x58,0xcc,0xa0,0x52,0xca,0x61,0xa4,0x9c,0xc3,0x54, + 0xb5,0x88,0x33,0xa3,0x65,0x9c,0x9f,0x1c,0xc4,0xc2,0xd8,0x20,0x2a,0xc2,0xbd,0x8a, + 0x99,0xd1,0xed,0xf6,0xb0,0xb6,0xdf,0xc0,0xdd,0x95,0x7d,0x7c,0xfc,0x68,0x93,0x3f, + 0x79,0xb4,0x89,0xc3,0x66,0xc7,0x1b,0x97,0x88,0x39,0x96,0x7e,0x25,0x21,0x9a,0xe7, + 0xdb,0x47,0x7c,0x6f,0x65,0x9f,0xaa,0x97,0x26,0x90,0xcd,0xc4,0x9d,0xc4,0xfa,0xc1, + 0x94,0x49,0x87,0xa3,0xfc,0x77,0x8d,0x56,0x1b,0x8f,0xd6,0xeb,0xf8,0xe0,0xde,0x6, + 0x7f,0x70,0x7f,0x3,0x3b,0xf5,0x53,0xc1,0x56,0x17,0xe1,0xdf,0x9e,0xb4,0x82,0x12, + 0xf2,0xbe,0xdd,0x8d,0xcc,0xc,0xee,0xf4,0x2,0xca,0xbf,0xc8,0xe8,0xc3,0x7c,0xdc, + 0xe4,0x9,0x4b,0x9c,0xcf,0x9a,0x6d,0xa9,0xd0,0x41,0x13,0x8a,0x95,0x54,0x50,0xb8, + 0x6,0x88,0x72,0x69,0x85,0xca,0x40,0xe,0x33,0x43,0x25,0xd4,0x6,0xb2,0xc8,0xa4, + 0x52,0x48,0xa5,0x74,0x5f,0xeb,0x28,0x74,0xc4,0x71,0x4f,0x6,0xaf,0xa8,0xe7,0xb2, + 0x69,0x94,0x73,0x19,0x94,0xb,0x69,0x94,0xb,0x59,0xaa,0x14,0xb3,0xa8,0x14,0xb3, + 0x28,0x17,0x32,0xa8,0x96,0x72,0x31,0xa8,0xb8,0x1f,0x1c,0x9c,0xd4,0x68,0xc9,0x49, + 0x34,0x7a,0x90,0xed,0x1f,0xb7,0xb0,0xba,0x7f,0x82,0x27,0xeb,0x47,0xfc,0xf5,0xca, + 0x1e,0x3e,0x7d,0xbc,0xcd,0x2b,0xbb,0xc7,0x2c,0x66,0x25,0xb9,0xac,0x64,0x31,0xa0, + 0xb0,0xd4,0xcc,0xda,0xde,0xcf,0xc8,0x2d,0xd9,0xb9,0xf6,0x39,0xd4,0x2e,0x54,0xfb, + 0x1a,0x43,0x45,0x99,0x56,0x4a,0xa6,0x8a,0xe9,0x9d,0x2a,0xa5,0x14,0xd5,0x4a,0x39, + 0x54,0x4b,0x59,0xa4,0xfa,0x98,0x19,0x81,0x80,0x6c,0x2a,0x85,0xb3,0xe3,0x83,0x89, + 0x5,0x37,0x9,0xa,0x7e,0xd1,0x3d,0x9a,0x14,0x96,0x22,0xef,0xd9,0xa3,0x66,0x7, + 0x5b,0xf5,0x26,0xb6,0xf,0x1a,0xbc,0xba,0xdf,0xc4,0x93,0xcd,0x3a,0x1e,0xae,0x1d, + 0xf2,0xa3,0xb5,0x43,0x6e,0x76,0xba,0x5a,0x4,0x6e,0x38,0x94,0x22,0x6,0xd1,0x86, + 0x90,0x84,0x44,0x36,0xf1,0x78,0xb1,0x55,0xeb,0x29,0x1d,0xcc,0xa5,0x93,0xd3,0xf4, + 0xb5,0x67,0xfd,0x85,0x98,0x8,0xcc,0x3a,0x59,0x53,0xb7,0x5,0x3a,0xbf,0x8b,0xd, + 0x4c,0xc4,0x2c,0xb4,0x46,0x86,0xe6,0x60,0x1f,0x13,0x6d,0xa8,0x61,0xd0,0x27,0x53, + 0xc2,0x35,0x4f,0x9b,0x9,0x8a,0x38,0xaa,0x6f,0xf5,0xe4,0x6c,0xe1,0x3a,0x71,0x6a, + 0x78,0x80,0xc,0xfb,0x3f,0x89,0x7b,0x40,0x20,0x3c,0xdb,0xaa,0xf3,0x83,0xb5,0x3a, + 0xba,0xc6,0x2f,0xdc,0xda,0x83,0xb1,0xb3,0xaa,0xf5,0x95,0xa2,0x6c,0x92,0x43,0xc9, + 0x63,0x6a,0x9b,0x4b,0x21,0xcf,0x40,0x16,0xe4,0x3e,0xa3,0xd5,0x13,0x6c,0x1a,0x23, + 0x8a,0x54,0x44,0x8d,0x4e,0xc0,0x8f,0x36,0x8e,0xd0,0xe9,0x31,0xb2,0x19,0x85,0x6f, + 0x9d,0x1b,0xa5,0x4b,0x53,0x61,0x2,0x5e,0x12,0xba,0x68,0x8a,0xfa,0xe5,0xe9,0x5a, + 0x48,0x3b,0x8,0x40,0x1f,0x3d,0xde,0xc2,0xca,0xee,0x89,0x8d,0x5c,0x23,0x72,0x5, + 0xd6,0xcc,0x76,0x36,0x29,0x15,0xa4,0x58,0x71,0xa0,0x99,0x10,0x9e,0x5,0x78,0xb8, + 0x6f,0xf,0xdd,0xe3,0x42,0x98,0x22,0x20,0x4b,0x82,0x64,0xcb,0x12,0x75,0x45,0x5e, + 0xbb,0xd7,0x69,0x8d,0xa5,0x7d,0x85,0xad,0x19,0x9d,0x12,0x55,0xd5,0x73,0xc3,0x72, + 0x53,0x34,0x4b,0xb3,0x2d,0xdf,0xa2,0x2,0xd1,0xd,0xa5,0x64,0xa3,0x5,0xe8,0xe3, + 0xe1,0xa0,0x8f,0xe2,0x0,0x22,0xd7,0x35,0xcc,0x12,0x40,0xda,0x32,0x27,0xe1,0x8b, + 0xde,0xa5,0xdd,0x80,0x1f,0xd5,0xa4,0xc7,0x49,0x25,0x2d,0x61,0x23,0xdb,0x4f,0x91, + 0xdc,0xce,0xc2,0x98,0x43,0x1a,0xbe,0x38,0x82,0x1b,0xbc,0x94,0xd4,0xb8,0xd5,0x93, + 0x73,0xac,0x12,0x9d,0x2d,0x4c,0xcc,0x24,0x79,0xdd,0x4e,0xf8,0x81,0xe1,0xc1,0x2, + 0xcd,0x8e,0x94,0x29,0xf3,0x2,0x8,0xcf,0xdc,0x40,0x85,0x6c,0x1a,0x6f,0x9c,0x1d, + 0x43,0xbd,0xd1,0xc1,0x97,0xcf,0x76,0x23,0xe6,0x31,0x31,0xfb,0x9e,0xd0,0x5e,0x8f, + 0x28,0x64,0x2e,0x8f,0x95,0xb1,0x30,0x5e,0xc6,0xd5,0x99,0x1a,0x2e,0xcf,0xd4,0x30, + 0x5a,0xce,0xdb,0xc3,0xde,0x64,0x2c,0xcb,0x1b,0x76,0x75,0xaf,0x81,0xdf,0xdc,0x5b, + 0xe3,0x9f,0x7f,0xb5,0x8a,0x3b,0xcb,0xfb,0x6c,0x7b,0xf6,0x48,0xd4,0x5e,0xd4,0xf6, + 0x5a,0x82,0x71,0x4f,0x36,0x8e,0xf0,0xfb,0x7,0x9b,0x7c,0x65,0xa6,0x46,0xa5,0x5c, + 0xfa,0xa5,0xdd,0xb0,0x5e,0x34,0x1d,0x9e,0xb6,0x3b,0x78,0xb4,0x5e,0xc7,0xcf,0x6f, + 0xad,0xf2,0x7f,0xfa,0x64,0x11,0x8d,0xff,0x8f,0xb6,0x37,0x6b,0xd2,0x34,0xbb,0xae, + 0xf3,0xf6,0x3e,0x99,0x55,0xd5,0xd5,0x33,0xd0,0x40,0x3,0x60,0x83,0xc4,0x40,0x91, + 0x30,0x68,0x99,0x83,0x69,0x9b,0x8e,0x10,0x15,0xe,0x85,0x15,0xa1,0x4b,0x5d,0xf8, + 0x4e,0x3f,0xc5,0xbf,0x47,0x17,0xe,0xdb,0x57,0xba,0x50,0x78,0x64,0xd0,0x41,0x8a, + 0x92,0x48,0x2,0xe0,0xd0,0x4,0xd0,0x18,0xba,0xd1,0xd5,0x43,0x55,0x57,0x65,0x4d, + 0x99,0x95,0x73,0x7e,0x67,0xf9,0xe2,0x9c,0xbd,0xf7,0xda,0xfb,0xbc,0x5f,0x83,0xa2, + 0xc3,0x8c,0x90,0x50,0xdd,0x5d,0x5d,0x9d,0xf9,0xe5,0xfb,0x9e,0xb3,0x87,0xb5,0x9e, + 0x75,0x79,0x3,0x49,0x59,0xde,0x2d,0x89,0x3,0x57,0x9c,0x2d,0xc3,0xec,0xe2,0xc5, + 0xef,0x1d,0x72,0x79,0xdd,0xe5,0xd5,0x97,0xf6,0x9,0xc1,0xec,0xb9,0x1f,0x9a,0x16, + 0x77,0x6,0x34,0x49,0xe3,0x29,0x42,0x7,0xcf,0x9e,0x12,0xbe,0xf,0xb4,0x2,0xe8, + 0xed,0x37,0x5f,0x96,0xdf,0xfb,0xd6,0x5b,0xfa,0xcf,0xfe,0xf1,0x3b,0xf2,0x9d,0x77, + 0xde,0xd4,0x97,0x6f,0x1f,0xc8,0xdd,0xdb,0x87,0x9b,0x59,0xec,0xbf,0xcc,0xf2,0xb7, + 0xaf,0x83,0xde,0x27,0xec,0xf9,0xfb,0x76,0x9b,0xfb,0xe8,0x7b,0xcf,0xce,0xae,0xe4, + 0xdd,0x7b,0x4f,0xf1,0x7f,0xff,0xed,0x27,0xf2,0x57,0xbf,0x78,0x8c,0x7,0x4f,0xcf, + 0x60,0x6,0xe7,0x30,0xea,0xf9,0x57,0xe0,0x63,0x6,0xf5,0x63,0x8c,0x7b,0x26,0xd0, + 0x76,0xcc,0xc6,0xbc,0x39,0x8,0x3d,0x7a,0x81,0x49,0x4,0x73,0x93,0xc8,0xf8,0x1b, + 0xad,0xa9,0xc2,0x5d,0x0,0x4d,0x5e,0xbe,0x73,0x28,0xaf,0xde,0x39,0x64,0xb9,0x70, + 0xfa,0xbf,0x83,0xd6,0xe4,0xa0,0xed,0x57,0x5a,0xff,0xa7,0xd2,0xdb,0xb6,0x52,0xd1, + 0x4c,0x53,0xf0,0xe4,0xf4,0x4a,0xde,0x7f,0xf0,0x1c,0xdf,0x7f,0xff,0x48,0xbe,0xf7, + 0xfe,0x11,0xde,0xfb,0xf4,0x39,0x2e,0x26,0x13,0xdc,0x33,0xd8,0x48,0x8c,0x36,0x90, + 0x9c,0xa0,0xcf,0x13,0x86,0x61,0x85,0x78,0xe2,0xba,0xa9,0xd7,0x1b,0x20,0x1d,0x33, + 0x9f,0xdd,0x85,0x6f,0xb0,0x7f,0x3e,0xc7,0xed,0xaa,0x7d,0x5e,0xe4,0x24,0x8c,0x6b, + 0x2a,0xf4,0xfb,0x22,0x8e,0x94,0x78,0xc4,0x73,0x92,0x3f,0x6c,0x3,0x14,0x42,0x3f, + 0x36,0xbd,0x12,0x49,0x56,0x8d,0x97,0x78,0x9,0x79,0x4,0x6d,0xaa,0x5f,0x7b,0xeb, + 0x55,0xfd,0xd5,0xb7,0xb2,0x48,0xb1,0xae,0x78,0x76,0x80,0xfc,0xe2,0xe8,0x85,0xbc, + 0xff,0xe8,0x4,0xd7,0x1d,0xc4,0x9b,0xcf,0x97,0xb9,0x68,0x1b,0xb4,0xbb,0x46,0x6f, + 0x1c,0xe5,0xec,0xc,0x77,0x31,0xdd,0xf8,0x94,0x39,0xc,0xd2,0xa3,0xfa,0x83,0xe9, + 0xc2,0xa,0x49,0x42,0x4c,0x55,0xd5,0xf,0x1f,0x9f,0xe2,0x5f,0xff,0xe9,0xcf,0xe5, + 0xde,0xe3,0x53,0xf9,0x1f,0xfe,0xe0,0x9b,0xfa,0x9b,0x93,0x2f,0xb0,0xef,0x8c,0x7e, + 0xf5,0xee,0x2d,0xf9,0xdd,0x6f,0xbe,0xa5,0x2f,0xbf,0x74,0x4b,0xbf,0xf0,0xda,0x4b, + 0xfd,0x7f,0xf9,0xf,0x1f,0xc8,0xd3,0xb3,0xcb,0x91,0x60,0x27,0xa2,0x21,0xea,0xa0, + 0x20,0x36,0xf8,0x18,0xdd,0x43,0x5b,0xfa,0x44,0x3b,0xcf,0x9f,0xaa,0x9a,0x17,0x71, + 0x9c,0x24,0x73,0x89,0x3e,0xbb,0x75,0x1f,0x67,0xcd,0x42,0x70,0xbc,0x4d,0x23,0xf9, + 0x49,0x4b,0x37,0x6d,0x9c,0x85,0x48,0x4e,0x6b,0x2b,0xe4,0xd3,0x6e,0xbd,0x94,0x2c, + 0xb7,0xc7,0xc2,0x46,0x67,0x67,0x8e,0xb3,0x95,0x5,0xe1,0xec,0x57,0x42,0x43,0x7c, + 0xd,0x4d,0x66,0x7c,0xaa,0xf2,0xbe,0xb1,0xf4,0x84,0x1a,0xfb,0x1e,0x8f,0x74,0x3, + 0xe5,0xe8,0x2a,0x69,0x2c,0xc8,0xcf,0x2a,0x69,0xcf,0x2e,0x91,0x9f,0xb4,0xac,0xc0, + 0x63,0x7a,0xce,0x30,0xe,0x27,0x19,0xf1,0x3,0xeb,0xff,0x72,0xf3,0x8b,0x3e,0xd6, + 0xac,0x73,0x37,0xa5,0x2a,0xaf,0xdd,0xbd,0x25,0x7c,0xd9,0xed,0x1b,0x77,0x8a,0x88, + 0xbc,0x74,0xeb,0x40,0xfe,0xf0,0xbb,0x5f,0x95,0xb7,0xdf,0xb8,0x2b,0xdf,0xf9,0x95, + 0x37,0xe5,0x83,0x87,0x27,0xf2,0xf8,0xe4,0x52,0xae,0x6f,0xba,0xdc,0x3a,0x6c,0xf2, + 0xfa,0xdd,0x5b,0xa3,0xb,0x7f,0xf9,0x8e,0xbc,0xfe,0xf2,0x6d,0x79,0xfd,0xee,0x6d, + 0x79,0xe3,0xe5,0x5b,0x62,0x9d,0xdb,0x1b,0xaf,0xdc,0x91,0x37,0x5f,0xb9,0x23,0x5f, + 0x7c,0xe5,0x76,0xba,0x3c,0xd8,0x12,0x77,0xef,0xd1,0x89,0xfc,0xf9,0xcf,0x1e,0xe1, + 0xaf,0x3f,0x7c,0x2c,0x3f,0x7f,0x70,0x2c,0x1f,0x3d,0x3a,0x99,0xdc,0x12,0x84,0x8a, + 0x3b,0x28,0x15,0x29,0xdd,0x6a,0xb2,0x54,0x8c,0xff,0x2c,0xf7,0x9f,0x9f,0xc9,0xdf, + 0x7c,0xfc,0x54,0xff,0xfa,0x17,0x8f,0x71,0xf7,0xd6,0x81,0xbe,0xf5,0xfa,0xdd,0x4, + 0xd9,0xf8,0xbc,0x3,0x73,0x4b,0xcc,0xf4,0xf8,0xe4,0x42,0xfe,0xea,0x83,0x23,0xfc, + 0xd1,0xbb,0x9f,0xca,0x5f,0xfd,0xe2,0x31,0xce,0xaf,0x6e,0xca,0x9f,0xa1,0xb2,0xf5, + 0x57,0x5a,0x5c,0xf4,0x1e,0x4f,0x4d,0x3f,0xd4,0xab,0x5d,0x97,0x27,0x2f,0x2e,0xe4, + 0xcd,0x57,0x6e,0xc9,0x1,0x59,0xb0,0xea,0xe,0xdb,0x9f,0x41,0x52,0x8e,0x7a,0x2c, + 0xa1,0x78,0xf1,0x19,0x13,0x7a,0xde,0x8f,0xcf,0xbf,0xf8,0xed,0x6f,0xbe,0xa5,0xff, + 0xf2,0xbf,0xf9,0xa6,0x7e,0xf3,0xcb,0xaf,0xcb,0xeb,0x2f,0xdf,0xfa,0xa5,0xa3,0xee, + 0xbf,0xcf,0x45,0xb2,0xaf,0xd3,0xde,0xda,0xe9,0x6e,0x75,0x99,0x5b,0x4a,0x76,0xfb, + 0x73,0x2f,0xae,0x6f,0xe4,0x67,0xf,0x8e,0xe5,0xdd,0x8f,0x9e,0xe2,0x67,0x9f,0x1e, + 0xcb,0x7,0x8f,0x4e,0xf0,0xe0,0xe9,0x29,0x8e,0x5e,0x5c,0x6,0x1d,0xcc,0x1d,0x81, + 0xbe,0xaf,0xb3,0xee,0xf,0x61,0x7c,0xa0,0x90,0x15,0x14,0xb7,0x0,0xc2,0x74,0xac, + 0x98,0x81,0x9e,0x95,0x3b,0xa1,0x73,0xda,0xd8,0x54,0x69,0x71,0xe1,0x9d,0xba,0x8a, + 0xe0,0xee,0xed,0x5b,0x5a,0xad,0x76,0xfb,0xac,0x62,0x75,0xe7,0xfd,0xcb,0xc4,0x9b, + 0xfb,0x3e,0x3f,0xfb,0xfb,0x47,0xc7,0x17,0x72,0xef,0xe8,0x85,0x7c,0xfc,0xe4,0x14, + 0x1f,0x3f,0x39,0x95,0xfb,0x4f,0xcf,0x71,0x74,0x7c,0x2e,0x47,0x27,0x57,0xf2,0xe8, + 0xf8,0x1c,0x17,0x33,0x9b,0x3c,0xca,0xf0,0xd0,0x19,0x84,0x2a,0x68,0x46,0x7a,0x44, + 0xd8,0x21,0xdf,0x4f,0x10,0xbb,0xe8,0x47,0x5c,0xe5,0x4c,0x4c,0x93,0xde,0x23,0x90, + 0x7b,0xcc,0x63,0x61,0x77,0x78,0xb3,0x4f,0x13,0xf6,0xe1,0x77,0xdb,0xb7,0x53,0x37, + 0x85,0xba,0xec,0x69,0x1e,0x2c,0xe9,0x17,0x28,0x9a,0xe5,0xb0,0x8d,0xf0,0x11,0x37, + 0x55,0x35,0x21,0xc4,0x42,0x44,0x8e,0x34,0x55,0x79,0xfb,0xcd,0xbb,0xf2,0x2b,0x6f, + 0xbd,0xfc,0x39,0xd9,0xe7,0x22,0x9f,0x3e,0x3d,0x97,0x87,0xc7,0x97,0x62,0x97,0xb9, + 0x79,0xe9,0x66,0x2c,0x2d,0xc2,0x96,0x26,0xd0,0x36,0xa3,0xe2,0xfa,0x98,0x61,0x75, + 0xf1,0xe3,0x34,0x8d,0x31,0x98,0x44,0xcb,0x8a,0x2d,0x1e,0xd,0xfb,0xba,0x46,0xa1, + 0x48,0xa8,0xc5,0x31,0xce,0xb8,0xea,0x82,0xbf,0xf8,0xe0,0xb1,0x9c,0x5e,0x77,0xfc, + 0xd3,0xef,0x7c,0x45,0x7f,0xff,0x5b,0x6f,0xe9,0xaf,0xd3,0x64,0xa7,0xbe,0x6b,0xad, + 0xa9,0x7c,0xeb,0xcb,0xaf,0x88,0xea,0x57,0x5b,0x6b,0xda,0xff,0xf8,0x47,0xf,0xe4, + 0xc7,0x9f,0x3e,0x13,0x2b,0x46,0xfd,0x53,0x77,0x17,0x80,0xef,0x92,0x74,0xd6,0x66, + 0xf3,0x3,0x1f,0xac,0xf7,0xb9,0x1e,0x1f,0xf3,0x98,0x29,0xda,0xc2,0xf8,0x77,0x20, + 0x3a,0x16,0x2d,0xd2,0xc7,0xb3,0x0,0x90,0xcd,0xab,0xcf,0xfd,0xa,0x8b,0x2,0x23, + 0xca,0x3d,0xbf,0x53,0xf6,0xb0,0xc1,0x3a,0x69,0x3a,0xd3,0xad,0xd9,0x29,0x9,0x82, + 0xa0,0xe9,0x75,0x4f,0x17,0x36,0x39,0xdd,0xa1,0x4b,0xc8,0xda,0xe8,0xe4,0xd5,0xb1, + 0xeb,0x87,0xc1,0xe2,0xe,0x8d,0x3,0x68,0xe8,0xe,0x51,0x1a,0xa3,0x72,0x68,0x8b, + 0x26,0xab,0x70,0xb2,0xab,0xe5,0xa4,0xc4,0x69,0x66,0x9d,0xc1,0x97,0x1a,0x28,0x19, + 0xd5,0xcc,0x93,0x6,0x2f,0x5d,0x4d,0xe9,0xde,0xe2,0x32,0xcf,0x16,0xf5,0x59,0x86, + 0x6b,0x64,0x6a,0x47,0xb6,0x4b,0xfb,0x25,0x7b,0xdb,0xf8,0xbf,0xdb,0xb7,0xe,0xe4, + 0xd7,0xbe,0xf4,0x9a,0x7c,0xe5,0xf5,0x97,0xe4,0xeb,0x6f,0xbd,0x22,0x3f,0xb9,0xff, + 0x5c,0x3e,0x3a,0x3a,0x95,0xcb,0xeb,0x9d,0xdc,0x39,0x6c,0xf2,0x85,0xd7,0xee,0xc8, + 0x5b,0xaf,0xda,0xee,0xf4,0x25,0xf9,0xe2,0xab,0x63,0x7f,0xba,0x75,0x48,0xdb,0x7f, + 0xaf,0x77,0xc8,0xc5,0xf5,0x8d,0x9c,0x5d,0xee,0xe4,0xc1,0xf3,0x33,0x79,0xf7,0xde, + 0x53,0xfc,0x6f,0x3f,0xf8,0x48,0x7e,0xfc,0xc9,0x33,0x74,0x64,0xa3,0x94,0xf2,0x58, + 0x3,0x31,0x46,0x36,0x9e,0xad,0x8,0x15,0xbc,0xf3,0x7,0xf8,0xf1,0xe3,0x33,0xfc, + 0xe9,0x7b,0x9f,0xe9,0xed,0xc3,0x3,0xfc,0xc1,0x6f,0x7c,0x59,0x5f,0x7f,0xf9,0xce, + 0x5e,0x86,0xf3,0xbe,0x5f,0x3,0x22,0xcf,0xce,0xae,0xe4,0x2f,0x7f,0xfe,0x8,0xff, + 0xcf,0xdf,0xdd,0x97,0x3f,0xf9,0xd1,0x7d,0x8c,0x9d,0x63,0xcb,0x1c,0x24,0xcd,0x25, + 0xf8,0x32,0x4a,0x28,0x9,0xb1,0x2c,0xb4,0x3e,0xbf,0xea,0xfa,0xd1,0xd1,0xa9,0x7c, + 0xf1,0xd5,0x3b,0xe,0x24,0x59,0x4,0x62,0x4d,0xa5,0xda,0x2c,0xaa,0xd0,0xc3,0xfc, + 0xe4,0x1,0x27,0xe1,0xdf,0x31,0x4c,0xea,0xdf,0xf8,0xd2,0x6b,0xf2,0xdb,0xdf,0x78, + 0xeb,0x3f,0xa9,0x3b,0xfe,0xfb,0x4c,0x2f,0xf6,0xfd,0x35,0xaf,0x38,0xb6,0xfc,0xe3, + 0x5c,0xd0,0x19,0xa5,0xec,0xe2,0xba,0xcb,0xd5,0x6e,0x27,0xcf,0xcf,0xaf,0xe5,0x93, + 0xa3,0x17,0xf8,0xde,0xfb,0x8f,0xe5,0x2f,0xde,0x3f,0xc2,0x7b,0x9f,0x3e,0x3,0xc5, + 0x4f,0x88,0x93,0x66,0xd,0x34,0x11,0x1f,0xad,0x77,0x95,0xb0,0x51,0x85,0xfd,0x9b, + 0x8a,0xfa,0x33,0xcb,0x40,0x17,0xd2,0xca,0x80,0x8d,0xb2,0x4d,0x85,0x26,0x77,0xd4, + 0x84,0xcc,0xb8,0xca,0x83,0x61,0xbb,0xdc,0xfa,0xfc,0xf6,0x5,0xee,0xd4,0x82,0xf6, + 0xf3,0x8a,0xa4,0x28,0x90,0x20,0x57,0xbb,0x2e,0x57,0xd7,0x5d,0xae,0x77,0x3b,0x39, + 0xbb,0xde,0xc9,0xd1,0xf1,0xb9,0x7c,0xfc,0xf8,0x14,0xef,0xdd,0x3f,0x96,0x9f,0xdc, + 0x3f,0xc6,0xcf,0x3f,0x3b,0x96,0x93,0xf3,0x6b,0x1b,0xfe,0xfa,0xd4,0xd3,0x2c,0x67, + 0xce,0x60,0xd,0x21,0xff,0x3c,0xe2,0x3d,0x53,0xd0,0xfc,0x68,0x73,0x17,0x3e,0x27, + 0x1d,0x10,0xa0,0x35,0x78,0x3a,0x89,0x5d,0xf0,0x90,0x3e,0x9f,0xcd,0xe,0xa3,0x99, + 0x40,0x21,0xcd,0xc6,0xec,0x53,0x66,0x25,0xf0,0xef,0xe,0xe5,0xed,0x1,0x15,0xac, + 0x88,0x98,0xb3,0xb9,0x6a,0x9e,0x7a,0x37,0x69,0xe3,0xe0,0x4e,0xcd,0x4b,0xf2,0xe, + 0xc7,0x38,0xf4,0x40,0xe5,0xed,0x37,0xee,0xca,0x57,0xde,0x78,0x59,0xf,0x29,0x71, + 0x91,0xcf,0xb9,0x27,0x2f,0x2e,0xe4,0xe7,0xf,0x4f,0xf0,0xf8,0xf4,0x12,0xf0,0x54, + 0xb5,0x71,0xf,0x74,0x50,0xbd,0xe1,0xbd,0xa9,0x37,0x89,0xe8,0x1e,0x6b,0xe0,0x3d, + 0xab,0x3f,0x8a,0x1e,0x9c,0x13,0x38,0x27,0x1b,0xea,0x24,0x74,0x19,0x68,0xaa,0x67, + 0xc3,0x78,0x1a,0xcd,0xeb,0xb3,0x8b,0x6b,0xfc,0xfb,0x9f,0x3f,0x92,0xf3,0xeb,0x9d, + 0x5c,0xdc,0xdc,0x88,0xaa,0xea,0x3b,0x5f,0xb8,0x2b,0xb7,0x4b,0xd1,0x68,0x4d,0xca, + 0x9d,0x5b,0x87,0xf2,0x9b,0x5f,0x7d,0x5d,0x5e,0xbe,0x73,0xd8,0xa0,0xda,0x8f,0x4e, + 0x2f,0xf1,0xe8,0xe4,0xc2,0xf4,0xb1,0x11,0xdf,0xd3,0x7,0xe,0xd6,0x50,0x87,0x1a, + 0x7c,0xdb,0x79,0x91,0x8f,0xff,0x37,0x9e,0x82,0x36,0x7f,0xd,0x92,0x42,0xe,0x3a, + 0x8b,0x1e,0xcc,0x17,0xca,0x14,0xca,0x10,0x91,0x3,0x9a,0x98,0x26,0xc8,0x8b,0xa6, + 0x71,0x46,0x86,0x38,0x38,0xf9,0x8a,0x62,0x93,0x19,0xdf,0x98,0x71,0x34,0x9d,0x33, + 0x2c,0x54,0x58,0xdf,0xea,0x89,0xa7,0x89,0xed,0x4f,0xed,0x7c,0x9f,0xab,0xe2,0x43, + 0x8a,0x33,0x95,0xf4,0x73,0x61,0xb7,0x9b,0x85,0xad,0x6c,0xa0,0xd1,0xb8,0x7b,0xda, + 0xe7,0xc9,0xb,0x9b,0x3,0x49,0x35,0x13,0x4a,0x5b,0x89,0x2f,0xcc,0xe3,0xf5,0x49, + 0x92,0xf3,0x7d,0x94,0xc6,0x88,0xd6,0xf,0x73,0x49,0xf,0xbd,0x8a,0xc8,0x35,0x8d, + 0xbb,0x3f,0x4f,0x8c,0xc3,0x7f,0xff,0xf6,0xad,0x43,0xf9,0xd6,0xdb,0xaf,0xc9,0xaf, + 0x7c,0xe1,0x15,0xb9,0xba,0xd9,0x79,0x77,0x7c,0xd0,0x54,0xe,0x55,0xe5,0xe0,0x40, + 0xe5,0x40,0xd5,0xa1,0x20,0x5b,0x81,0x10,0xf6,0x7f,0xcf,0xcf,0xae,0xe4,0xdd,0x7b, + 0x8f,0xf1,0x1f,0x7f,0xf6,0x48,0x7e,0xf8,0xf1,0x53,0x7c,0xf2,0xe4,0x54,0x4e,0x2f, + 0x6f,0x6,0xfe,0x5f,0xd9,0x60,0x44,0xa,0x71,0x14,0x6b,0xdf,0x2c,0x26,0xc3,0xe3, + 0xde,0x3c,0xb7,0xe4,0x7a,0xd7,0xe5,0x4f,0xfe,0xee,0x3e,0xce,0x2f,0x77,0xf2,0xd2, + 0xad,0x3,0xf9,0xbd,0x6f,0xbd,0x95,0xc2,0x19,0xea,0xc5,0xb9,0xb5,0xd3,0xfc,0xe8, + 0xf1,0xb,0xf9,0xb7,0xdf,0xbf,0x87,0x3f,0xff,0xd9,0x11,0x7e,0xfe,0xd9,0xb1,0x5c, + 0xdc,0x8c,0x16,0x45,0xeb,0x3c,0x48,0xf3,0xae,0x19,0x31,0xbd,0x5,0x53,0x82,0x3b, + 0x56,0xe7,0xd9,0xd3,0xf3,0x2b,0xfc,0xed,0xc7,0x4f,0xe5,0x9d,0xb7,0x5e,0x51,0x8b, + 0x59,0x5c,0xc6,0xb0,0x89,0x42,0x98,0x62,0x48,0x25,0x98,0x50,0x8e,0x1c,0x86,0xbf, + 0x30,0x1a,0x0,0x5,0x90,0x43,0x62,0xb,0x48,0xf2,0xf,0xb9,0xd0,0xff,0x21,0xff, + 0xb7,0x45,0x50,0xf3,0xbd,0xef,0xc5,0x8d,0xbc,0x77,0xff,0x19,0x7e,0xf0,0xc1,0x63, + 0xf9,0xf1,0xfd,0x63,0x7c,0xf8,0xe8,0x44,0x8e,0xcf,0xae,0x70,0x79,0xdd,0xbd,0xe3, + 0xe,0xa1,0x1b,0x83,0xf,0x40,0xc9,0x5d,0xe2,0x8b,0x5e,0xf2,0xd0,0x81,0x42,0x1e, + 0xb0,0x51,0x6f,0x91,0x14,0x8e,0x8c,0xea,0x64,0x4e,0x71,0xbb,0x68,0xe6,0x48,0xcd, + 0x1d,0x68,0xd3,0xd6,0xfe,0xbe,0x1e,0x44,0xf9,0xdc,0xcf,0xfe,0xf3,0x7c,0xf7,0xc7, + 0x17,0x37,0x72,0xef,0xf1,0xb,0xf9,0xf9,0x83,0x63,0xfc,0xec,0xe1,0x89,0xfc,0xe2, + 0xd1,0x9,0x1e,0x1d,0x5f,0xc8,0xf1,0xf9,0x35,0xae,0x77,0x5d,0xae,0x26,0xb6,0x75, + 0x32,0xa3,0x46,0xd3,0x84,0xa0,0x49,0x85,0x40,0xb0,0x36,0x6a,0xf3,0xdc,0xc4,0x64, + 0xb4,0xce,0xfb,0x9c,0x82,0x70,0x1,0x85,0xa1,0x5a,0xed,0xcd,0xc1,0x54,0x83,0x61, + 0x4e,0x2d,0x0,0xa0,0x8f,0xc2,0xa1,0x1b,0xd,0x1f,0x72,0x40,0xf7,0x78,0xdc,0x23, + 0xc,0xa4,0x8a,0x4b,0xae,0xf9,0xc9,0x35,0xba,0xf2,0x9,0xaa,0x6,0x43,0x5a,0x54, + 0x63,0xd,0xad,0x2d,0x3b,0x3f,0xd4,0x2b,0x25,0x79,0xf3,0x95,0xdb,0xfa,0xc5,0x57, + 0x6f,0xf,0x1f,0x49,0xf1,0x74,0x3,0x90,0xcf,0x8e,0x2f,0xe4,0x6f,0x3f,0x7e,0x2a, + 0xcf,0x2f,0x6e,0x52,0xb4,0x35,0x75,0x12,0xb3,0x3f,0x1d,0xff,0x9f,0x5f,0x53,0x7, + 0xe2,0x5a,0x1,0x31,0xc9,0x3a,0x6b,0x55,0xe6,0x67,0x68,0x33,0xa0,0x3e,0x42,0x5f, + 0x35,0x44,0xfc,0x9c,0xea,0x67,0xbb,0x63,0xde,0x30,0x47,0x50,0x5,0x44,0xf5,0x6f, + 0x3e,0x7e,0x8a,0x47,0x2f,0x2e,0xe5,0x83,0xa3,0x33,0xf9,0xef,0x7f,0xeb,0x2b,0xf2, + 0x4f,0x7e,0xe3,0x2b,0xba,0x4f,0x50,0xda,0x5a,0x93,0x77,0xde,0x7c,0x59,0xfe,0xd9, + 0x6f,0x7d,0x55,0x6f,0xdf,0x6a,0xed,0xdf,0x7c,0xff,0x23,0xfc,0xe2,0xf1,0x8b,0x1e, + 0xc2,0x43,0xb0,0xf7,0xd7,0xa2,0xf0,0xe6,0x5e,0xa9,0xcf,0xcb,0xbc,0xa9,0xc,0xb9, + 0xe3,0x40,0xc1,0xcd,0x8e,0x5d,0x6d,0x2c,0x8a,0x3e,0x7f,0xe8,0xdd,0xdb,0x6a,0xf4, + 0x9c,0x38,0x27,0x59,0x45,0x94,0xc6,0x3d,0x9c,0x11,0x3,0x59,0x38,0x17,0xe9,0xef, + 0x73,0xf6,0x5,0xa0,0xcb,0x40,0x5b,0xb2,0x4f,0x2f,0x35,0xcf,0x5b,0x74,0x76,0x3b, + 0x29,0xe,0x39,0x88,0x21,0x2a,0x89,0xaa,0xfd,0xd5,0x94,0xc1,0xae,0xd5,0xae,0x94, + 0xdc,0xe,0x79,0xa4,0x8a,0x1c,0x8b,0x3e,0xdc,0x9d,0x8d,0x70,0x9c,0xa6,0x43,0x98, + 0x33,0x83,0x49,0xc9,0x81,0xe1,0x3b,0x6d,0x9c,0xa3,0xd4,0xc1,0x43,0x15,0x84,0x71, + 0xe7,0x24,0x22,0x88,0xa8,0x5e,0x5e,0xef,0xe4,0xfc,0xea,0x46,0x5e,0xbe,0x73,0x2b, + 0x9,0x92,0x6a,0x47,0x51,0xbb,0x88,0xa1,0xca,0x3d,0x10,0x91,0x5b,0x7b,0xad,0x60, + 0x5b,0x9d,0xff,0xd5,0xf5,0x8d,0x1c,0xbd,0xb8,0x92,0xa7,0x2f,0x2e,0xe5,0xc1,0xb3, + 0x33,0xdc,0x3b,0x7a,0x21,0x3f,0xb9,0x7f,0x8c,0x1f,0x7d,0xf2,0x4c,0x3e,0x7e,0x7c, + 0x1a,0x69,0x3d,0x1e,0x9f,0xa,0x70,0x90,0xc7,0x66,0xfe,0x1,0x18,0x93,0x3f,0x7f, + 0xd1,0xda,0x78,0x89,0xa4,0xc9,0x65,0x17,0x79,0xf7,0xe3,0xa7,0xf2,0xca,0x4b,0x87, + 0xf2,0xe0,0xf9,0xb9,0xfc,0xc6,0xd7,0x5e,0x97,0x2f,0xbf,0x7e,0x57,0x5f,0xbf,0x7b, + 0x4b,0x5e,0xbb,0x7b,0x7b,0x11,0xcb,0x5c,0x5d,0xdf,0xc8,0xf3,0xf3,0x6b,0x79,0x7c, + 0x72,0x29,0x9f,0x3d,0xbf,0xc0,0xdf,0x7c,0xf8,0x58,0xfe,0xec,0x27,0xf,0xf1,0xc1, + 0xa3,0x13,0xdc,0xec,0x3a,0x59,0xad,0xd,0x5f,0x91,0xa2,0xa1,0xb2,0x40,0x7c,0xee, + 0x6e,0xd2,0x43,0x3a,0x1b,0x3a,0xd0,0x96,0xf7,0xe9,0xd9,0xa5,0x7e,0xef,0x83,0x23, + 0x7c,0xfb,0xed,0x57,0xe5,0xdb,0x6f,0xbf,0x9a,0xe2,0x6a,0x81,0x29,0xaa,0x6e,0x2a, + 0x32,0xf,0xe9,0xfc,0x27,0x9a,0x28,0x4,0x2e,0xac,0x1c,0xd3,0x4e,0x25,0x44,0xa9, + 0x79,0xd2,0x55,0xae,0x76,0x5d,0x2f,0xaf,0xae,0x17,0xe5,0xff,0xe7,0x75,0x91,0xff, + 0x5f,0x2f,0xef,0x1a,0x6b,0xca,0xcf,0xd3,0xd5,0xcd,0x4e,0x9e,0xbc,0xb8,0x92,0x47, + 0x27,0xe7,0xf2,0xf0,0xf9,0x5,0xee,0x3d,0x7e,0x21,0xef,0x3f,0x7c,0x81,0x9f,0x3e, + 0x78,0x2e,0x1f,0x1d,0x9d,0xe2,0x72,0xd7,0xe3,0x8c,0x18,0x56,0x37,0x90,0x54,0x2, + 0x26,0x3a,0x56,0xff,0xa0,0x3d,0xe8,0x1d,0x7e,0x9b,0x63,0x9c,0xff,0x8,0xe1,0xfb, + 0x16,0x16,0x21,0x68,0xab,0xda,0xf2,0xb1,0x34,0x9f,0xc9,0x2e,0xb4,0xba,0xa,0xcf, + 0xd4,0xbc,0x5c,0x14,0x97,0x37,0x5d,0xb7,0xde,0x81,0x2d,0x11,0xdb,0xbe,0x4b,0xdb, + 0xc3,0x5b,0x2e,0x6f,0xe4,0xec,0xf2,0x46,0x5e,0x5c,0xdd,0xc8,0x8b,0x8b,0x6b,0x39, + 0x3e,0xbf,0xc6,0xd3,0xd3,0x4b,0x79,0xf8,0xfc,0x42,0xee,0x3f,0xbf,0x90,0x4f,0x9f, + 0x9e,0xe2,0xa3,0x27,0x67,0xf2,0xd9,0xf3,0x33,0xec,0x42,0x9f,0xe,0x37,0x9,0x2b, + 0x9d,0x42,0xc1,0x39,0x12,0x1a,0x51,0xf0,0xe7,0x85,0x79,0x99,0xda,0x2c,0xc3,0x46, + 0xec,0x32,0xf3,0xb8,0xe0,0xbb,0x74,0x0,0x5d,0x1d,0xf2,0x99,0x94,0xec,0x10,0x1, + 0xe,0x4,0x2,0xe3,0x8c,0x79,0x95,0x8d,0xe8,0xdc,0x7d,0x1f,0xe9,0x45,0x2f,0x48, + 0xd1,0x6e,0xeb,0x4a,0x78,0x84,0xdd,0x5c,0xb6,0xab,0x8e,0xae,0x78,0x2e,0xff,0xa7, + 0xd0,0xd8,0xff,0x3a,0xb2,0xe,0xe6,0xf1,0xd7,0x74,0x68,0x1a,0x6e,0x1f,0x38,0xe1, + 0xb1,0x4e,0x92,0x1e,0x9d,0x5c,0xe2,0xdd,0x4f,0x9e,0xe3,0xd9,0xc5,0x15,0x9c,0x4a, + 0xa5,0x8a,0xe1,0xa8,0x6e,0x73,0xba,0xa0,0xf3,0xe2,0xe,0xf1,0x9f,0x99,0x48,0x1c, + 0x10,0x37,0x5f,0x6c,0xcf,0xe3,0x20,0xa3,0x70,0x77,0xe2,0x5d,0x11,0x61,0x4c,0xb5, + 0x3e,0x84,0x2f,0x1c,0xc2,0x3a,0xdb,0x98,0x44,0x4,0x37,0xa2,0xfa,0xd1,0xf3,0x73, + 0x5c,0xbe,0xff,0x48,0x6e,0x0,0xbd,0xbc,0x1,0x7e,0xfb,0xeb,0x5f,0xd0,0x2f,0xbf, + 0xfe,0xd2,0xa6,0xf5,0xf3,0xe0,0xa0,0xc9,0x37,0xde,0x7a,0x59,0x55,0xbf,0x22,0x1f, + 0x3d,0x39,0x93,0xe7,0x97,0x37,0xfa,0xf4,0xf4,0x32,0xc6,0xdc,0x88,0x19,0xa1,0x9a, + 0x60,0xc2,0x2f,0x72,0xdb,0xa1,0xb7,0x51,0x93,0xd,0x96,0x9c,0xc7,0xb,0x5a,0xbc, + 0x8e,0x4c,0x36,0x8d,0x1f,0x62,0x4d,0x89,0x51,0x31,0xff,0x3,0x84,0xb9,0xc9,0x6a, + 0xd4,0xb2,0x4a,0xdc,0xfa,0x35,0x9f,0xf7,0xac,0x30,0x17,0xf1,0xf7,0x10,0x8c,0xfa, + 0x85,0xe1,0xef,0xc2,0x59,0x25,0xa0,0xdd,0x79,0x61,0x83,0x1c,0x72,0x5,0x7,0x66, + 0xfe,0x14,0x1d,0x9c,0xd2,0xc5,0xc,0xba,0x64,0x98,0x69,0xc3,0xe8,0x48,0x4f,0xac, + 0x88,0x50,0x3,0xf3,0x32,0xc4,0x8,0xb0,0x5c,0x74,0x72,0x30,0x2b,0x40,0x73,0x20, + 0xcc,0x1d,0x93,0x4e,0xee,0x7b,0xa8,0xdd,0xfd,0xc5,0x10,0x67,0x2b,0xa9,0x8f,0x2d, + 0x70,0x7c,0x7e,0x8d,0x27,0x27,0x97,0x38,0x6c,0x4d,0x6f,0xdf,0x3a,0xf8,0xdc,0xb1, + 0xfb,0x2f,0xdb,0x99,0x6e,0x29,0x6d,0xe3,0x20,0x83,0x5c,0xdd,0xec,0xe4,0xe3,0x27, + 0x67,0xf2,0xee,0x47,0x4f,0xf0,0x57,0xbf,0x78,0x22,0x3f,0xfa,0xf4,0x19,0x3e,0x7e, + 0x7c,0x8a,0xcb,0x9b,0x9d,0xef,0x7c,0x91,0xd7,0xc5,0x73,0x51,0xa6,0xe1,0x7,0x28, + 0xde,0xe8,0xa0,0x9d,0xcc,0x7,0xa,0x71,0xc8,0xfa,0xe5,0x2a,0x22,0xcf,0x2e,0xae, + 0xf5,0x7f,0x7f,0xf7,0x53,0xfc,0xcd,0xc7,0xcf,0xf0,0x9f,0xbd,0xf3,0x86,0xfe,0xfe, + 0x37,0xbf,0x24,0xdf,0xf9,0xda,0x6b,0xf2,0xf5,0xb7,0x5e,0xd3,0x37,0x5e,0xbe,0x25, + 0xb7,0xe,0x9a,0x5c,0xdf,0xec,0xe4,0xc5,0xe5,0x4e,0x8e,0x4e,0x2e,0xe4,0xc3,0x47, + 0x2f,0xf0,0xee,0xc7,0x4f,0xf1,0xef,0x7f,0xfa,0x10,0x1f,0x3d,0x39,0x95,0xeb,0x9b, + 0x59,0x7e,0x36,0x9b,0x6,0xa4,0x2c,0x64,0x8,0xc9,0xa7,0xc8,0xa3,0x93,0x19,0x3, + 0x24,0xa7,0x40,0x1a,0xca,0x43,0xcf,0x6f,0x80,0x1f,0xdd,0x3f,0x96,0x1f,0x7c,0xf8, + 0x54,0xbe,0xf5,0xf6,0x6b,0xf2,0xeb,0x5f,0x79,0x5d,0x99,0xc,0x76,0x76,0x75,0x23, + 0x3b,0xc8,0xc,0x95,0xe6,0xcd,0x43,0x93,0xfc,0xe1,0x20,0xa4,0xb8,0x5a,0x70,0xab, + 0xf3,0xb3,0x3c,0xbe,0xbc,0x96,0xa3,0xd3,0x6b,0xf9,0xf2,0xab,0xba,0xf8,0x5c,0xff, + 0xff,0xfa,0xbf,0x7d,0x17,0xdc,0xc9,0xf9,0xb5,0x3c,0x3c,0x39,0x97,0x77,0x3f,0x7e, + 0x8a,0xef,0xff,0xe2,0x9,0xbe,0xff,0x8b,0x27,0xf2,0xe8,0xf8,0x1c,0xd7,0xdd,0x7b, + 0x65,0x6a,0x26,0x82,0xbc,0x6a,0xce,0x0,0x2e,0x9f,0xe0,0xd8,0xd1,0xd9,0x81,0x77, + 0xb2,0x46,0xa9,0xa2,0xbb,0x5d,0x13,0xb1,0x47,0xd6,0x1c,0x47,0x63,0xaa,0xe4,0x41, + 0x29,0x75,0x35,0x6a,0x8c,0x60,0x3c,0x85,0xcf,0xe5,0xef,0x1e,0x36,0xb9,0x53,0xd1, + 0xa7,0xe7,0x57,0x72,0x72,0x7e,0x2d,0xaf,0xdc,0xd9,0x16,0x19,0xd6,0x75,0xcf,0x56, + 0x87,0x75,0xb3,0xdb,0xc9,0xe3,0x17,0x57,0xf2,0xc9,0xd3,0x53,0xf9,0xec,0xf8,0x12, + 0x9f,0x3c,0x3d,0x93,0xf,0x8f,0x5e,0xc8,0xcf,0x1f,0x9e,0xe0,0xa3,0x27,0xa7,0x38, + 0xbf,0xde,0x89,0xdd,0xb8,0x86,0x41,0xe5,0xf4,0x13,0x25,0xcf,0x4f,0xc4,0xec,0x1a, + 0xe2,0x2,0x40,0x13,0x19,0x20,0x10,0x5f,0xe,0xc3,0xbf,0xf5,0xa9,0x84,0x73,0x7b, + 0xbe,0x0,0x13,0xc,0xe2,0xdd,0xf6,0x14,0x22,0xfb,0x25,0x2e,0xd6,0xad,0xbb,0xcf, + 0x7c,0xfa,0x9d,0x6,0x34,0x1b,0xdd,0x31,0xb0,0x6a,0x96,0x3f,0x3b,0xef,0x62,0x46, + 0xd2,0x42,0x7,0xe4,0x4d,0x4f,0xf3,0x4b,0x30,0x7c,0x99,0x76,0x91,0x9b,0x15,0xab, + 0xb5,0x3c,0x72,0x57,0xa2,0x84,0xa9,0xca,0xad,0x5b,0x87,0x4b,0xe1,0xca,0xe7,0xd2, + 0xa3,0x17,0x97,0xf2,0x93,0x87,0x27,0x72,0x7a,0xdd,0x67,0xb1,0x2c,0xd1,0xc6,0x8a, + 0x5b,0xf5,0xa2,0x70,0x99,0x29,0xe2,0x26,0x12,0x10,0x96,0x48,0xce,0x87,0xb4,0xcf, + 0xe3,0xba,0x27,0x97,0xb4,0x52,0xf2,0xd3,0x78,0xa,0x7a,0x23,0xcc,0x70,0x23,0x82, + 0xa4,0xb2,0xc9,0x5e,0x9c,0xf1,0x21,0xa2,0xfa,0xf0,0xc5,0x15,0xfe,0xaf,0x1f,0x3f, + 0xc0,0xcf,0x1e,0xbd,0xd0,0x7f,0xf5,0x7,0xdf,0x94,0xff,0xee,0x37,0xbf,0xa2,0x2f, + 0xdf,0x6a,0x72,0x48,0x23,0x78,0xfb,0x5e,0xf,0xf,0xe,0xe4,0x5b,0x5f,0x7a,0x55, + 0xff,0xc9,0x6f,0xbe,0x2d,0x17,0xbb,0x9d,0xfe,0xf1,0x7b,0xf,0x71,0x7a,0xb5,0x1b, + 0xd2,0x7c,0x1b,0xd3,0xf5,0x89,0x1a,0xc0,0xdc,0x54,0xeb,0x6c,0xd,0xa6,0x28,0x42, + 0xe,0xe6,0xd8,0xbd,0x99,0x58,0xce,0x2a,0xe2,0x83,0xa1,0x87,0x54,0xf,0x7d,0x4b, + 0xe8,0xde,0x5c,0xb,0xeb,0x6,0xdd,0x3a,0x47,0xbe,0x8a,0x56,0x42,0x8f,0x1b,0xcf, + 0xe3,0xc,0x9b,0x21,0x37,0x9,0xa,0x50,0xef,0x63,0x17,0x67,0x68,0xb2,0xd,0x72, + 0x15,0x6f,0x37,0xf1,0xe1,0x50,0xa,0x46,0xc7,0xe5,0x97,0x95,0x14,0x5a,0x19,0x24, + 0x5,0xc3,0xf2,0x70,0xbe,0x67,0x86,0x5a,0x2c,0xf1,0xe7,0x41,0xd,0x25,0x29,0x15, + 0x47,0x33,0xaa,0x92,0x97,0x5b,0x47,0x23,0xa6,0x34,0x86,0x9a,0xc1,0x69,0x3e,0x3e, + 0x34,0x61,0x5c,0x13,0xb6,0xec,0x4c,0x9b,0xa4,0xba,0x2,0xe0,0x87,0xf7,0x8f,0xf1, + 0xce,0xcf,0x1f,0xe1,0x5f,0xfc,0xf6,0x3b,0x7a,0xfb,0xd6,0xc1,0x72,0xd8,0x30,0x2a, + 0x71,0x9f,0x2a,0x77,0x6b,0xff,0xa7,0xaa,0xf2,0xe4,0xc5,0xa5,0x3c,0x78,0x7e,0x2e, + 0xf,0x9e,0x9d,0xe3,0xd3,0xa7,0xa7,0xf2,0xd1,0x93,0x33,0x79,0xf8,0xfc,0x2,0x8f, + 0x4f,0x2f,0xe5,0xe8,0xf8,0x2,0x4f,0xcf,0x2e,0x47,0x64,0x69,0x6b,0xec,0x7b,0x8d, + 0x2,0xd0,0xc3,0xec,0x91,0x26,0xcc,0xc9,0xba,0xc0,0x5c,0x0,0x53,0x43,0x51,0x18, + 0x71,0x51,0xa4,0xc8,0x83,0x93,0xb,0xb9,0xfc,0x70,0x27,0x9f,0x3e,0x3b,0xc7,0x9f, + 0xfc,0xf4,0xb6,0xbc,0x7a,0xe7,0x96,0xde,0x39,0x3c,0x90,0x91,0x47,0x4,0xb9,0xee, + 0x90,0x8b,0xab,0x9d,0x1c,0x9f,0x5f,0xe1,0xf1,0x8b,0x4b,0x79,0xf0,0xec,0x1c,0xd7, + 0xbb,0x60,0x43,0xdb,0x4b,0xf,0x4a,0x4d,0x53,0xcc,0x57,0xa4,0xd1,0x36,0x52,0x57, + 0x20,0x8b,0x2c,0x71,0x82,0x98,0x18,0xa5,0xe0,0xb5,0xfd,0xc7,0xf,0x8e,0xe4,0xf4, + 0x7a,0x27,0xff,0xf4,0x3b,0x6f,0xcb,0x77,0xbf,0xf6,0xa6,0xbc,0xf1,0xf2,0x2d,0x7d, + 0x78,0x72,0x81,0xef,0xfd,0xe2,0xb1,0x3c,0x39,0xbf,0x1a,0xa,0x5f,0xf,0x94,0x53, + 0x46,0x1c,0x8c,0xdd,0x22,0x18,0xee,0x24,0x1b,0xd8,0x26,0x91,0x4f,0x9f,0x5d,0xc8, + 0x8f,0x3f,0x7d,0x86,0x37,0x7e,0xfd,0xcb,0x7a,0xfb,0x56,0x16,0xae,0xfd,0x43,0xfe, + 0xaf,0x52,0xac,0xb6,0x3a,0x54,0xfb,0xeb,0x67,0xa7,0x97,0xf2,0xd1,0xd3,0x33,0xf9, + 0xf4,0xe9,0x19,0x3e,0x79,0x7a,0x2a,0x9f,0x3e,0xbb,0x90,0xa3,0x93,0xf9,0x4c,0x9c, + 0x5c,0xe0,0xd1,0xf1,0xa5,0x71,0xb3,0xa7,0x37,0x9c,0xf2,0xab,0xd0,0x2,0x26,0x2d, + 0xd6,0x40,0x79,0xc7,0x9,0x97,0xd7,0x1a,0xcc,0xa4,0x39,0x13,0xcb,0xae,0x28,0x78, + 0x4c,0x14,0x89,0x2c,0x7d,0xe9,0xae,0x8,0x61,0xca,0x4c,0xe,0x33,0x1b,0x4f,0xac, + 0xd5,0x1b,0xb9,0x6d,0x9a,0x81,0xd4,0x44,0x45,0xb4,0xb,0xe4,0xde,0xe3,0x33,0xdc, + 0x7b,0x72,0x2a,0xdf,0xfd,0xda,0x1b,0xba,0x6f,0xc5,0x60,0xbf,0xbe,0xd9,0xed,0xe4, + 0xd9,0xd9,0xb5,0x3c,0x3b,0xbf,0x92,0x47,0xc7,0x17,0xb8,0xff,0xec,0x5c,0x1e,0x9e, + 0x5c,0xc8,0xe3,0x17,0x97,0xf2,0xfc,0xfc,0x6,0x2f,0x2e,0xaf,0xe5,0xec,0xea,0x46, + 0x4e,0x2f,0x6f,0xe4,0xe4,0xe2,0x1a,0xcf,0xce,0xae,0xe4,0x6a,0x17,0xa2,0xcf,0x28, + 0xe4,0x28,0x47,0x58,0x84,0x2f,0x4a,0xf8,0xc1,0x37,0xef,0x4f,0xd8,0x1e,0xbb,0x19, + 0x26,0x44,0xe7,0xaf,0x15,0xe8,0x9e,0x45,0x6e,0x83,0x77,0xf4,0xa1,0x65,0xe,0xef, + 0x38,0xa8,0x13,0x9f,0x4,0x38,0xfe,0xfb,0x22,0x32,0x86,0xb6,0xdd,0xce,0xfe,0x79, + 0x8d,0x5b,0x3d,0x39,0x8b,0x89,0x6a,0x37,0x63,0xbb,0xee,0xc8,0xf5,0xd2,0x41,0x3d, + 0x51,0xd,0xdd,0xf0,0x5c,0x3,0x58,0x96,0xe7,0x3c,0x37,0x74,0x8e,0xdc,0x27,0xce, + 0xb8,0x5,0x67,0xbc,0xe9,0xc2,0x46,0xf7,0x34,0xb9,0xdd,0x4e,0x9e,0x9e,0x5d,0xcb, + 0xfd,0xe3,0x73,0x79,0x71,0xb3,0xc3,0x64,0xbd,0xc,0x43,0x38,0x5d,0xd6,0x70,0xf5, + 0xc5,0xfc,0xfe,0xba,0xc1,0x74,0xd4,0x2,0x24,0xed,0xd7,0x3c,0x11,0xe6,0xf7,0x9e, + 0xd2,0x75,0x8d,0x74,0x60,0xb4,0x42,0x4b,0xba,0x8c,0xb8,0xeb,0xf0,0xb3,0x87,0x47, + 0x7b,0xf0,0x25,0x9a,0xd3,0xd6,0x2e,0x76,0x5d,0xdf,0x7f,0x72,0x8a,0xff,0xf9,0xfb, + 0xf7,0xe4,0xc3,0x27,0x67,0xf2,0xcf,0xbf,0xfb,0x15,0xfd,0x47,0x5f,0x7e,0x55,0xe, + 0xf,0xe,0xfc,0xcc,0x8e,0xd5,0x82,0xc8,0x7f,0xf9,0x6b,0x5f,0xd4,0xab,0x1d,0xda, + 0xf,0x1f,0x1c,0xe3,0x83,0xa3,0xd3,0xb1,0x7e,0x6d,0xb6,0x91,0x9a,0x47,0x9,0xda, + 0xe8,0xca,0xe7,0xbe,0x5c,0x1b,0xb4,0x4b,0x98,0xb9,0x6d,0xb9,0xd2,0x7b,0x4e,0xc8, + 0x6,0xcd,0xd2,0xb5,0x89,0x76,0x84,0x61,0x61,0x1d,0xb1,0xf3,0x5,0x1f,0x49,0xf7, + 0x49,0x7d,0x4e,0x7c,0x15,0x4d,0x61,0x1f,0x99,0x1a,0xe7,0x71,0xaa,0x94,0xf0,0xe9, + 0xdc,0x8d,0xb4,0x32,0xdf,0x32,0xdc,0xce,0x82,0x7,0xad,0xe5,0x81,0x7d,0xad,0xfa, + 0xcc,0x22,0x56,0xf,0xbc,0x72,0xa4,0x9a,0x76,0xa2,0x1b,0xd9,0x1e,0x8d,0x5,0xdb, + 0xf1,0x70,0x9b,0x53,0x91,0x78,0xd3,0xb0,0x7d,0x51,0xa3,0xb,0xdf,0xb2,0x94,0x55, + 0xed,0x65,0x47,0x17,0x45,0x33,0xde,0x8f,0x7b,0x48,0xc6,0x37,0xdf,0xdd,0x8f,0xab, + 0xf2,0xb3,0x87,0x27,0x78,0xf9,0xa7,0xf,0xf1,0xce,0x17,0x5f,0xc6,0x77,0xbe,0xf6, + 0xa6,0xde,0x99,0xe0,0x8f,0xc3,0xe9,0xad,0x61,0xe8,0xa,0x1f,0xd2,0xbb,0x5d,0x97, + 0x1d,0x20,0x37,0xbb,0x2e,0x1d,0x90,0x9b,0x2e,0x72,0xb3,0x1b,0x5c,0xf3,0xf3,0xab, + 0x1b,0x79,0x7a,0x76,0x89,0x7,0xcf,0x2e,0xe4,0x17,0x47,0x27,0xf2,0xfe,0xa3,0x53, + 0x7c,0xf0,0xf0,0x58,0x3e,0x38,0x3a,0xa5,0x55,0x87,0x19,0x9e,0x6d,0x94,0x1e,0xf6, + 0x2a,0xf1,0x88,0x26,0xf6,0xf6,0xa5,0x90,0xdc,0xc4,0x5a,0x21,0xa6,0xe9,0xc0,0x13, + 0x82,0x7,0xd2,0x1e,0xb2,0x6c,0x46,0x18,0x79,0x7c,0x7e,0x85,0xc7,0xe7,0x57,0x1b, + 0xb2,0x44,0xf6,0x89,0x9b,0x78,0x47,0x45,0xf,0x18,0xa3,0x98,0x3a,0xc2,0xf9,0x8e, + 0x6b,0x34,0xc8,0xaa,0x65,0x82,0xe0,0x52,0x4f,0x5e,0x8,0xf8,0x9,0xd5,0x8d,0xab, + 0x38,0xdf,0xf8,0xcf,0x4e,0x2e,0xf1,0xe8,0xbd,0x7,0xb8,0xb8,0xd9,0xe9,0x83,0xe7, + 0x17,0xfa,0xd5,0x37,0x5e,0x92,0xf7,0x1f,0xbd,0xc0,0x5f,0xdd,0x7b,0x2a,0xcf,0x2e, + 0xae,0x67,0x39,0x3d,0x13,0x2e,0x24,0xe7,0xc2,0xc3,0xa1,0x3b,0x31,0xd5,0xa1,0xc1, + 0xb0,0x7f,0x4d,0x1f,0x3d,0x3d,0xc5,0xf7,0xee,0x3d,0xd5,0x6f,0x7c,0xe9,0x55,0xf9, + 0xf5,0x3b,0x87,0xcb,0x45,0xbc,0x75,0x51,0x7f,0x9e,0x2b,0x80,0xb,0x1,0x0,0xb2, + 0xdb,0x75,0xb9,0x1,0xe4,0x7a,0x37,0x30,0xa7,0xbb,0x5d,0x97,0xab,0xde,0xe5,0xc9, + 0xe9,0x95,0xdc,0x7f,0x7a,0x86,0x9f,0x3d,0x7c,0x21,0x3f,0x79,0xf8,0x1c,0x3f,0xfd, + 0xec,0x44,0x3e,0x7b,0x7e,0x41,0x16,0x33,0xb3,0x4,0xcd,0x10,0x8c,0x78,0xf9,0x31, + 0x3,0x4c,0xf2,0xce,0x5c,0xdd,0x4e,0x35,0xf7,0xbe,0xd,0x73,0xb3,0x89,0x70,0x9a, + 0xcd,0xa,0xcf,0x14,0xdb,0x4,0x30,0x49,0xef,0x7a,0xcb,0xe7,0xc0,0xc4,0x6b,0x28, + 0x4d,0x57,0xe2,0x80,0x65,0x8d,0xf2,0x94,0x29,0x8b,0x8a,0xdc,0x88,0xca,0x8f,0x3f, + 0x3b,0x96,0xaf,0xbf,0xf5,0x8a,0x7e,0xe3,0xad,0x57,0xe5,0xd5,0x97,0xc6,0x67,0x7b, + 0x7e,0x75,0x2d,0x67,0x57,0x5d,0x4e,0x2e,0xae,0x5d,0x12,0x76,0x71,0xd3,0xe5,0xe4, + 0xfc,0xa,0x8f,0x4e,0x2e,0xe5,0xe1,0xc9,0x85,0x7c,0xfc,0xf4,0x4c,0x3e,0x38,0x1a, + 0xea,0xf4,0xa3,0xb3,0x2b,0x54,0x1a,0xaf,0xed,0x9c,0x39,0xec,0x23,0x76,0xd0,0x76, + 0x1c,0x6a,0x4c,0xf9,0x2,0xd7,0x32,0x76,0xe9,0xa0,0x78,0xbb,0xd9,0x65,0x7a,0x97, + 0x6c,0xaf,0x1d,0xb,0xd8,0xda,0x74,0x98,0x2b,0x30,0xf6,0xef,0xd,0x22,0x7d,0xee, + 0xce,0x63,0x67,0xde,0x25,0x2e,0xd8,0x40,0x2a,0x38,0x31,0x6e,0x74,0xfc,0xd3,0xd7, + 0xed,0x59,0xe8,0xd,0x52,0x63,0x80,0x19,0xd8,0x25,0xfe,0x99,0x9a,0x8b,0x40,0x47, + 0xfa,0xb7,0x42,0xed,0xa2,0x6,0xad,0xa2,0x63,0x8d,0xd8,0x72,0x83,0xd8,0x74,0x49, + 0x46,0xb4,0xff,0x3d,0xbf,0xee,0xf2,0x93,0xcf,0x8e,0xf1,0xc9,0xb3,0xf3,0x71,0x5e, + 0xce,0x8a,0xc,0x42,0xe7,0xad,0x5b,0x4b,0xad,0xa8,0x1,0xc6,0x73,0xa4,0x10,0x45, + 0x17,0x28,0xba,0x59,0xf4,0xa0,0xd3,0xea,0x9d,0xe2,0x59,0x32,0x32,0xd8,0x93,0x30, + 0x45,0x85,0xc0,0x69,0x95,0x21,0xae,0xac,0xd8,0x66,0x2d,0xed,0x10,0x19,0x2a,0x20, + 0xb8,0xda,0x41,0xff,0xf6,0xfe,0x31,0x1e,0xbe,0xb8,0x92,0x3b,0xb7,0x54,0xae,0x76, + 0xd0,0x6f,0x7f,0xe9,0x15,0x79,0xf5,0xce,0xad,0x65,0x22,0xf4,0xc6,0xcb,0xb7,0xe5, + 0x1f,0xbf,0xf3,0xa6,0xfe,0xe6,0xd7,0xde,0xd0,0x27,0x17,0x37,0x78,0x76,0x7e,0x65, + 0x48,0x3d,0x31,0x1c,0xff,0x38,0xc8,0xe2,0x24,0x92,0x9e,0x53,0xb,0x60,0xd8,0xa5, + 0x89,0xae,0x4a,0xcb,0x1a,0xbb,0xc8,0x14,0x61,0x6,0x45,0x76,0x86,0x97,0x89,0x64, + 0x58,0xb5,0x29,0xb7,0xb8,0xde,0x7f,0x48,0xcb,0x70,0x71,0x55,0xbb,0x8,0x37,0x71, + 0xae,0x3f,0x58,0x52,0x39,0x3b,0xdf,0x1,0x59,0x3a,0x3c,0xd0,0xaf,0x68,0x54,0x9a, + 0x48,0x2b,0xbb,0xf3,0x30,0x18,0xa3,0xfc,0x83,0x62,0x95,0xf6,0x97,0x90,0xd5,0x69, + 0xa1,0xcc,0x43,0xaa,0x4a,0xfc,0x21,0x6f,0x34,0xf6,0x6b,0x63,0xab,0x6a,0x53,0xb5, + 0xa9,0xb6,0x4,0x34,0x7b,0xcc,0xa1,0x49,0xbd,0x8b,0x89,0x53,0xf4,0xb5,0xaf,0x40, + 0xe5,0xd9,0xc5,0x35,0x7e,0xf0,0xd1,0x93,0xfe,0xe4,0xec,0x1a,0xbf,0xf7,0x8d,0x2f, + 0xb6,0x3f,0xf8,0xf6,0x5b,0xfa,0xab,0x6f,0xbd,0xaa,0x5f,0x7a,0xf5,0x8e,0xdc,0xb9, + 0x75,0xb0,0x8,0x96,0x44,0x44,0x2e,0xaf,0x6f,0xe4,0xec,0xaa,0xcb,0xf3,0xb3,0x4b, + 0x79,0x76,0x76,0x85,0x27,0xa7,0x57,0x72,0x74,0x72,0x29,0x9f,0x9d,0x9c,0xcb,0xfd, + 0xa7,0x67,0x78,0x78,0x72,0x29,0x4f,0x4e,0x2f,0xe5,0xec,0x6a,0x87,0x9b,0x9b,0x2e, + 0x97,0xbb,0x2e,0xd7,0x37,0xbb,0x29,0x12,0xe1,0x3c,0x78,0x7a,0x36,0x74,0x38,0x27, + 0xbc,0x7b,0x88,0xf,0x15,0xba,0xb1,0xf0,0x84,0x5,0x3b,0xa9,0x26,0x3b,0x7f,0xf, + 0x2b,0xb1,0xf6,0xd,0xf1,0x5,0x87,0x87,0x99,0xa8,0x92,0xc5,0x96,0xe0,0x2a,0x4e, + 0xc9,0x8e,0x92,0x18,0xcd,0x21,0xec,0x4,0x5,0x36,0x68,0xb4,0x83,0x49,0xe4,0xa1, + 0x41,0xaf,0x4b,0xa,0x23,0x4d,0x42,0xf,0xf5,0xa2,0x63,0x7,0xc8,0xf7,0x3f,0x7a, + 0x2a,0x3f,0x7a,0xf0,0x1c,0x87,0x7,0x4d,0x2e,0xaf,0x21,0xe7,0xd7,0xd7,0x63,0xec, + 0xdf,0xa8,0xf3,0xf6,0xd5,0xa7,0xc5,0x5a,0x59,0x62,0x79,0x88,0xf5,0xa6,0x40,0xd3, + 0xe6,0x85,0xa2,0x22,0xfa,0x8b,0xa7,0xe7,0x72,0xf3,0xb3,0xcf,0xf0,0xad,0x2f,0xbd, + 0x2a,0xaf,0xdf,0xbd,0xad,0x6f,0xcf,0x3d,0xdc,0x2f,0x13,0xc8,0xed,0xc3,0xe2,0xd6, + 0xee,0xe7,0xe4,0x72,0x27,0xf7,0x8f,0xcf,0xe5,0xe3,0x27,0xa7,0xf8,0xf4,0xd9,0x99, + 0x7c,0xf2,0xec,0x5c,0x3e,0x79,0x7a,0x8e,0xa3,0xd3,0xb,0x39,0x39,0xbb,0x96,0x8b, + 0x5d,0xc7,0xf5,0xae,0xcb,0xe5,0x75,0xf7,0x67,0x62,0x76,0xbf,0xee,0x2e,0x33,0x4d, + 0x75,0x27,0x97,0x8d,0xb,0xac,0x8c,0x27,0x19,0xc9,0x94,0x44,0x1f,0xf3,0x9e,0x6a, + 0x5e,0x4,0xd6,0x2d,0x68,0xe4,0x79,0x39,0x18,0x26,0x9c,0xcf,0xc,0x97,0xe4,0x5a, + 0xce,0x7b,0x3d,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0xfc,0x77,0x26,0xf,0xf2, + 0xc5,0x1e,0x9a,0x14,0xab,0x24,0x15,0x37,0x80,0xfc,0xf5,0x27,0xcf,0xe4,0xf5,0x97, + 0x6f,0xf7,0xff,0xf6,0xdb,0x5f,0x3a,0x78,0xed,0xee,0xa0,0x2f,0xde,0x7b,0x72,0x86, + 0x3f,0xfd,0xd9,0x43,0xf9,0x3f,0x7e,0xf4,0x19,0x4e,0xce,0x6f,0xe4,0xf6,0xe1,0x58, + 0x4d,0xf6,0xe9,0x81,0xbe,0xbe,0xe9,0xb8,0xde,0xd,0xe5,0xfa,0xf5,0xae,0xdb,0x7b, + 0xf,0x32,0x74,0xd8,0x4,0xf,0x14,0xcb,0x4e,0xa3,0xa,0xb8,0xa5,0x58,0x63,0x4c, + 0x1,0xcf,0xf9,0x84,0x5f,0xe2,0xf3,0x4b,0xed,0x2e,0x7c,0x33,0x96,0x50,0xf7,0xf3, + 0x36,0x2e,0xe7,0x2e,0x93,0xcd,0xde,0xe0,0x60,0x18,0x23,0xc0,0x41,0x9a,0x35,0xe9, + 0x30,0x8a,0x5c,0x9f,0x2c,0xf7,0x61,0x4c,0x73,0x5b,0x1a,0x8c,0xda,0xd7,0x27,0xac, + 0xa6,0x3b,0xf1,0xa8,0x31,0x30,0x2b,0xe8,0xcd,0xd0,0xd9,0x6c,0x19,0x8b,0x85,0xb0, + 0xd9,0x1a,0x78,0x4f,0x18,0x2,0x51,0xfd,0x90,0x0,0x7,0x8,0xa2,0xe9,0x20,0xe0, + 0x6d,0x68,0x7b,0xce,0xaf,0x76,0xf2,0xc3,0x7,0xc7,0xf2,0xd1,0xf3,0x33,0xb7,0xc3, + 0x61,0x4c,0x60,0x61,0x81,0xa1,0x31,0x76,0x37,0x42,0x4a,0xb3,0x71,0x7b,0x9f,0xe3, + 0x69,0x47,0xa6,0xc1,0x62,0x31,0x91,0xd5,0x51,0xdd,0x9d,0x93,0x8d,0x88,0xcb,0x73, + 0x6f,0x3d,0xe4,0x56,0xd4,0xa1,0x5b,0xe7,0xe2,0x31,0x5b,0xca,0xe2,0xda,0x4e,0x1f, + 0x95,0x5d,0x9d,0x8f,0x4e,0x2f,0xe5,0x5f,0xff,0xe5,0x3d,0xfc,0xf4,0xe8,0x54,0xff, + 0xc5,0x77,0xbf,0xaa,0xff,0xf5,0xaf,0x7d,0x51,0x5f,0x9b,0xce,0x22,0x7e,0x4f,0x5f, + 0xbe,0xd5,0xe4,0xf,0xbe,0xf5,0x25,0x7d,0x7e,0x7e,0xa3,0x7f,0xf6,0xe1,0xd1,0x14, + 0xb0,0xf9,0x58,0x2f,0x56,0x9e,0x76,0xb8,0x1c,0xcc,0x83,0xb1,0x63,0xda,0xbc,0x6c, + 0x1a,0xaf,0x2e,0x9d,0x0,0xad,0x94,0x35,0xd4,0x83,0xf3,0xb1,0x6d,0x5c,0xf,0x94, + 0x11,0xb6,0x6e,0x2a,0xc2,0x79,0xba,0xa9,0x44,0xf2,0x49,0xe3,0xd8,0x96,0xef,0xdc, + 0xc5,0xfe,0x56,0x66,0x1,0x15,0x13,0xcb,0xbb,0xf9,0x43,0x34,0x52,0x17,0xb3,0xfd, + 0x68,0xd3,0x5b,0xe7,0xba,0x33,0x5f,0xe5,0xf9,0xf,0x39,0x7d,0x5b,0x9a,0xd3,0xc7, + 0xc0,0x22,0x91,0x10,0xb6,0xa8,0xb1,0xf5,0xc7,0xf8,0x45,0x9c,0x6d,0xd5,0x28,0x45, + 0x6b,0xb0,0x97,0xa3,0x3a,0xd6,0xc9,0x5d,0x9e,0xc3,0xb,0x18,0x87,0x76,0x7a,0x29, + 0xed,0x2,0x3b,0xbe,0xdc,0xc9,0xdf,0x7d,0xfa,0x54,0x8e,0xaf,0x6e,0xfa,0xe3,0xd3, + 0x4b,0xfd,0xca,0x1b,0x77,0xf5,0x8d,0xbb,0xb7,0xe5,0xe5,0xdb,0x4d,0x6f,0xcd,0x4e, + 0xbd,0xcf,0xad,0xd8,0x4d,0x1f,0x4c,0xf7,0xf3,0xeb,0x1b,0x39,0xbb,0xda,0xe1,0xc5, + 0xc5,0xb5,0x1c,0x5f,0x5c,0xcb,0xb3,0xf3,0x6b,0x79,0xf2,0xe2,0x2,0x47,0x27,0x57, + 0xf2,0xfc,0xe2,0x26,0x80,0x52,0x49,0xb9,0x36,0xa1,0xbf,0x3e,0x4e,0x77,0xa4,0xc5, + 0xd4,0x15,0x91,0x60,0x47,0xe9,0xf2,0x94,0x24,0x3d,0x46,0xb5,0x34,0x50,0x77,0x6c, + 0x80,0xce,0xac,0x8c,0x17,0xd2,0x4d,0x90,0x1a,0x16,0xa0,0x87,0xb8,0xa4,0x90,0xc6, + 0x2c,0x33,0x7c,0xef,0x3d,0x24,0xf,0x66,0xad,0x80,0x8d,0x86,0xe0,0x49,0x1e,0x91, + 0x77,0x1b,0xb6,0xa,0xa5,0xd,0x51,0xc4,0x3a,0xf7,0x79,0xa4,0xc1,0x9c,0x57,0x6, + 0x5d,0x84,0xca,0xe9,0xcd,0x4e,0x4e,0xaf,0x77,0x1,0xcb,0x30,0x63,0x2c,0x39,0x73, + 0x10,0xd6,0x8d,0x71,0x4,0xb7,0xf4,0xe1,0x84,0x86,0x42,0x12,0x59,0x1e,0x22,0x90, + 0x4f,0x9e,0x5f,0xca,0x1f,0xbd,0xf7,0x99,0x3c,0xbf,0xb8,0x92,0xdf,0xfa,0x95,0x37, + 0xe4,0x9d,0x37,0x5f,0xd1,0x2f,0xdc,0xbd,0x25,0xaf,0xdd,0xbd,0xc5,0xf1,0x0,0x4b, + 0xd7,0x7e,0x79,0x7d,0x23,0x17,0xd7,0x5d,0xce,0xaf,0x6f,0xe4,0xf2,0x6,0x72,0x7e, + 0x7d,0x23,0xe7,0x57,0x37,0x72,0x7e,0xbd,0xc3,0xd9,0xe5,0x4e,0x8e,0x2f,0xae,0xe5, + 0xc9,0xd9,0x95,0x1c,0x9d,0x5c,0xe2,0xe8,0x74,0x30,0xf8,0x8f,0x5e,0x5c,0xc8,0xa3, + 0x17,0x97,0xb8,0xe9,0x6c,0x69,0x56,0xb7,0xd9,0x25,0x62,0x58,0xc4,0x72,0x91,0xb, + 0xc5,0x28,0x66,0xd6,0xb,0x9,0xcc,0xfc,0x3d,0xa7,0xf0,0x7e,0x59,0xd,0x90,0xff, + 0xe8,0xcc,0xbb,0xad,0xc3,0xed,0xa1,0xf1,0xf1,0x72,0xec,0x26,0xe7,0x41,0xc9,0x60, + 0x5e,0xfb,0x58,0x43,0xde,0x64,0x7,0xb2,0x72,0x76,0x26,0x88,0xda,0x18,0x27,0xcf, + 0xe5,0xe,0xf2,0xde,0xc3,0x13,0xf9,0xa3,0xf7,0x3e,0xeb,0xbf,0xf3,0xab,0x5f,0xd0, + 0xbb,0xb7,0xe,0xe4,0xcf,0xde,0x3f,0xc2,0x1f,0xff,0xf4,0x8,0x3f,0x79,0xf4,0x62, + 0xa3,0xb4,0x27,0x18,0x56,0x28,0xf2,0xfc,0xa2,0x2e,0x2a,0x60,0xc4,0x54,0x8e,0x1c, + 0x40,0xf6,0x8e,0x34,0x18,0xa7,0xb,0x25,0x24,0xd7,0x86,0x8,0xb0,0x2d,0xf7,0x78, + 0xf7,0xfa,0xbc,0xb0,0xc9,0x77,0x8e,0x18,0x27,0xcf,0x7c,0x2d,0x1e,0x9b,0xa3,0x2b, + 0x59,0xd6,0xec,0xf7,0x19,0x60,0x70,0xaa,0x31,0xbb,0x34,0x78,0xd,0x9,0xdb,0x85, + 0xcc,0xaf,0xa7,0x95,0x35,0x2b,0x6c,0xd,0x38,0xc4,0xd2,0x23,0xba,0x9b,0x2a,0x26, + 0x6d,0x30,0x7,0x35,0x7c,0x22,0xa3,0x98,0x45,0x2a,0xaf,0x1d,0x11,0x99,0x1d,0xa, + 0x69,0x2a,0x5d,0x55,0x9e,0x5f,0x5c,0xe3,0xd9,0xe9,0x95,0xbe,0xf6,0xd2,0xa1,0xf0, + 0x46,0xe9,0xec,0x7a,0x27,0x3f,0x7c,0x78,0x82,0x8f,0x9e,0x5f,0xb8,0x5d,0x4d,0xd5, + 0x74,0x17,0xe3,0xbf,0x33,0x6d,0xe9,0x90,0x71,0x95,0x99,0x23,0xbb,0xcf,0xc7,0x11, + 0xa2,0xda,0xa5,0xcf,0x22,0x33,0xdd,0xbd,0xe3,0xc4,0x37,0x94,0xa7,0xcd,0xe8,0x89, + 0x24,0xe2,0x17,0xf8,0x8c,0x35,0x6b,0xb6,0x1a,0xad,0xcc,0x89,0x34,0x99,0x34,0xd5, + 0x7b,0x6c,0xe2,0xb5,0x8b,0xe0,0xf9,0xd5,0x8d,0xfe,0xf9,0xbd,0xa7,0x80,0xaa,0x9c, + 0x5d,0x77,0xf9,0x9d,0x77,0xde,0xd0,0x5f,0x9b,0x41,0x34,0xf6,0x90,0xdc,0xbd,0x7d, + 0x28,0xff,0xf9,0xd7,0xde,0xd0,0x1f,0x7f,0x76,0xac,0x7f,0x76,0xcf,0xce,0xa,0xb5, + 0xbb,0x17,0xd3,0xec,0xed,0x2,0x39,0x5b,0x70,0x60,0xa6,0xde,0x41,0xe3,0x22,0x4, + 0x81,0xac,0x24,0x96,0xea,0x69,0xc7,0xc0,0x77,0xb0,0xeb,0x0,0x1a,0x13,0xf4,0x2, + 0xde,0x84,0xd2,0xf9,0x5a,0xd7,0xae,0x34,0xf5,0x16,0x4b,0x58,0x9b,0xc3,0x83,0xad, + 0xb8,0x33,0x4e,0xa1,0xe7,0xc,0x15,0xad,0xea,0xf8,0xd9,0x4,0x1d,0x9a,0xe8,0xca, + 0xe6,0xf6,0x4,0x68,0x20,0x59,0x7d,0x2c,0xf4,0xdd,0x4f,0xa7,0x34,0x86,0xd7,0x52, + 0x3d,0xb0,0xb6,0xbe,0x74,0xa2,0xb1,0x47,0x48,0xf9,0xb3,0x10,0xd,0xe5,0xa4,0x78, + 0x30,0x81,0x9a,0x2f,0x82,0x46,0x54,0xf3,0xe1,0x17,0x41,0xb7,0xc6,0xcd,0xc1,0x56, + 0x2d,0x9,0xf7,0x76,0xad,0xc9,0x87,0x4f,0x4e,0xf1,0xe1,0x93,0xd3,0x4a,0xbd,0x8f, + 0x3a,0x7,0xee,0xc1,0xe2,0x51,0x5,0xd,0xcf,0x50,0xba,0x9a,0x10,0x7f,0x69,0xce, + 0xa7,0xa4,0xa4,0x10,0xe5,0xc,0x46,0x9,0xd7,0x7,0xc3,0xbe,0x62,0xd2,0x89,0xb0, + 0xe,0x95,0xe9,0x88,0x10,0x8b,0x3a,0xfe,0x11,0x21,0x98,0xa2,0x75,0x97,0x19,0x18, + 0x98,0xb2,0x36,0x52,0x72,0xc7,0xe8,0xc0,0x35,0x4e,0xff,0xac,0xfb,0x50,0xee,0x61, + 0x1d,0x46,0xe1,0xa,0x68,0x90,0x30,0x4d,0xd2,0xbf,0xe7,0xcb,0x4c,0x5b,0x4,0xf4, + 0xd1,0x1,0xa9,0x26,0x81,0x7,0xe9,0x3c,0x38,0x4c,0x99,0x1e,0x52,0xe4,0x22,0x6, + 0x3e,0xb1,0x48,0x9d,0x25,0x31,0xde,0x59,0x22,0x2a,0x2a,0x5d,0xa0,0xff,0xe1,0xde, + 0x63,0xbc,0xfb,0xe0,0x39,0xbe,0xfb,0xd5,0xd7,0xf5,0xf7,0xbf,0xf1,0x45,0xf9,0xdd, + 0xaf,0xbf,0x29,0xdf,0xf8,0xe2,0xab,0xfa,0xe6,0xdd,0x43,0xb9,0x73,0x2b,0x23,0x5b, + 0xaf,0xae,0x6f,0xe4,0xf4,0x6a,0x27,0x8f,0xed,0xb2,0x7e,0x71,0x29,0x8f,0x4e,0x2e, + 0xe4,0xe8,0xec,0x4a,0x8e,0x5e,0x5c,0xe0,0xd1,0x8b,0x2b,0xf9,0xe4,0xd9,0xb9,0x3c, + 0x3f,0xbb,0x32,0x55,0x3a,0x5b,0x44,0x6c,0xf2,0x62,0x25,0x4d,0x82,0x8a,0xd8,0xcf, + 0x6d,0xee,0xa5,0xa7,0x13,0x18,0x1e,0xaf,0x89,0xf8,0x11,0xd1,0xe4,0xe,0xb4,0x4f, + 0x75,0x5e,0x15,0x4c,0x0,0xe7,0xb3,0x43,0xf3,0x9,0x23,0xeb,0x10,0x91,0xa9,0x62, + 0x42,0x9c,0x46,0xed,0x71,0xdc,0xe8,0xc0,0xa7,0x8d,0x9f,0x5c,0x97,0xd6,0x75,0x2a, + 0xbd,0xdc,0x2a,0x45,0x70,0xa7,0x3e,0x2f,0xa3,0xfb,0x27,0x17,0xf2,0x3f,0x7d,0xef, + 0x5e,0xff,0xd1,0xc3,0x13,0x7d,0xe7,0x8d,0xbb,0xfa,0xef,0x3e,0x38,0xea,0x3f,0x7b, + 0xf8,0x42,0x52,0xf0,0x7a,0x61,0xe3,0x77,0x49,0x8,0x4a,0x27,0xb9,0xf5,0xd8,0x1, + 0x40,0xe7,0x74,0xd3,0x7,0x8f,0x4,0x5c,0x8a,0x4b,0x65,0xfe,0xb5,0xbd,0x66,0xee, + 0x35,0x57,0x74,0x58,0x3d,0x3d,0x8b,0x9d,0x31,0xc4,0x45,0x8c,0xdd,0x2d,0x96,0x7c, + 0x6a,0x12,0xd4,0x7,0xf5,0x2e,0x6c,0x13,0x83,0xc2,0x4c,0xfb,0x89,0x17,0xd,0xd, + 0x8e,0x79,0x9d,0x20,0xdc,0xe9,0xe3,0xa6,0x55,0x9a,0xdb,0xf,0x72,0x75,0xeb,0xb2, + 0x74,0x22,0x29,0x7a,0x43,0x22,0x92,0x71,0xd6,0x2e,0xf6,0xb4,0x73,0xc0,0x83,0x3d, + 0xd,0xac,0xe1,0xdd,0x12,0x54,0xe4,0xe3,0xe7,0xe7,0xf8,0xf0,0xd9,0x29,0xbe,0xf3, + 0xf6,0xeb,0x7a,0x87,0x38,0xf9,0xcf,0x2e,0xae,0xf1,0xf3,0xa3,0x17,0x38,0xbe,0xda, + 0x41,0x4c,0xee,0x65,0xa3,0x6e,0x4e,0x1d,0xf1,0xae,0x5c,0x30,0x1b,0x6e,0x2b,0x24, + 0x7a,0x8c,0xe0,0xe7,0xf3,0xe5,0xef,0x57,0x3,0xe2,0xd9,0xb0,0xd9,0x81,0x8a,0x3f, + 0x5b,0x33,0x9a,0x74,0x6,0x96,0x76,0xd5,0x3e,0xcd,0x51,0xde,0xa1,0xab,0xb4,0xe6, + 0x9c,0xf2,0x58,0x25,0x44,0x52,0xa2,0x72,0x44,0x1d,0xf0,0xec,0xf2,0x5a,0xfe,0xcf, + 0x9f,0x3c,0x94,0xfb,0x27,0x17,0xf2,0xe8,0xc5,0xa5,0xfc,0xcb,0xff,0xe2,0x1d,0xfd, + 0x22,0x41,0xa3,0xee,0x1c,0x36,0xf9,0xd5,0x37,0x5f,0xd2,0xb7,0x5f,0x7b,0x69,0x3c, + 0x87,0xcd,0xc4,0xa,0xd3,0x1a,0x7c,0x80,0xc8,0xc4,0xa3,0x33,0x75,0x60,0x83,0xe6, + 0x3e,0x82,0x76,0xc7,0x48,0xff,0x1b,0x63,0x6d,0xbb,0xff,0xac,0xb2,0x8c,0x14,0x2a, + 0x13,0x6b,0x43,0x18,0xda,0xb4,0x34,0xc3,0x2c,0x5e,0x4b,0x2f,0xa8,0xa6,0xbc,0xb6, + 0x3c,0x56,0x47,0xe9,0xd0,0x4b,0xe7,0xcf,0x3a,0x47,0x52,0xac,0x1f,0x4e,0xbd,0xc0, + 0xd8,0x43,0x7b,0xd5,0x20,0xce,0xd7,0x6,0x99,0xa5,0xdd,0xf5,0x42,0xf9,0xd7,0x9a, + 0xc6,0xa,0x9a,0x95,0x53,0x9c,0xa2,0x45,0x2,0x6a,0x34,0xa3,0xba,0xf1,0xfe,0x7d, + 0xac,0xc3,0xc7,0xd8,0x70,0xa6,0x37,0x2a,0x65,0x69,0xcd,0x46,0x75,0xa0,0x8e,0xe7, + 0xc5,0x9e,0x32,0x8d,0x5b,0xae,0x23,0xe,0x82,0x9,0xb0,0x84,0x88,0x6b,0xdc,0x1c, + 0x50,0xde,0xd7,0xc5,0x94,0x18,0x24,0xd9,0xe7,0xea,0x32,0xd6,0x50,0x74,0x12,0x1b, + 0xa2,0x33,0xfc,0x2e,0x74,0xb6,0x23,0x79,0x54,0x61,0x4a,0x23,0xb5,0xaa,0xc,0x29, + 0x1d,0xc,0x19,0x7,0xec,0x3,0xee,0x40,0x35,0x6a,0x28,0x91,0x79,0x1a,0x19,0x8e, + 0x6,0x63,0xfb,0x82,0xad,0x6f,0x76,0x58,0x74,0x95,0x44,0xd6,0x12,0xfe,0x98,0xd2, + 0x1e,0x33,0x1c,0xa,0xa8,0xb0,0xa0,0x99,0x19,0x2e,0x60,0xb7,0x48,0x7c,0x8d,0x38, + 0x50,0x8d,0x7c,0x72,0x89,0x11,0x63,0x50,0x2c,0xa6,0x67,0xd,0x2b,0xd0,0x20,0x79, + 0xb1,0xd5,0xa2,0x43,0x92,0xe0,0x92,0x7,0xd8,0x34,0x1c,0xf0,0x7a,0xed,0xe4,0xaa, + 0xcb,0xf,0x3f,0x3b,0xc1,0xd1,0xd9,0xb5,0x7e,0xef,0xa3,0x67,0xfa,0xda,0x4b,0x87, + 0x78,0xe9,0xd6,0x81,0xe5,0xfb,0xf9,0x7f,0x67,0x8,0x6,0xbb,0x5c,0xdc,0x74,0x39, + 0xbf,0xda,0xc9,0xf9,0xf5,0x4e,0x2e,0x6f,0x76,0x38,0xbf,0xde,0xf9,0x5f,0x9f,0x5d, + 0x77,0xe9,0xe8,0x8,0x0,0x13,0x82,0x5d,0x2d,0x2d,0x5c,0x4c,0xda,0x62,0xbf,0x3b, + 0x2a,0x71,0x70,0xa7,0xda,0x3d,0x99,0x4a,0x13,0x24,0x46,0x4d,0x81,0x6e,0x3e,0xe8, + 0x2e,0x90,0x66,0x6a,0xe9,0x18,0x95,0xaa,0xcc,0xce,0x3d,0x26,0x44,0x88,0x1f,0x5d, + 0x9,0x91,0xf7,0x2a,0x5e,0xa7,0x34,0x9b,0x5e,0xcc,0x31,0xe1,0xe8,0x83,0x8b,0x35, + 0x96,0x9f,0x68,0x43,0x1f,0x6e,0x12,0xee,0xc4,0x8d,0x9f,0xef,0xc7,0x55,0x17,0x79, + 0x70,0x7a,0x89,0xeb,0x7b,0x4f,0xf5,0x47,0x2f,0x9d,0xc8,0xc3,0x93,0xb,0xb9,0xa6, + 0x0,0x8f,0x82,0xa,0x93,0x94,0xaf,0x2d,0x69,0x3d,0x13,0x5,0x51,0x1b,0x3e,0xb0, + 0xf1,0xf6,0x4c,0xd5,0x9a,0xa,0xf9,0xc9,0x1d,0x41,0x19,0xe3,0xb0,0x18,0x1d,0xb, + 0x20,0xe8,0x4d,0xc7,0x32,0xc2,0xc0,0x55,0xc1,0xc4,0x83,0x7d,0x78,0x43,0x85,0x38, + 0x47,0xee,0x16,0xb2,0xd2,0x42,0xe4,0x66,0xd3,0xbf,0x1e,0x9b,0x28,0xf8,0x1a,0x53, + 0x7d,0x91,0x3e,0xff,0x3d,0xf5,0xb3,0x7d,0x52,0x4d,0x10,0xcd,0x4d,0xf4,0x53,0xa0, + 0x6c,0x73,0x1b,0xa3,0xcf,0x14,0x42,0x43,0x9b,0x8c,0x1d,0x7e,0x13,0xff,0xd9,0x7, + 0x7e,0x75,0xe6,0x2b,0x33,0x18,0x67,0xbe,0xc0,0x5d,0x5,0x7f,0x7b,0xff,0x18,0x6f, + 0xbf,0xf6,0x12,0xbe,0xf3,0xf6,0xeb,0xde,0x4e,0x1c,0x5f,0xdc,0xc8,0x87,0x4f,0x4e, + 0x71,0x7c,0xb5,0xf3,0x71,0x7b,0x38,0x2,0x42,0xc,0x17,0xfe,0xfa,0xf1,0x35,0xc0, + 0x42,0x69,0x46,0xfd,0x5,0x40,0xbb,0x9,0xe4,0x78,0x18,0x88,0xc4,0xcc,0xb0,0xca, + 0xca,0x72,0x58,0x28,0xc,0xbb,0xe9,0x4c,0x1b,0x1f,0xa,0xe6,0x3e,0x1e,0x43,0x7b, + 0x39,0xba,0x85,0x76,0xf8,0xb5,0xa8,0xcd,0x0,0x0,0x62,0x71,0x80,0x2d,0x87,0x54, + 0xe3,0xbd,0xa3,0x53,0xb9,0xc1,0x67,0x38,0xbb,0xe9,0xfa,0x87,0xdf,0x7e,0x4b,0x7f, + 0x87,0xc4,0x99,0x2f,0xdd,0x3a,0x94,0x57,0x5e,0xba,0xa5,0xbe,0x3a,0x3e,0xc8,0xc5, + 0xe5,0xcc,0x60,0x9b,0xdc,0x77,0x6a,0x3c,0xe7,0xf8,0x5d,0xf,0x62,0x1c,0xa3,0x63, + 0x34,0x11,0x78,0xd7,0xb4,0x3f,0x57,0x91,0x83,0x9e,0x4e,0x47,0x69,0x94,0xe6,0xa8, + 0xf1,0xf5,0xc7,0x2b,0x99,0xe,0xdf,0xd4,0x7e,0x24,0xb5,0xfa,0x96,0x2d,0x76,0xab, + 0x30,0x90,0x2,0xf0,0xa2,0x26,0xd9,0x1a,0xae,0x43,0x34,0x15,0xa8,0x2e,0x87,0x62, + 0x47,0xa8,0xe9,0x7d,0xc6,0xbf,0xe1,0x97,0x86,0x66,0x7a,0x4d,0x1a,0x1b,0x4c,0x82, + 0x8d,0x68,0x2c,0xc5,0x94,0x2c,0x67,0x69,0x37,0x3f,0xba,0x41,0xe8,0x30,0x44,0xfb, + 0x48,0x6a,0x8c,0xa2,0x1a,0x72,0xaa,0xa9,0xda,0x88,0xd2,0x8c,0xd2,0x88,0x3f,0x17, + 0x36,0xa6,0x95,0x36,0x84,0x75,0x6,0xc5,0x1c,0x14,0x21,0x9,0xf5,0x22,0x43,0xec, + 0x4b,0xf2,0x36,0xdd,0x1d,0x52,0xe9,0x1c,0x48,0x8a,0x6b,0xab,0xc6,0x1b,0xe3,0xe2, + 0x8c,0x4e,0x35,0x2f,0x5e,0x7,0x5,0xcd,0x19,0x61,0xb,0xa1,0x49,0x74,0x99,0xab, + 0x38,0xc1,0x46,0xa6,0x8,0x5,0xb4,0x22,0x45,0xe1,0x85,0xc,0x1d,0x9a,0xf6,0x38, + 0xa,0x6,0x53,0x34,0x2,0x3d,0xf2,0x24,0x85,0x32,0x80,0x81,0x84,0x30,0x44,0x59, + 0xb0,0x83,0x73,0x37,0x6d,0x79,0x1b,0xc9,0x78,0x91,0x28,0x38,0x5f,0x72,0xda,0x89, + 0xf9,0xe5,0x3e,0xd1,0xe0,0x14,0x41,0x4,0x75,0xb6,0x14,0xd8,0x2b,0x69,0xd9,0xd1, + 0xcd,0x5e,0x87,0xa0,0xb,0x22,0xf4,0x5d,0xea,0x15,0x83,0x86,0x4f,0xc4,0x7e,0x75, + 0x72,0xbd,0x93,0x17,0x4f,0x4e,0xe5,0xfd,0x27,0xa7,0x58,0x24,0xa9,0xa8,0xf8,0xc4, + 0xa2,0xd3,0xa7,0x87,0xc6,0x3,0x86,0xe0,0xdf,0x35,0x15,0x17,0x5a,0xd1,0x98,0xa9, + 0xa3,0x1c,0x2d,0x30,0xd0,0x99,0x6,0x8a,0xd8,0x8f,0xbb,0x4a,0xba,0x9b,0x20,0x5b, + 0x21,0x7,0xb3,0x50,0xb1,0x0,0x90,0x39,0x52,0xee,0x2a,0xe5,0x90,0x1d,0xcf,0xbf, + 0x15,0xf,0x48,0x9f,0x40,0x74,0x52,0xa3,0x4b,0x1c,0xdf,0x89,0x31,0xad,0x47,0xca, + 0x4d,0x13,0x51,0xe9,0x7d,0xe0,0x37,0xda,0x54,0x94,0xf5,0x9,0x3f,0x97,0x88,0x69, + 0x9b,0x5,0x42,0x53,0xd9,0x89,0xc8,0xa3,0xf3,0x4b,0x3c,0x3a,0xbf,0x22,0x9f,0x31, + 0xdb,0xc2,0xcb,0xce,0x4f,0xa9,0x50,0x84,0xaf,0xe6,0x49,0x32,0x32,0x6f,0x7,0x65, + 0xd3,0x4,0x67,0x8e,0x4e,0x78,0x17,0x38,0x3c,0x44,0x1,0x5a,0xb3,0xdb,0xe7,0x10, + 0x47,0x8c,0x84,0xbf,0x3a,0xbc,0x42,0xa0,0xb0,0x72,0xf,0x5b,0x99,0xcc,0x74,0x98, + 0x6a,0x6e,0xee,0x13,0x1,0xe9,0x18,0x25,0x8f,0x4a,0x6f,0x26,0x50,0x74,0x8b,0xac, + 0x7f,0x7d,0x36,0xf0,0x4f,0x17,0x45,0x64,0xe,0x0,0x2d,0x44,0x4c,0xdd,0xc3,0x58, + 0x8c,0x63,0x62,0x56,0x35,0xe2,0x7c,0xb7,0x39,0x2a,0xb4,0x95,0xcd,0x18,0xc3,0x4f, + 0x7d,0xd0,0xf8,0xc,0x77,0xa2,0xfa,0xd3,0x27,0xa7,0x78,0xeb,0xd3,0xe7,0xf8,0xc3, + 0x6f,0x9f,0xe1,0x1f,0x7d,0xe9,0x55,0xbd,0xba,0xe9,0xf2,0xde,0xa3,0x63,0xfc,0xe8, + 0xe1,0x9,0x2e,0xcc,0x5f,0xef,0x92,0xef,0x98,0x42,0xf8,0x7b,0x6e,0x53,0x67,0xe9, + 0x7d,0x7e,0xc0,0xe3,0x32,0x1f,0xb9,0xe1,0x20,0xb8,0xdb,0x9c,0x66,0x44,0x8c,0x9c, + 0x28,0xaf,0x53,0x4d,0x74,0x3e,0x76,0x1c,0xf3,0x63,0xef,0xfe,0xd,0xda,0xc8,0x54, + 0xfd,0x63,0x68,0x59,0x2f,0x44,0x20,0x2b,0x7b,0x32,0x41,0xcf,0xee,0xfc,0x39,0x5f, + 0x76,0xc8,0xf,0x1f,0xbd,0x90,0x67,0x97,0x37,0x72,0xdd,0xbb,0xbc,0x7e,0xe7,0x50, + 0x7e,0xe5,0xf5,0xbb,0x7a,0xe7,0xb0,0xc5,0x11,0xd5,0x1a,0xc,0x35,0xe0,0x9f,0x2f, + 0xba,0xe0,0x40,0x45,0xfa,0xfc,0x5f,0x90,0x90,0xd0,0x76,0x60,0xb6,0x3b,0x9f,0x76, + 0x5,0x1b,0x1d,0x32,0x7e,0xd5,0x2f,0x3f,0x34,0xbf,0x5b,0xec,0xec,0xe9,0x34,0xa4, + 0xee,0x4,0xbe,0x4e,0xce,0xae,0xe5,0xa2,0xde,0xd8,0x8c,0x6b,0xc4,0x8c,0x2b,0xb2, + 0xbf,0x1c,0xfc,0x3b,0x35,0x23,0x64,0x6d,0xef,0x6a,0xff,0xeb,0x2a,0xf7,0xe4,0x21, + 0x2f,0xf8,0xb9,0x74,0x0,0x2e,0x58,0x38,0x95,0x9a,0x1,0xe5,0x5f,0x5c,0xf5,0xac, + 0xda,0x5b,0x6d,0xb8,0x47,0x16,0x87,0x59,0x5b,0xae,0x53,0x1c,0xd7,0xcc,0x56,0x31, + 0xf6,0x87,0xd3,0x69,0x63,0x33,0xb7,0x18,0xbf,0x8f,0x53,0xa5,0x8f,0xd8,0x37,0x61, + 0xaf,0xaa,0xf1,0x72,0x21,0xcd,0xc4,0x64,0x7c,0xd8,0x8d,0xb,0x5e,0x69,0x7f,0x43, + 0xb3,0xcb,0x74,0xde,0x43,0x9,0x2c,0xa9,0x60,0xeb,0x2,0x54,0x4d,0x2e,0x63,0xdd, + 0x43,0x4e,0xc1,0x32,0x21,0x13,0xd2,0x84,0xa5,0x8,0x99,0xd8,0x6b,0x18,0xdc,0xee, + 0x18,0x98,0x9b,0xca,0x2d,0xa2,0x41,0x59,0x5f,0xa1,0x28,0x21,0x8,0x3e,0xf2,0x6b, + 0xf9,0x12,0xb3,0xdd,0x2e,0x81,0x10,0x78,0x1,0x44,0x44,0xd5,0xc8,0x56,0x42,0x75, + 0xa7,0x8d,0xb1,0x28,0x9d,0xd0,0xee,0x88,0x92,0xf9,0x79,0x62,0x1a,0xdb,0x23,0xc7, + 0x40,0x9,0xa2,0xa8,0xf6,0x35,0x4e,0xc1,0x2f,0x89,0x4f,0xe7,0x21,0xae,0xc1,0x19, + 0xc8,0xd3,0x8e,0x6e,0xab,0x6f,0x18,0x94,0x83,0x67,0x98,0x6d,0x8a,0x5a,0x79,0x7, + 0x4f,0x42,0x7e,0x90,0x18,0xae,0x49,0x7a,0xb0,0x5d,0xb4,0xe6,0xf0,0x12,0x56,0x93, + 0xda,0x17,0xdd,0x91,0xba,0xcf,0x90,0x8c,0xba,0x34,0x1,0xfe,0xc2,0xb5,0xe8,0xbc, + 0xad,0xa6,0xb4,0x54,0xf7,0xd9,0xf0,0x91,0x2b,0x62,0xec,0x3b,0x69,0xfd,0x37,0x26, + 0x18,0x76,0x59,0x35,0xc,0xf2,0x28,0x8f,0x93,0x7d,0xcd,0x3,0xf7,0x6e,0xc5,0xf3, + 0x64,0x45,0xed,0x5c,0x17,0x9a,0x1a,0xb,0x30,0x33,0x8d,0x34,0xd7,0x56,0x36,0x19, + 0x9c,0x8d,0xae,0x7,0xd2,0xfc,0x5d,0xb2,0x97,0xcd,0x33,0x3f,0xd9,0xa2,0xaa,0x8b, + 0x17,0xd7,0x5a,0xd1,0xee,0xda,0x4,0x45,0xda,0x27,0xfa,0xd0,0xab,0x89,0xf4,0x18, + 0x7e,0x75,0xf3,0x71,0xab,0xb0,0x81,0x9d,0xe9,0x46,0x43,0x71,0xd9,0x3c,0x9b,0xdc, + 0x27,0xa6,0x1e,0x77,0x1a,0xe5,0x17,0x40,0x97,0xb7,0x8f,0x94,0x63,0x6a,0x3a,0xbf, + 0xa5,0xf9,0x99,0xdb,0xf0,0x62,0x2c,0x96,0x47,0xd3,0x0,0xc7,0xb9,0x8a,0x1c,0xcc, + 0xbf,0x6a,0x10,0xe9,0xd,0x16,0x58,0x32,0x2,0xba,0x8,0xd9,0xc1,0x53,0x49,0xb2, + 0x67,0x93,0xbe,0xc5,0x38,0x19,0x6,0xd5,0x1a,0x2c,0xf8,0x46,0xf6,0xb0,0x26,0xbe, + 0xe3,0x96,0x83,0x81,0x16,0x97,0x3,0x16,0x82,0xab,0x23,0xde,0xbb,0xa8,0x9c,0xed, + 0xba,0xfc,0xe8,0xe8,0x45,0xff,0x37,0x3f,0x7c,0x20,0xff,0xf4,0xdb,0x6f,0xb5,0xaf, + 0xbf,0x7e,0x57,0xbe,0xff,0xc9,0xf3,0xfe,0x97,0x9f,0x3e,0xc7,0x55,0x7,0xc6,0x99, + 0x3e,0x31,0x6e,0xb1,0xa6,0x1,0xac,0xb,0xf,0xe6,0x8a,0x15,0x2b,0x43,0x14,0x37, + 0x74,0x48,0x9d,0xce,0x2c,0x47,0xc3,0x52,0x40,0xaf,0x78,0x2c,0xaf,0x8f,0xcb,0x9b, + 0x5,0x4a,0xab,0xea,0xf4,0xa2,0x53,0x48,0x47,0x1f,0xf6,0xfb,0x26,0x86,0x29,0x6f, + 0xda,0x38,0x40,0x8,0x29,0x81,0xb4,0x44,0x48,0xcf,0x47,0x58,0x44,0xe5,0xfe,0xe9, + 0x15,0xfe,0xed,0x7b,0xf,0xf5,0xde,0xf3,0x73,0xfd,0x57,0xbf,0xfb,0xf5,0xf6,0x5f, + 0x7d,0xfd,0xb,0x7a,0x71,0xb3,0x93,0x93,0xab,0xdd,0x8,0x90,0xe9,0x3c,0xda,0x76, + 0x70,0x3d,0x70,0xd0,0xe6,0xe1,0xdd,0x21,0xb1,0x8e,0x89,0xe,0x5e,0x3,0x23,0x34, + 0x84,0xf,0x88,0x77,0x29,0x92,0x1a,0x25,0xc1,0xed,0xdb,0x76,0x4a,0xda,0x36,0x54, + 0x86,0x9,0x98,0x34,0xc5,0x29,0x7f,0xdf,0x1c,0x5b,0xe1,0xe6,0x59,0xa9,0x63,0x5d, + 0x3,0x83,0xdd,0xb3,0x44,0x6d,0xc4,0xa7,0x8e,0x51,0x45,0xb4,0xf,0xf0,0x6c,0xea, + 0xea,0x89,0x96,0x1c,0x2d,0x2f,0x6c,0x21,0x6a,0xb,0x84,0xc6,0xc3,0xb,0x53,0x5a, + 0xf6,0xfc,0xb1,0x7b,0x7,0x6b,0x52,0x9d,0x16,0x7e,0xec,0xd9,0xa1,0x8b,0xcd,0x64, + 0x9b,0x6,0xf8,0x41,0xb5,0x2b,0xa4,0xa1,0xb5,0x79,0xc1,0x4b,0x17,0xd5,0xc6,0x97, + 0x6b,0x86,0x18,0x20,0xf6,0x33,0xf0,0xb5,0x88,0xa6,0x11,0x60,0xf2,0x57,0xcf,0xf, + 0xb6,0x69,0x41,0xee,0x21,0x26,0x2f,0x62,0xab,0x8,0xcc,0xcb,0xbc,0x23,0x44,0x50, + 0xea,0x69,0x4f,0xc1,0x98,0xb0,0x9d,0xe1,0xd8,0xf1,0x99,0x90,0x5b,0xc9,0xde,0xf, + 0xcd,0x3d,0xe2,0x4c,0xd3,0x20,0x26,0xa3,0x5a,0xb2,0xf,0xf,0xb1,0xcd,0x89,0x11, + 0xa5,0xec,0xb0,0xb7,0x81,0xf6,0x76,0x1c,0xce,0xe5,0x62,0x27,0xa4,0x12,0x3b,0x75, + 0x27,0x11,0xa5,0xcd,0xa2,0x73,0x76,0x31,0xd8,0xd,0x4f,0xc5,0x82,0x5d,0xd0,0x4d, + 0x9c,0x6e,0xa5,0xe9,0xdb,0xb1,0xdf,0xa1,0x8d,0xc6,0x11,0x4a,0x5b,0x19,0x57,0x33, + 0x4f,0x1d,0xc0,0xec,0x6a,0xa2,0x91,0x77,0x8c,0x5d,0xfa,0xf3,0x69,0x91,0x3,0x13, + 0xe0,0x45,0x21,0x33,0xa,0xee,0x8d,0x7d,0x95,0x7a,0x65,0xa3,0x2e,0xc5,0x5,0xea, + 0x74,0xab,0xec,0xaf,0x32,0xa8,0x1,0x5c,0x27,0x61,0xe,0x4a,0x7c,0xec,0xe1,0xdd, + 0x50,0x8c,0x7b,0xa3,0x3b,0x32,0xc5,0x9b,0xd7,0xa,0x73,0xf4,0xc9,0xf8,0x66,0xb8, + 0xa5,0xa,0x2,0xca,0xde,0x6,0x76,0xdc,0xc0,0x78,0x11,0xa9,0xe1,0x31,0xa5,0x50, + 0xf4,0x71,0x98,0xaa,0x11,0xc6,0xc6,0x1d,0x3a,0x84,0xbd,0x6d,0x64,0xb1,0x4c,0x7b, + 0xf4,0x81,0x4a,0x17,0xe9,0xd,0x73,0xd4,0x15,0x99,0x1a,0xc,0xaf,0x70,0x37,0x43, + 0x19,0x2e,0x47,0x3c,0x57,0x6b,0xec,0x8c,0xc,0x65,0xfb,0xd0,0xe8,0x8c,0x1f,0xfb, + 0x41,0xa3,0xd6,0x1a,0xd9,0xc6,0xe9,0xa6,0x8,0xd,0xdd,0x27,0xe5,0xbe,0x77,0xef, + 0xad,0xfc,0x19,0xf,0x9b,0xd9,0xec,0x9c,0x15,0x9a,0x48,0x6f,0xfe,0xf9,0x4,0x80, + 0xcb,0x3b,0x4f,0x2b,0x58,0xe7,0xc4,0xc,0x44,0xa5,0x41,0x60,0xc9,0x15,0x38,0x10, + 0x2b,0xcc,0xc7,0x21,0x7a,0x50,0x45,0xad,0xac,0x38,0xa2,0x9f,0x89,0x29,0x1d,0x5b, + 0x84,0x11,0x22,0x8,0xe3,0x13,0x9c,0x45,0x5b,0xa5,0x79,0xd6,0xa9,0xdb,0xc8,0x82, + 0xcd,0x15,0x45,0xfb,0xf8,0xbc,0x8f,0xce,0xaf,0xe4,0xdf,0xdd,0x7b,0xd2,0x9f,0x9c, + 0x5f,0xe3,0xab,0xaf,0xdf,0xd1,0xbf,0xfc,0xf8,0x59,0xbf,0x77,0x7c,0x81,0x6b,0x30, + 0xb7,0xc0,0x89,0x83,0x61,0xcd,0x1b,0x35,0x76,0x87,0x5f,0xd8,0x63,0xc4,0xe,0x4c, + 0x61,0xe0,0xb8,0x97,0xc7,0xfa,0xc1,0xc4,0x85,0x2,0x6c,0x5c,0x56,0x86,0x6d,0x84, + 0xb5,0xfc,0x6a,0x87,0xc8,0x38,0x4,0x47,0x12,0xf9,0x38,0xbc,0x5a,0xd7,0xa1,0x41, + 0xd7,0x7c,0xb1,0xeb,0x1c,0xd3,0xf9,0xc2,0x6d,0x4,0xd8,0x38,0x43,0x61,0x7c,0xb5, + 0xcd,0xe9,0x74,0x72,0xff,0xfc,0xa,0xa7,0x9f,0x3c,0xc3,0xeb,0x77,0x6f,0xe3,0x27, + 0x4f,0x4e,0xdb,0xc5,0x75,0xc7,0xf7,0x3f,0x7d,0xde,0xbb,0xd2,0xca,0x62,0xd4,0x8e, + 0xae,0x45,0x89,0x9c,0x84,0x16,0xa,0xb8,0xec,0x34,0xb,0xb5,0x2a,0xa7,0x3d,0x3a, + 0xbd,0x68,0xae,0x4,0xfb,0xf8,0x5f,0x57,0xc1,0xfb,0xef,0x45,0x22,0x7a,0x3a,0xdf, + 0x9d,0xd5,0xec,0x65,0x84,0x9e,0xd2,0x39,0x74,0x8e,0x73,0x8a,0x8,0x2e,0x81,0x66, + 0xca,0x2a,0x1b,0x45,0x41,0xe7,0x7f,0xd6,0x77,0xfe,0xc7,0xff,0xf5,0x7,0xae,0xfa, + 0xc5,0x3e,0x64,0x33,0xa4,0x2,0x8a,0x83,0xbc,0xb8,0xa5,0xcd,0x4b,0x63,0xc8,0x8c, + 0x29,0x17,0xba,0x7d,0x93,0x15,0x58,0xdb,0x84,0x28,0x4c,0xd,0x9c,0xce,0xe3,0xb8, + 0xb5,0x61,0xd6,0x68,0x2a,0x4d,0xda,0x30,0x6d,0xce,0xdf,0xb,0x6d,0x73,0xb2,0xdc, + 0x92,0x7,0x84,0xd2,0x5a,0xd4,0xdf,0xa5,0x65,0xae,0xa0,0xe0,0x5b,0x47,0xf9,0xb1, + 0x55,0xf2,0xc9,0x86,0x86,0xa5,0x23,0x5b,0x76,0x69,0xc3,0x7,0xbe,0x8,0x4d,0x64, + 0x13,0xb,0x28,0xd4,0x2,0x2e,0x7e,0x5f,0x99,0x10,0x6c,0xfa,0xc7,0x65,0xc9,0xa9, + 0x25,0xda,0x4b,0xe,0xb1,0x63,0x7d,0x83,0xd8,0xb,0xb1,0x44,0xd5,0x77,0x14,0xe, + 0xa0,0xc8,0x16,0x3b,0x2,0xd9,0x4a,0xa4,0x59,0x3c,0xa2,0x1a,0xd5,0x49,0x48,0x7e, + 0x94,0x81,0x78,0xe1,0xbb,0xf1,0x7f,0xc5,0x6f,0x2e,0xa5,0x2c,0xa9,0x4a,0xeb,0xa3, + 0x75,0x83,0xf2,0x6,0x55,0x95,0x3f,0x2b,0xa5,0x80,0x61,0xef,0xb1,0x95,0xd6,0x2a, + 0x8e,0x1c,0x23,0xad,0x87,0x22,0xdb,0xfd,0x56,0x81,0x76,0x75,0x78,0x82,0xf9,0xbc, + 0xb3,0x62,0xa2,0x59,0x4e,0x29,0xc8,0xd5,0x17,0x8e,0x28,0x2b,0xb0,0x81,0x3,0xe7, + 0xb1,0x3c,0xac,0x3,0x32,0x43,0x1b,0x20,0xcc,0x12,0xb7,0x79,0xe0,0xb8,0x4e,0x26, + 0xec,0xc4,0x11,0x1e,0x24,0xb7,0x40,0x26,0x5f,0x86,0xc6,0x88,0x65,0x33,0x3a,0x81, + 0x26,0x6d,0x8a,0x9a,0x54,0x21,0x6d,0xe4,0x54,0x4c,0xef,0x48,0xb3,0x77,0x52,0x5b, + 0x52,0x30,0x4b,0x74,0xea,0xa4,0x23,0xd,0x57,0x5,0x55,0xff,0xd1,0x96,0x46,0xad, + 0xcc,0x72,0x93,0x20,0x62,0x49,0x8a,0x39,0xd,0x55,0x7f,0xb0,0xd1,0xe9,0x3b,0x8a, + 0x15,0x2e,0xc4,0x23,0x4b,0x69,0x89,0x81,0x14,0xc,0x36,0x85,0x6b,0x88,0xbf,0x32, + 0x4f,0x52,0xa,0x65,0x61,0xc9,0xcb,0x10,0xd5,0x75,0xfe,0xfb,0x66,0x31,0x4f,0x7a, + 0xaa,0x84,0x34,0xe4,0xd1,0xa9,0x86,0xed,0x43,0x19,0xac,0x32,0x17,0xcb,0x96,0x36, + 0x80,0xa6,0xad,0x89,0x34,0xa8,0xb4,0x36,0xc2,0x2a,0xe8,0xd7,0xd2,0x74,0x70,0x5f, + 0x75,0x20,0x37,0xda,0xc4,0xb5,0x43,0x65,0x8,0xca,0x4a,0xe,0xf5,0xc2,0x28,0xe3, + 0xf7,0xd5,0xd9,0xf4,0xd6,0x1b,0xc0,0x92,0xe3,0x6,0xf8,0x16,0x32,0xec,0xf8,0x7d, + 0xc4,0x8c,0x75,0x84,0xf1,0x7,0xd0,0x81,0x9b,0x1,0xd7,0xd0,0xdd,0x9d,0xb,0x81, + 0x25,0xa2,0x81,0x58,0x9c,0xbd,0xe3,0x7b,0xb1,0x2e,0xbd,0x69,0xf3,0xe4,0xb5,0x36, + 0x87,0xa2,0xea,0x9d,0xba,0xdb,0x2a,0x28,0x62,0x33,0xee,0x6,0xbe,0x1,0x75,0xe3, + 0x9a,0x41,0x71,0xa4,0xfa,0xb3,0xa0,0x98,0x2,0xbf,0x1,0x66,0xef,0x32,0x4,0x94, + 0x7d,0xcc,0x57,0x86,0xc3,0x52,0xd0,0x77,0x18,0xdf,0x67,0xc7,0x40,0xb8,0x77,0xff, + 0x6c,0x26,0x72,0x6,0xc1,0x5b,0x85,0x93,0xee,0x29,0x1f,0x37,0xac,0x7d,0x9c,0x73, + 0x9d,0x5b,0xc1,0xca,0x76,0xaf,0x20,0x39,0x6,0xc6,0x68,0x15,0x99,0x6e,0x64,0xa6, + 0x6b,0xed,0x2a,0x88,0x50,0x72,0x38,0xea,0x23,0x2d,0xd5,0x41,0x41,0xde,0xd9,0x9b, + 0xdc,0x4a,0xd0,0x3a,0x62,0x3c,0xb2,0x97,0x79,0x2d,0x1c,0x8d,0x94,0x72,0x59,0x79, + 0x54,0xe8,0xdf,0x1e,0x6c,0xa4,0xdc,0x80,0xb1,0xb3,0x18,0xb8,0x45,0xf3,0x8f,0xcc, + 0x22,0xb0,0x8b,0x4a,0xc3,0x98,0x40,0x35,0xd1,0x16,0x23,0x44,0x4d,0x66,0x83,0xb9, + 0x37,0x8c,0x26,0xdd,0x56,0x56,0xb6,0x76,0x6,0x7f,0x90,0x15,0xbd,0xe7,0xef,0xe1, + 0x7c,0x60,0x1a,0x5d,0xda,0x81,0xc8,0xb,0xa,0x88,0xba,0xf0,0x1a,0xe1,0x74,0x50, + 0x48,0xd,0xcf,0x89,0x80,0x22,0xda,0x4d,0xe7,0xd7,0x32,0xee,0x90,0x1c,0x41,0x66, + 0x50,0x5c,0xcc,0x16,0x4b,0x9a,0xf3,0x2d,0x3d,0xe3,0x83,0xf,0xdc,0x82,0x6c,0x14, + 0x56,0xac,0xa6,0xe4,0x3e,0x49,0x4b,0x1b,0xf8,0x54,0xa0,0x7b,0x7,0x9f,0x3,0x0, + 0x1b,0xb1,0xa6,0xad,0xc5,0x60,0xaf,0xa1,0x2a,0xc9,0x2e,0x42,0x38,0x93,0x2a,0x22, + 0xd,0x6,0x29,0xab,0x35,0x67,0x67,0x3e,0x1,0x35,0x9,0xca,0xa0,0x31,0x32,0x87, + 0x39,0x50,0x28,0xa,0x50,0xa9,0xd9,0x8e,0x9f,0xb3,0xd,0x90,0x12,0x45,0x2d,0xeb, + 0x14,0xdc,0xa2,0x67,0x3f,0x56,0xaf,0x39,0x29,0x37,0x18,0x46,0x7a,0xf3,0x1f,0xa2, + 0xa4,0x88,0xd3,0x40,0xcc,0x8f,0x29,0xb7,0x20,0xec,0x67,0xe3,0x47,0xdd,0x2c,0x5f, + 0x9b,0x40,0x28,0x82,0x50,0xb8,0xab,0x45,0x5c,0x61,0xaa,0x54,0x89,0xde,0xe5,0xa3, + 0xe4,0x74,0xc1,0x81,0x5c,0x17,0x4,0x6e,0x42,0xc0,0x61,0x10,0x9,0x58,0xe3,0xa6, + 0xe9,0xd3,0x92,0xd0,0xa0,0xd3,0x85,0xab,0xda,0xa4,0xd,0xc2,0xf5,0x14,0x3c,0xda, + 0xd9,0x3d,0x7c,0x53,0x1a,0x2,0x2,0x76,0x33,0xa0,0xd6,0x9b,0x6d,0xb6,0x64,0xcd, + 0x17,0xe1,0xfe,0x8a,0x93,0x75,0x93,0xec,0x64,0x34,0x91,0xe1,0x49,0x11,0x28,0x44, + 0x24,0xaa,0xd7,0xb1,0xeb,0x6e,0xfe,0x2,0x21,0x7a,0x74,0x5b,0xbf,0x59,0xdd,0x64, + 0xda,0x66,0xff,0x4d,0x18,0xb1,0xa8,0x7d,0x46,0xad,0xb8,0xa8,0x76,0x6c,0x5a,0x69, + 0x9a,0xe6,0xd,0x26,0x55,0x97,0x3d,0x5b,0xed,0x10,0x7d,0x79,0x4a,0xbb,0x0,0x54, + 0x74,0x99,0xb0,0xd2,0x7e,0x53,0x62,0x7d,0x91,0x1c,0x3b,0x32,0xbd,0xee,0xa2,0xa4, + 0x7,0x70,0xdd,0x90,0x46,0xf0,0xe,0xcd,0xda,0x72,0xad,0xf,0xdf,0xeb,0xc6,0xbe, + 0x1f,0x3c,0x32,0x1f,0xbf,0xee,0xc6,0x45,0x13,0xcc,0x95,0x2f,0x66,0xcb,0x89,0xb1, + 0xe3,0xe9,0xb3,0x11,0xd1,0x3e,0xdf,0x2e,0x5a,0xeb,0xb0,0x16,0x4b,0x29,0x23,0x60, + 0x4,0xa0,0xf4,0x2c,0xde,0x9e,0x1a,0x72,0x9b,0xbf,0xcd,0x90,0x94,0x26,0xd2,0x2d, + 0xc6,0x6f,0x14,0x96,0x1d,0x6d,0xc2,0xa7,0x59,0x20,0x2d,0xb6,0x2a,0xa2,0x38,0x4a, + 0x4f,0x37,0xd7,0x6a,0x8a,0x94,0xc0,0xd4,0xce,0x77,0x64,0x8e,0x81,0xfb,0x74,0x33, + 0xcc,0xf,0xd6,0x9d,0xc,0xdd,0xd8,0xf5,0x46,0xca,0x9c,0xe5,0x9e,0xc3,0xb6,0xba, + 0x45,0xff,0xcc,0x14,0xbc,0x59,0xe8,0x29,0xf2,0xf9,0xa1,0xa9,0xc5,0xd7,0x85,0xa4, + 0x49,0x42,0xe3,0xd4,0x51,0x25,0xa6,0x7b,0xb2,0x56,0xe5,0x20,0x7a,0xd1,0x2a,0xa8, + 0x42,0x5d,0x1,0xc7,0x75,0x3a,0xc7,0xbe,0x43,0x14,0xc7,0xc2,0xd4,0x85,0xd3,0xce, + 0xca,0x6b,0x8a,0x77,0xe3,0xf6,0xad,0xc,0x8c,0x91,0xb1,0xb6,0xca,0x21,0x59,0xa0, + 0xf4,0x1e,0xcd,0xa4,0x9d,0xa9,0xec,0x74,0xb9,0xa0,0xe8,0x81,0xa3,0x94,0xc6,0xcc, + 0x72,0xec,0x1a,0xfb,0x14,0x57,0xf4,0x59,0xd1,0x76,0xa8,0xd1,0x1c,0x6c,0x37,0x8, + 0x36,0xd3,0x72,0xb,0xaa,0x9d,0x56,0xa5,0xbe,0xe4,0x9f,0xfb,0xbf,0x4,0x59,0x69, + 0xcb,0x5c,0x81,0xbd,0xe4,0x99,0x75,0xec,0x8d,0x8a,0xef,0x13,0x92,0x78,0xc9,0x38, + 0xdd,0x12,0xe1,0xa9,0x53,0xc9,0x6c,0xc8,0x6,0x5d,0x60,0x7e,0xa1,0x30,0xf6,0x10, + 0xb9,0x44,0xff,0x20,0x68,0x5,0x49,0x9c,0x5b,0xc8,0x8b,0xb5,0x52,0xfd,0xc,0xd4, + 0x52,0xac,0xee,0x91,0xba,0x13,0x13,0x5,0xe7,0x9c,0x4c,0x8b,0x37,0xa3,0x8,0x43, + 0xd0,0xe3,0xde,0x32,0x75,0x67,0x9b,0xad,0x50,0x54,0x49,0xa,0x90,0xd5,0x6e,0x29, + 0x52,0x88,0x67,0x7,0xba,0x39,0x9a,0x40,0xfa,0xbe,0x11,0x16,0x8c,0xb0,0x85,0xa9, + 0x96,0x77,0xc7,0xf2,0x1,0x27,0xbc,0x48,0xd3,0x38,0x9d,0x5d,0x1a,0x2c,0x72,0x63, + 0x15,0x3e,0xbd,0x98,0xf3,0x60,0xe3,0xf,0x8c,0x5b,0x4f,0x6b,0x5f,0xd2,0xeb,0x0, + 0xe5,0x48,0x4a,0x65,0x44,0x80,0x1d,0xdc,0x52,0x93,0xbd,0xbc,0xa3,0xa,0x38,0x11, + 0x22,0xbb,0xdb,0x84,0x5b,0x24,0xaa,0xcb,0x7c,0x20,0x24,0x61,0xa7,0x3a,0x64,0x78, + 0x1a,0x65,0x61,0x22,0x25,0x85,0x68,0x1b,0xb2,0x37,0xed,0x24,0x52,0x9a,0xbf,0x96, + 0x1e,0x7e,0xe2,0x29,0x49,0x1d,0xad,0xce,0xec,0xd0,0xfd,0x1,0xd2,0x24,0xe0,0x25, + 0x8d,0x8d,0x59,0xc2,0xad,0x53,0xef,0x31,0x8f,0x86,0x92,0xa8,0x34,0xf2,0xc7,0xa7, + 0x1d,0x8c,0x47,0xed,0x9a,0xa2,0x4,0xd0,0x27,0xc4,0xc5,0xc5,0xa4,0x3d,0x5f,0xd6, + 0x11,0x2b,0x3b,0x35,0x29,0x4d,0x90,0x23,0x67,0x23,0xa8,0x45,0xc4,0x7d,0xfe,0x51, + 0xc,0x45,0xda,0x9a,0x58,0x17,0x86,0x16,0x11,0xb6,0xa8,0xdd,0x38,0xc8,0x31,0x69, + 0xe1,0xf5,0xde,0xc6,0xcd,0x49,0xac,0x46,0x1,0x29,0xcd,0x3a,0xab,0xc6,0x23,0x3f, + 0xbf,0xcc,0x55,0xc6,0x4e,0x5d,0x8a,0x7f,0xde,0xb6,0xa5,0xf3,0xb5,0xee,0x31,0x8d, + 0x43,0xd0,0xa9,0x92,0xda,0x79,0x3e,0x67,0x43,0xcc,0xc0,0x16,0xeb,0xe,0x60,0x8, + 0x2e,0xfb,0xbc,0xa4,0xb5,0x43,0xa4,0x75,0x74,0xf4,0xe1,0x1c,0xea,0x5d,0x7a,0x43, + 0x57,0xf4,0x51,0xf2,0xd,0xa8,0x8e,0x24,0xeb,0xda,0x2a,0x23,0xf5,0xc8,0xd8,0x16, + 0x13,0xd2,0x71,0xb5,0x34,0x9d,0x31,0x5c,0xf3,0x36,0x8c,0xb,0x7c,0xee,0x5f,0xfa, + 0x98,0xd,0xa9,0xcc,0x4a,0x62,0xec,0xe1,0x55,0xd5,0x83,0xbc,0x5b,0x1a,0x32,0x93, + 0xf7,0x51,0x39,0xb2,0x1b,0x31,0x54,0x57,0xd3,0x44,0xce,0x77,0xad,0xc5,0x79,0x3c, + 0x46,0x6b,0xee,0x68,0x18,0xf1,0x79,0xb3,0xa0,0x6e,0x6,0xe7,0x9f,0x1a,0xd5,0x3, + 0x85,0x41,0x64,0xcc,0x9a,0xe6,0x19,0xe6,0x74,0xb7,0x76,0x42,0x50,0xa7,0xd2,0x4e, + 0x91,0x58,0x6a,0xc9,0x9e,0x46,0xe2,0x51,0x83,0xdb,0x48,0xd0,0x76,0x4,0x93,0xe7, + 0xcf,0xb1,0x87,0x5c,0xda,0x8a,0x37,0x1f,0x6d,0x53,0x19,0x3f,0x58,0xee,0xb,0x91, + 0x26,0x59,0x84,0xd2,0x8e,0x60,0x1b,0x3a,0x53,0x46,0xd6,0x6e,0xba,0xb7,0xd1,0x1a, + 0xc5,0x70,0xd,0x2e,0xf2,0xd4,0x96,0x10,0x4,0xc,0x26,0x18,0x99,0x3f,0xac,0xd6, + 0x4c,0xb8,0x26,0x5d,0xa4,0xab,0x6a,0xc3,0x70,0xd6,0xa5,0xcb,0x7c,0x37,0xc6,0x38, + 0x46,0xe3,0x9d,0x8b,0xe0,0x61,0xce,0x24,0x4,0xbe,0xc6,0x26,0x37,0x6a,0xa6,0xae, + 0xa6,0x27,0xcc,0x15,0xaf,0xef,0x3f,0xfa,0xc,0x5d,0xb0,0xe2,0x58,0x39,0x54,0x5, + 0x4e,0xc4,0x35,0x64,0x76,0x9f,0xe2,0x3d,0x6f,0xbe,0x69,0xac,0x7,0x1d,0xe2,0x9a, + 0x18,0xe3,0x92,0xa0,0x8a,0x41,0x45,0x7c,0x3d,0xa5,0x6a,0x81,0xb2,0x63,0xdd,0xb3, + 0x69,0x5f,0x37,0x1d,0x6d,0x31,0x6e,0x9,0xc1,0x4,0xa8,0x1a,0x69,0x61,0xab,0xe4, + 0xfd,0x0,0x41,0xe7,0x1,0xa1,0xbf,0x6e,0xba,0x2,0x6f,0xc2,0x93,0x3e,0x8b,0x87, + 0x16,0xd2,0x7f,0xf1,0x28,0x7b,0xf2,0x1b,0x69,0xda,0xa9,0xbb,0x7a,0x9c,0x66,0xf2, + 0x58,0x66,0x87,0xf4,0x45,0x39,0xa5,0x5f,0xfd,0xb5,0x4f,0x44,0x99,0xb1,0x8e,0x81, + 0xb1,0x6,0x47,0xb,0xd5,0x8c,0x82,0xf,0x8f,0x78,0xb2,0x8d,0x9d,0x90,0x38,0xb3, + 0x5a,0x37,0xb4,0x58,0xf8,0x83,0x27,0x2a,0xae,0x1c,0x4e,0x5d,0x3,0x79,0xc5,0xe8, + 0x33,0x9c,0xd3,0x13,0x4,0x7c,0x2a,0x8d,0x78,0xcd,0x2b,0x5,0x4a,0x5,0x2b,0x17, + 0x53,0x1e,0x15,0x4f,0xf1,0x1a,0x22,0x5c,0xcd,0xbf,0x7e,0x23,0xa2,0xb9,0xee,0x60, + 0xe,0x4b,0x2c,0xd4,0x5b,0x35,0xfb,0xa1,0xfb,0x6e,0xc4,0xb0,0x34,0x91,0x31,0xd9, + 0x82,0x5d,0xe6,0xce,0xe1,0x1e,0x4a,0x27,0x73,0xb1,0xba,0x40,0xce,0x26,0x42,0x94, + 0x9b,0x63,0xf1,0xc8,0x7e,0x44,0x34,0xf5,0x9c,0xc,0xea,0xb6,0xc,0x9a,0xee,0x6b, + 0x61,0x4c,0x6f,0x7e,0x8,0x4d,0xa3,0x2b,0x56,0xb2,0xf6,0xcd,0x14,0xcc,0xf1,0x47, + 0x5a,0x90,0x4f,0xb3,0xe,0x4b,0xa7,0x1d,0x10,0xbe,0x2f,0x9d,0x89,0x61,0x88,0x81, + 0xfb,0xb4,0x4b,0xd8,0xe7,0x9c,0x27,0x83,0x8,0x21,0x1e,0x57,0x47,0xb4,0xc3,0x17, + 0x49,0x13,0x6,0xb8,0x2b,0x24,0x1c,0x35,0x84,0xed,0xf5,0xbd,0x43,0x87,0x31,0xaf, + 0x8c,0x0,0x17,0x2c,0x2d,0x4f,0xd2,0x69,0x80,0xa2,0x4d,0x3b,0x62,0xb3,0xdd,0x79, + 0x47,0x9b,0xcb,0xe9,0x51,0x60,0x35,0x21,0xb6,0xcc,0xf8,0x19,0x7b,0x35,0x6d,0x17, + 0x69,0x1c,0xfb,0xc3,0x7f,0xd,0x16,0x2,0x9a,0xf8,0x52,0xa0,0x7d,0x82,0x76,0x3a, + 0xb4,0xb9,0x40,0x4e,0xfb,0x88,0x86,0x1d,0x17,0x59,0x87,0x1c,0x88,0x4d,0x92,0xe6, + 0x11,0x3d,0xbf,0x77,0x5f,0xd5,0x59,0xdf,0xd3,0x68,0x17,0xc5,0x45,0xf9,0xf8,0xc6, + 0xf2,0xe4,0x54,0x3b,0x20,0xda,0xda,0x30,0xc,0xba,0xe,0xc7,0x3,0x2b,0x7c,0x9a, + 0xda,0xe0,0x13,0x26,0xd8,0xf8,0x98,0x59,0x2e,0xac,0x3b,0x4f,0xd7,0x5d,0x5c,0xda, + 0xb1,0xae,0x4a,0x2,0x40,0xff,0xdf,0x62,0x6b,0x53,0xb7,0xee,0xc9,0x4e,0x1a,0x6, + 0x7f,0x81,0x4c,0xe7,0xbd,0xcf,0xcb,0x3b,0x2a,0x58,0xb0,0x20,0xd4,0xab,0x30,0xf5, + 0x6,0x4a,0x12,0x6a,0x37,0x3,0x73,0x4d,0xc8,0xe1,0x11,0x7c,0x86,0x7f,0x6d,0x51, + 0x28,0xa8,0xe,0x4b,0xa7,0xff,0xcc,0x91,0x37,0xae,0xb2,0x49,0x95,0x53,0x39,0xc, + 0x65,0x5d,0x13,0x56,0x1e,0x6a,0x99,0xdb,0x67,0x23,0x32,0xd8,0xb6,0x55,0x10,0x92, + 0x79,0xcb,0x83,0xb4,0x71,0xe2,0xb4,0x31,0xf,0x64,0x50,0xf0,0xc2,0xe1,0x20,0xbd, + 0x21,0x24,0x8,0xd1,0xf0,0xe7,0x8e,0x6a,0xb7,0x63,0x64,0x4b,0xf6,0x3e,0xaa,0x41, + 0xd,0x3e,0xaf,0x87,0xa7,0xdb,0xfe,0x34,0x5d,0xec,0xde,0x2a,0x28,0x71,0xab,0x9a, + 0xa6,0x50,0x14,0x4e,0x36,0x9b,0xc0,0x21,0x64,0x6d,0xb4,0xe,0x95,0x6e,0xda,0x11, + 0x46,0x70,0x4f,0x5c,0xa,0xae,0xbc,0x35,0xf6,0xb6,0xb5,0xdd,0xf0,0xa2,0x47,0x80, + 0xba,0xe7,0x56,0x86,0xdb,0x36,0xf1,0x64,0x59,0xf0,0xba,0x3c,0x62,0x93,0xd2,0x46, + 0xd9,0x4e,0x64,0xff,0xe2,0x22,0xf5,0xc8,0x85,0xd8,0xbd,0x85,0xdc,0xcd,0x6e,0x42, + 0xfb,0xda,0x54,0x2b,0x64,0xb1,0x48,0x25,0x38,0xf,0x96,0x72,0xc9,0x69,0x7d,0xa2, + 0x65,0xdd,0xa3,0x44,0x7c,0xf,0xb6,0xa5,0x2f,0xe2,0x33,0x81,0xc9,0x6d,0x93,0x24, + 0x4b,0xef,0xf3,0xb2,0xee,0x8e,0xb5,0xb0,0xdb,0x2d,0x74,0x9e,0x50,0x95,0xee,0xd1, + 0x3e,0x36,0x8d,0xf1,0xe,0x9c,0x40,0x50,0x2d,0x9b,0x34,0x12,0x40,0x29,0x6f,0x42, + 0x8,0xa3,0x7,0xcf,0x18,0x88,0x6b,0x2e,0x76,0x77,0x2a,0xa6,0x10,0xb0,0x3,0xd, + 0x51,0x1f,0x7a,0x4e,0xb6,0x7b,0xa4,0x1d,0x1a,0x64,0x8e,0x19,0xf0,0xee,0x73,0xee, + 0xd7,0x4d,0xb8,0x64,0xda,0x23,0x95,0x18,0xd7,0x27,0x6e,0x2,0x5b,0xff,0xbc,0x8, + 0x84,0xaf,0x34,0xe6,0x52,0x51,0x83,0xb9,0xdd,0xba,0xb4,0x3e,0xab,0xaf,0x36,0x58, + 0x40,0xb1,0xf3,0x9c,0xef,0x6d,0x97,0x94,0xa6,0x35,0xb6,0xba,0xd9,0x9d,0xe7,0x4e, + 0x12,0x56,0xda,0x42,0x8,0xd3,0x3b,0x4f,0x4b,0xef,0x82,0xf9,0x5d,0xef,0x94,0x5c, + 0x39,0x7f,0x9e,0x63,0x32,0x3c,0xd3,0xcd,0xec,0x1b,0xeb,0x76,0x3b,0xb7,0x40,0xbe, + 0x92,0x7b,0x10,0xee,0xfa,0x9f,0xdd,0xe9,0x2c,0x2c,0x5c,0xf8,0xe6,0x41,0x24,0x1e, + 0x3c,0x27,0x91,0x4e,0xa7,0xb1,0x3a,0xe9,0x92,0xd5,0xf6,0xa4,0xcd,0x4a,0x74,0x42, + 0x10,0x50,0xa8,0xec,0x35,0x1d,0xb8,0x3f,0x68,0x97,0x84,0x5b,0x8e,0xda,0x76,0x48, + 0xd0,0xe,0x66,0xdc,0xdb,0xb4,0x61,0x7,0xc3,0x7f,0x5c,0x88,0xe2,0x97,0xb9,0xc4, + 0x24,0x25,0x84,0x39,0x46,0x44,0x66,0x6b,0x6c,0xac,0x1,0x85,0x46,0xf4,0x98,0x2, + 0xcb,0xa1,0x73,0xc3,0xfc,0xb9,0xda,0xe5,0xd6,0x61,0xa,0xf8,0x61,0x9f,0xec,0x68, + 0x53,0x8c,0x89,0x31,0x31,0x37,0xed,0x87,0x15,0xc9,0x64,0x79,0x15,0x65,0xe3,0xa9, + 0x3a,0x5d,0x6a,0x78,0x20,0x5b,0x1b,0x6,0xba,0xa6,0xcd,0x87,0x84,0x4d,0xdb,0xe, + 0xda,0xe7,0xf4,0x22,0x51,0x2a,0x44,0x9b,0x75,0x3b,0x5d,0x1b,0x65,0xb6,0xa6,0xd4, + 0x66,0xa5,0x8c,0x14,0x46,0x7f,0x11,0x8c,0x69,0x1e,0xb,0xbd,0xcf,0x95,0xc2,0xa8, + 0x14,0x8c,0x37,0x30,0x4b,0xca,0x1e,0xd6,0xc6,0x3,0x9d,0xd4,0x5b,0x5b,0xa1,0xda, + 0xfc,0x83,0x82,0x81,0xdc,0x46,0xaf,0x5,0xfb,0x8a,0xd5,0xf2,0x2d,0x79,0x62,0x22, + 0xdc,0x34,0xd9,0xf3,0xd2,0xc4,0x55,0xbb,0x92,0x81,0x79,0x12,0x83,0x1,0x12,0xd1, + 0x81,0x1b,0xab,0x7d,0x93,0x12,0x4c,0xb0,0xcc,0x81,0xa,0x43,0x7e,0x75,0xcf,0x8e, + 0x91,0x55,0xc1,0xa2,0x89,0x61,0x99,0xb5,0x41,0x65,0x91,0xaf,0x5e,0x82,0x47,0xc4, + 0x91,0xcc,0xdc,0xd9,0x50,0x3e,0x5b,0xc1,0x3a,0x36,0x2b,0x36,0xe2,0x0,0x75,0xb1, + 0x50,0xe9,0x43,0x3b,0x32,0x84,0xdd,0x5d,0xed,0x7c,0x9f,0x84,0xa2,0xf1,0x22,0x8d, + 0x21,0x86,0x85,0x50,0xc,0x4a,0x81,0xf8,0x2e,0x26,0xf2,0x1e,0xe2,0xe4,0x6b,0x24, + 0x33,0xaf,0x5e,0xfe,0xcd,0x50,0x95,0xc2,0x9b,0x8e,0xa6,0x3e,0xa8,0x8f,0x53,0x4d, + 0x63,0xcb,0x58,0x53,0x2c,0x87,0x8f,0x1d,0xf6,0xd2,0xa,0xed,0xd,0xe3,0xb6,0x15, + 0xba,0xd0,0xdc,0x72,0x16,0xf9,0x87,0x91,0xa5,0xaa,0xa4,0xd8,0x57,0xbe,0x26,0x89, + 0x24,0xa4,0xd4,0xcc,0x25,0x55,0x24,0x23,0x2b,0x11,0xb3,0x2b,0x5b,0xec,0x2a,0x96, + 0x64,0x80,0x96,0x41,0x9,0x4a,0x4,0x79,0x4b,0xf0,0xa,0x9c,0xfc,0x6c,0x5b,0x95, + 0xb4,0xd7,0x13,0x22,0xe0,0x4f,0x55,0xa3,0x92,0x5b,0x69,0x2c,0xa0,0x34,0xe9,0xf1, + 0x1b,0x2b,0xa6,0x13,0xdd,0x52,0x2a,0x88,0x5f,0x1f,0xbb,0x62,0xcd,0xa8,0x36,0x1a, + 0xd6,0xb3,0x6d,0x11,0xc4,0x6d,0x17,0x16,0x58,0xf8,0x8e,0x2a,0x9,0xde,0xac,0x8a, + 0x4f,0x1a,0xa,0xd0,0x4e,0x5b,0x6d,0xf5,0x16,0x8c,0xe3,0xe9,0x6e,0x80,0x67,0x9b, + 0x83,0xe3,0x39,0x43,0x5d,0x84,0x89,0x69,0x77,0x80,0xde,0x18,0xbd,0x2a,0x5c,0x91, + 0x64,0x97,0xbb,0xb2,0xbb,0x30,0xc,0xa9,0xfe,0x9e,0x20,0x19,0x25,0xa2,0xa6,0x6e, + 0xcd,0x31,0x73,0xe3,0x5b,0x1b,0x74,0xb8,0xd9,0x3e,0xd9,0x28,0xb7,0x99,0xec,0x2, + 0xc2,0x8a,0x65,0x62,0x83,0xc1,0x51,0x8e,0x8c,0x54,0x14,0xf0,0x64,0x8b,0xd8,0xd, + 0x2,0x86,0xe8,0xa4,0x9d,0x27,0xfc,0x9f,0xfb,0x45,0x9a,0xf3,0xcc,0xa3,0x89,0x19, + 0xc8,0x53,0x93,0x24,0x79,0x33,0x44,0xa3,0xfb,0x80,0xf6,0x0,0xd2,0x46,0x37,0xde, + 0x41,0x2e,0xe3,0x49,0x5e,0x73,0xd,0x7b,0x2,0xfc,0x8c,0x36,0xbd,0x93,0x48,0x35, + 0x2e,0x12,0xc2,0x92,0x8a,0x46,0x4c,0x83,0xb6,0x2a,0x72,0x52,0xca,0xc8,0xb6,0xc0, + 0xc1,0x41,0x4c,0x74,0x27,0xa3,0x1f,0xcc,0xf1,0x73,0x9e,0xc5,0xe1,0xd0,0x8,0x9, + 0xa0,0xda,0xc7,0x92,0x48,0x5d,0xb2,0x33,0x9f,0xb3,0xf9,0x33,0x81,0xc6,0x68,0x9b, + 0x53,0x60,0x6c,0xcc,0xab,0x90,0x3,0x9f,0xed,0x60,0xba,0x2f,0x5c,0x7f,0x30,0x57, + 0x92,0xb3,0x43,0x57,0xb3,0xf5,0xf5,0x59,0xa0,0x76,0x39,0x30,0x2f,0x77,0xeb,0xa3, + 0x89,0x8e,0x33,0x4d,0x38,0x25,0x90,0x83,0x45,0x8c,0xb4,0xa,0x43,0x9d,0x7b,0xe3, + 0xd2,0x66,0x97,0xda,0xa7,0x48,0xd9,0x8a,0x93,0x71,0x68,0x6b,0x6b,0x10,0xf4,0x49, + 0x78,0x6f,0xd3,0x71,0x31,0xa9,0x62,0x6,0x8c,0x76,0x81,0x1c,0x2c,0x83,0x3d,0xed, + 0xe3,0x66,0x81,0xe8,0x60,0xb0,0x3e,0xa,0xa4,0x3e,0x32,0x8d,0xec,0x47,0xd2,0xfb, + 0x81,0xeb,0x51,0xfa,0x98,0x68,0x35,0xcc,0x8c,0xd5,0x39,0x3e,0x9d,0xd2,0xf5,0x3, + 0xe1,0xf3,0xd,0x5c,0xa6,0x61,0xc3,0xf5,0x23,0x8d,0x5,0x4b,0x8d,0x44,0x70,0xad, + 0x50,0xdd,0x5a,0x28,0x5d,0x28,0x10,0x49,0x19,0xaa,0x2a,0x65,0xec,0xa0,0x39,0x4d, + 0x32,0x3b,0x2a,0x74,0x55,0xf2,0x66,0x52,0xdc,0x86,0x6c,0xb0,0x20,0x52,0x93,0x7a, + 0x7a,0x73,0x69,0xaf,0x39,0xec,0xa9,0xe4,0xab,0xa3,0x69,0xb2,0xa,0x80,0x4b,0x15, + 0xf5,0x9f,0x3c,0x35,0x44,0x49,0x24,0x61,0xa0,0x8f,0xe1,0x37,0x1f,0x1f,0x60,0x77, + 0xa4,0x60,0x13,0xed,0x73,0xd8,0xd7,0x43,0xe2,0xae,0xde,0x88,0xcd,0x8c,0x5e,0xa8, + 0xdd,0x62,0x21,0x82,0xb,0x7e,0x35,0x55,0x5c,0x75,0x83,0xeb,0x59,0xdf,0x36,0x5c, + 0x87,0x77,0xe9,0x8,0xd9,0x36,0x5c,0x82,0x3b,0x6d,0x32,0x7a,0x10,0x8a,0x67,0xbf, + 0xe8,0x4d,0x1a,0xda,0x5d,0xe0,0x43,0xbe,0x74,0xa4,0xd1,0x2f,0xb3,0xd,0xd2,0xb8, + 0xdd,0x40,0x2b,0x8b,0x7c,0x72,0xcc,0x78,0x93,0x23,0x81,0xf9,0x2,0xca,0x58,0x57, + 0x84,0x4d,0x43,0xda,0x3c,0x84,0x3b,0x4a,0x6e,0xdc,0xc6,0x7a,0x3b,0x7c,0xb,0xdd, + 0xec,0xf6,0xc3,0xd8,0x8c,0x16,0x4b,0xad,0xf8,0x6e,0x8a,0xf8,0x17,0x2d,0x4a,0xa6, + 0x28,0x4b,0xe6,0xa8,0x78,0xee,0x51,0xec,0xb,0xee,0x24,0x6e,0x8b,0x9d,0x95,0xaf, + 0x67,0x55,0x25,0xc6,0xef,0x94,0x70,0xa1,0x6c,0x10,0x57,0xd3,0x47,0x68,0x62,0x37, + 0xad,0x3a,0x11,0x5d,0x52,0x94,0x28,0xb1,0x93,0x5e,0x6e,0x55,0xa4,0x12,0x88,0x4, + 0x42,0xa1,0x51,0xb,0x91,0xc9,0x38,0x84,0x1a,0x8f,0x70,0x23,0x5c,0xc5,0xa6,0xe2, + 0xce,0x58,0x98,0x83,0x4d,0xaf,0xaf,0x63,0x54,0xdc,0x1d,0x42,0x17,0x3c,0x53,0xe, + 0x7c,0xa4,0xef,0xc9,0xa5,0xb2,0x60,0x6d,0x86,0x46,0x95,0x3a,0x57,0xe,0xdd,0x8b, + 0xde,0xd1,0x1d,0xf5,0xd1,0xcc,0x34,0x8f,0x4f,0xb2,0xb1,0x14,0x62,0x2,0x16,0xc2, + 0x74,0xd5,0x15,0xce,0xa3,0x99,0xe8,0xeb,0x5e,0xc,0x1a,0xa5,0x23,0x9,0x30,0x67, + 0x91,0xd4,0x19,0xb0,0xa8,0xb0,0x55,0x1d,0xd2,0x7a,0x4a,0xdc,0x5a,0x9,0x1d,0xbc, + 0xb7,0xae,0xa1,0x51,0x8,0x11,0x1b,0x40,0x85,0x56,0x0,0x6c,0xba,0x5b,0xe9,0xc0, + 0x4,0xd0,0x14,0x8c,0xa9,0x5a,0x95,0xec,0x59,0x24,0xaa,0x9a,0xa7,0x96,0xc9,0x66, + 0x40,0xc4,0x19,0x77,0x20,0x45,0x44,0xad,0xe4,0x41,0x94,0x4c,0x68,0xcc,0xb0,0xc1, + 0x8f,0xf,0x77,0x30,0xcd,0x74,0x82,0x5e,0x54,0x5b,0x37,0xd7,0xe1,0xec,0x70,0xa6, + 0x19,0x7e,0xea,0xc8,0x8c,0xd1,0x16,0x85,0x89,0xc7,0x2c,0x7b,0xb1,0xae,0xe8,0xbd, + 0x63,0x64,0x44,0x39,0xcf,0xa0,0x8f,0xdb,0xce,0xf8,0xed,0x3d,0x9e,0xbf,0x31,0xa9, + 0xeb,0xe8,0x1d,0xc4,0x9b,0xf,0xcd,0x0,0x7f,0x4e,0xde,0x20,0x34,0x9f,0x62,0x4a, + 0xe0,0xca,0x55,0xe6,0xf3,0x35,0xb6,0x3d,0xad,0x75,0x41,0x6f,0xbe,0xe,0xc5,0xbc, + 0xcc,0x9b,0x8e,0xce,0xc6,0x2c,0x6d,0xe1,0xc,0x8,0xb5,0xab,0x68,0xfe,0xb4,0x95, + 0xc4,0xc5,0xd4,0x59,0xa9,0x8a,0x1c,0x8,0xad,0xb8,0x4,0xa2,0xad,0xcf,0x81,0x4d, + 0x17,0x4f,0xdd,0x9b,0x4c,0x7b,0x21,0x7e,0x3f,0x61,0x95,0xfb,0x90,0x4c,0xfa,0xb6, + 0xb0,0x4b,0x68,0x68,0x50,0x80,0x6a,0x6,0x97,0xa9,0xf7,0x60,0xb6,0x94,0x55,0x6c, + 0xb6,0x72,0xb3,0x22,0xc5,0xf,0x42,0xec,0x16,0xda,0x99,0x27,0x24,0x7b,0x15,0xf3, + 0x6a,0x92,0xab,0x1e,0xf6,0xd6,0x64,0x2b,0xe1,0x95,0xcc,0xcd,0x2,0x9e,0xa9,0x29, + 0x39,0x2f,0xfd,0x23,0x6e,0x11,0xbc,0x22,0x41,0x97,0x93,0x29,0x54,0xe7,0xbc,0x56, + 0xe5,0xb7,0x19,0x94,0x9c,0x9b,0xc1,0xef,0xa9,0x9c,0x89,0x6c,0x74,0x19,0x74,0x80, + 0x29,0x9c,0x98,0x1,0xc1,0xf6,0xaf,0x74,0xdb,0xff,0x75,0x7,0x5f,0x86,0x8a,0xc2, + 0x11,0xaf,0x4c,0xb2,0x50,0xcd,0x23,0x8b,0x14,0x13,0xca,0x7,0x38,0x2d,0xe,0x22, + 0x70,0xc1,0xfd,0xe5,0xa2,0x46,0xae,0xf4,0x2a,0x0,0x22,0x2a,0x3b,0x15,0xab,0x4, + 0xc7,0xf7,0x4b,0xc,0x77,0xb4,0x58,0xc3,0x29,0x75,0x7e,0xa0,0x91,0x32,0x2d,0x2a, + 0xc8,0xed,0xa0,0x59,0xf2,0xa6,0xaa,0xc2,0xd4,0x76,0x75,0xf4,0xa4,0xd3,0xf,0xa0, + 0x25,0x1,0x91,0xc7,0x88,0x1e,0x72,0xa4,0xe2,0x6e,0x82,0xb9,0x16,0x5a,0xac,0x5d, + 0x52,0xab,0x39,0x5,0x2b,0xcd,0x60,0x5f,0x20,0x51,0xb1,0x48,0x8c,0x19,0x3a,0xa, + 0x98,0x4a,0x3e,0x5f,0x34,0xa2,0x30,0xa2,0x56,0xba,0x70,0xe1,0xb8,0x9c,0x49,0x8c, + 0xf6,0x1f,0x6,0x66,0x7e,0x77,0x4a,0x51,0x8f,0x19,0x44,0x53,0xe5,0xe0,0x1a,0xd, + 0xb5,0x41,0x9e,0xca,0x80,0x81,0x4a,0x33,0x44,0x5e,0x95,0x3d,0xa3,0x84,0xa2,0x45, + 0x78,0x9e,0x85,0x3a,0x76,0x72,0x35,0xc4,0x56,0x89,0xba,0xee,0x18,0x36,0xcc,0xd4, + 0x34,0x1a,0xaf,0xf6,0x1e,0x9d,0x2a,0x1a,0xaf,0xfd,0x28,0x26,0x95,0x2a,0xcc,0x8e, + 0xf0,0xdc,0x16,0x81,0x8c,0x42,0x62,0x79,0x9b,0x1c,0xe,0x1c,0x20,0x60,0xdb,0xf0, + 0x51,0x60,0xc1,0x4d,0x10,0xcd,0xfe,0xe1,0x54,0x22,0xb7,0x94,0x90,0x44,0xdd,0xf8, + 0xe6,0x26,0xd3,0xbe,0xbe,0x6e,0xf3,0x2,0xe7,0xf7,0x2b,0x81,0xe7,0x39,0x8e,0x40, + 0x11,0x14,0x45,0x6f,0xef,0x41,0xeb,0xb8,0x28,0x62,0xa6,0xe7,0x68,0xee,0xd0,0x8c, + 0xed,0x1a,0xf9,0x41,0x54,0x81,0x93,0x6,0xda,0x17,0xe9,0x7a,0xe0,0xa,0x43,0x70, + 0x1d,0x44,0x70,0x18,0x68,0x71,0xfa,0xf0,0x37,0xc1,0xb9,0xb,0x93,0x37,0x2f,0x9a, + 0xa0,0x1e,0xb1,0x41,0x82,0x95,0xf0,0xad,0xe5,0xca,0xb9,0xb5,0xa0,0x4c,0x8c,0xb, + 0xb3,0xf,0xb,0x9b,0x76,0xf1,0xce,0x1c,0x7d,0x84,0xa1,0x8f,0xb,0x51,0x46,0xc8, + 0x49,0x77,0xfa,0xbb,0xce,0x5c,0xb9,0xc1,0x70,0x99,0x93,0x3c,0xc9,0xa6,0xbd,0x10, + 0x93,0xc1,0xba,0xee,0xf1,0x33,0x6e,0x61,0x8b,0x1c,0x17,0x78,0xef,0xda,0xa0,0x40, + 0x77,0xa5,0xbd,0x4c,0xea,0x1a,0x81,0xb1,0x4c,0x18,0x8a,0x56,0xd4,0xb6,0x9a,0xbb, + 0x50,0x25,0xb4,0x20,0x43,0x62,0xec,0xc2,0x9e,0xa4,0xc2,0xa9,0x81,0x8a,0xab,0x10, + 0xb3,0x88,0x74,0x90,0xf0,0x34,0x58,0x8e,0x93,0x53,0x3d,0x85,0x8b,0x34,0xef,0xb9, + 0xc9,0xe8,0x51,0x3c,0x9b,0x20,0xd2,0x78,0x4,0x1e,0x7e,0xd3,0xd1,0xe7,0xab,0xd1, + 0x43,0x30,0xd7,0x19,0xae,0x65,0x3b,0x5b,0x6f,0x7e,0x14,0x19,0xaa,0xb6,0x9c,0x85, + 0x8d,0x32,0x5c,0xb8,0x8f,0xa,0x41,0xdf,0x38,0xf4,0x5a,0x2b,0xee,0xd6,0x96,0x6c, + 0x6e,0x51,0x35,0x36,0x91,0xcd,0x6f,0xb0,0xaa,0xb2,0x4b,0xf3,0xdd,0xa2,0x90,0xf0, + 0xb4,0x35,0x5e,0xf1,0xc7,0xae,0x81,0xaa,0x7a,0x2d,0xd4,0x34,0xab,0x13,0xed,0xc0, + 0xd0,0x22,0xdb,0x37,0xab,0x86,0xda,0xcc,0x85,0x3d,0x29,0x55,0x15,0xaf,0x75,0x9a, + 0x10,0x2b,0xfc,0x4c,0x41,0xa3,0x8,0xd5,0xe9,0x4a,0x1b,0x3d,0xda,0x14,0x4f,0xc4, + 0x63,0xe4,0x27,0xa0,0x36,0xa,0x5b,0x85,0xd0,0xee,0x89,0x86,0x18,0xeb,0x87,0xe8, + 0xfc,0xed,0x62,0x9f,0xa7,0x33,0x89,0xf6,0x7e,0x31,0x9a,0x80,0xb,0x6d,0xec,0x63, + 0x6a,0x92,0xac,0x4b,0x6d,0xf8,0xd9,0xc9,0x8a,0x51,0x88,0x53,0xa6,0x84,0x6a,0x4c, + 0xe,0xf7,0xb,0xb1,0x91,0x8e,0x6f,0x80,0xed,0x87,0xfe,0x88,0x65,0x1,0xac,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x64,0x5e,0xc4,0xe9,0xd3,0x8b,0x35,0x54,0x66, + 0xf2,0xfa,0xa5,0xe4,0x5b,0xcf,0x58,0x29,0x74,0xdb,0xa1,0xeb,0x4a,0x48,0xad,0x71, + 0xd6,0x5c,0x80,0xe8,0x88,0x9a,0x4c,0xc,0xd6,0x9,0x64,0x70,0x1f,0x29,0x3,0x6f, + 0xd4,0x3b,0x6c,0x76,0xf1,0x71,0x16,0x36,0xdb,0xda,0x1d,0xa6,0x27,0x3d,0x74,0x74, + 0x34,0x55,0xd6,0x8c,0x6d,0x53,0x5f,0x22,0x6a,0x19,0x5f,0x69,0x6a,0xe6,0x13,0x26, + 0x55,0x66,0x54,0xad,0xe9,0x38,0xfc,0x3f,0x82,0x20,0x46,0x29,0x1,0x13,0x8d,0x8f, + 0x63,0x92,0xe9,0x8,0x5e,0xa1,0xcb,0x0,0x91,0xa2,0x22,0x1,0x43,0x89,0xeb,0xb, + 0xa1,0x5f,0x88,0xbd,0x38,0x66,0x28,0x11,0xd7,0xc8,0x82,0x80,0x51,0xe,0xb0,0x49, + 0x60,0x71,0xa8,0x1e,0x51,0x1e,0x2b,0x4,0x9a,0x32,0xa2,0x7d,0xd5,0x2f,0x6c,0x77, + 0x1a,0xf9,0x68,0x13,0x4e,0xf4,0xf2,0x97,0xcb,0x49,0xed,0x4d,0x43,0xae,0x9f,0xe7, + 0x19,0x8d,0xfc,0xfa,0x6c,0xde,0xd6,0xb4,0x9d,0xb2,0x22,0xc3,0x9f,0x35,0x0,0x6c, + 0xa2,0x97,0x46,0xbe,0x72,0xe,0x25,0xb2,0x65,0xf7,0x1,0x4d,0x35,0xb8,0x78,0x68, + 0x94,0x93,0x61,0xc5,0x4e,0x74,0xc5,0x19,0x67,0xac,0xb3,0xe5,0x4a,0xcd,0x9e,0x42, + 0x56,0x5a,0x24,0x52,0xc1,0x52,0xe3,0xa3,0x55,0x57,0xc3,0x37,0xe1,0x44,0xa8,0x49, + 0x40,0x8,0x71,0x13,0x59,0xe,0x14,0x70,0xe5,0x2b,0x0,0x15,0x3,0x65,0x85,0x3, + 0x41,0x55,0x7a,0xa7,0x48,0xd2,0xc0,0x4e,0x8a,0x86,0x40,0x2f,0xc6,0xbf,0x96,0xbd, + 0x24,0xc9,0xe,0xd9,0x26,0x21,0xf,0xe8,0xaa,0x7d,0x8,0x4d,0x3a,0xfa,0xa8,0x1c, + 0x47,0xf7,0x6e,0x35,0x17,0xd0,0x55,0x9b,0x3b,0xde,0x66,0x65,0x8c,0xc4,0x37,0x37, + 0x68,0xb9,0x86,0x5c,0x10,0x44,0xc5,0x53,0x86,0xb5,0xb8,0x3d,0xdd,0x1,0x1,0x5d, + 0xac,0x21,0x1b,0x3c,0x91,0xae,0x14,0xe0,0x2,0x76,0x59,0xd0,0x5f,0x83,0x96,0xa5, + 0xd5,0x74,0xaf,0xcd,0x36,0x3e,0x6e,0xf1,0x9c,0x3e,0x4f,0x9d,0x8a,0x7d,0x0,0x7, + 0xea,0x94,0x38,0xa4,0xce,0x7c,0x2a,0xfe,0xb5,0xa1,0x77,0xe4,0xcc,0xfb,0x36,0x15, + 0xdc,0xc9,0x22,0x9a,0x7d,0xe4,0x88,0xac,0xb2,0x29,0x5c,0xe3,0x9a,0x55,0x89,0xac, + 0x48,0x2,0xc9,0x18,0x53,0x53,0xc0,0xd7,0x6,0x1b,0xa3,0x68,0xd4,0x95,0x6d,0x6e, + 0x5a,0xe1,0x20,0xe3,0x1f,0x1d,0xda,0x5e,0x74,0xad,0xe,0x40,0x5d,0xb1,0xe4,0x7, + 0x3e,0xc1,0x4b,0x2a,0x71,0x41,0x23,0xd7,0x1b,0x99,0x3d,0x9b,0x67,0xa,0xdc,0xe3, + 0x5b,0x96,0xf3,0x98,0x44,0xbb,0x63,0xc6,0x8,0x51,0x4a,0x77,0xb0,0xad,0x8,0x6c, + 0xde,0x14,0xaa,0x5c,0xb5,0x41,0x7a,0x57,0x9b,0x46,0xc5,0xf5,0xd1,0x25,0x78,0x85, + 0x16,0xfc,0x92,0x68,0x64,0xac,0xdf,0xb2,0xc5,0x4f,0x20,0x28,0x67,0xc2,0x93,0x4f, + 0x2f,0xe0,0x1e,0x75,0x27,0x1,0xd3,0xc7,0x60,0xa,0xde,0x79,0x76,0x75,0x5b,0xbf, + 0x69,0xdb,0xc2,0x80,0xe7,0xe6,0x75,0xf,0x98,0xc7,0xa6,0xec,0x9d,0x77,0xdb,0x56, + 0xa7,0x34,0x32,0xf3,0x57,0xda,0x6e,0xd,0x45,0x77,0xdf,0x7c,0xfa,0x79,0x21,0x79, + 0xaf,0x50,0xa8,0x32,0xeb,0x4a,0x86,0xbe,0x78,0xd5,0x4e,0x7d,0xb8,0x67,0x10,0x44, + 0x31,0x11,0xc1,0x2c,0x11,0x99,0x36,0x47,0x56,0xe4,0x9e,0x57,0xcd,0x21,0xe1,0xf3, + 0x5f,0xef,0x21,0xc4,0x53,0x1e,0xe5,0x18,0xef,0x97,0xff,0x7b,0x4,0x95,0x49,0x60, + 0x7e,0x57,0x17,0x64,0x88,0x2d,0x4d,0x87,0x34,0x85,0xc4,0x6,0x9c,0x89,0x20,0x23, + 0x86,0x91,0x74,0xc3,0x74,0xd8,0xb4,0x2c,0xfc,0xd,0xee,0xf2,0x9e,0xea,0x2c,0x25, + 0x3e,0x81,0xbb,0x66,0xa6,0x12,0x79,0xda,0x94,0xb4,0x11,0x4c,0x5,0x1a,0x13,0x3b, + 0x5f,0x0,0xc3,0xbb,0xa6,0xba,0xdf,0xdb,0x58,0x95,0x71,0x18,0x8a,0x26,0x95,0x76, + 0x2a,0xa6,0x42,0xa9,0x9b,0x10,0x8,0x63,0xf5,0xd1,0xdd,0x3c,0x17,0xf6,0xa1,0xa9, + 0x90,0x2,0x5d,0x70,0xeb,0x34,0x2d,0xc0,0x18,0x74,0x91,0xa6,0x90,0x1a,0xc8,0x4e, + 0x63,0x13,0x63,0xfa,0x36,0xd0,0x4e,0x5c,0xbd,0xa0,0x81,0x61,0x61,0xc5,0x77,0x26, + 0x4a,0x41,0x81,0xe4,0x1c,0x74,0xbe,0xbf,0x88,0xe0,0x40,0x17,0xf8,0x8b,0xff,0x9c, + 0xe0,0xb1,0xb0,0x69,0x9d,0xe4,0xae,0xf,0xd5,0x9c,0xb2,0xe8,0x4,0x2f,0x2f,0x0, + 0x48,0x39,0xd4,0xfc,0x64,0x73,0x16,0x7b,0xe,0xe6,0x0,0xb3,0x7d,0x90,0x84,0x97, + 0x1a,0x89,0x45,0x31,0xc5,0xef,0x68,0xd3,0x23,0x30,0x84,0x89,0xdd,0x21,0x2b,0xaa, + 0xad,0xc3,0x35,0xb4,0xa4,0x88,0xe1,0x31,0x6d,0x8c,0x71,0x4d,0xb1,0x29,0x1e,0xcc, + 0xd2,0xa7,0xce,0xc0,0x26,0x22,0xe8,0x7d,0x6,0xc2,0x8b,0xd9,0x82,0x69,0xe7,0xde, + 0xe7,0x8a,0x62,0xe8,0x6c,0x68,0xa5,0x31,0x83,0xbc,0x3c,0x6f,0x6a,0x5a,0x1c,0x66, + 0x6f,0x87,0xd4,0x49,0xd2,0x78,0x74,0x7a,0xee,0x5c,0x94,0x39,0x1b,0xee,0x61,0x39, + 0x9e,0xd,0x59,0xc,0xaf,0x67,0x6a,0x8d,0x3a,0x9,0xd5,0x80,0x33,0xac,0xf4,0x8d, + 0x2e,0x9a,0x6d,0xcf,0xf3,0x23,0xee,0x70,0x2f,0x3a,0xe4,0x0,0xc6,0xab,0xb7,0x8f, + 0xc6,0x32,0x40,0xdc,0xbe,0x66,0xc9,0x50,0x23,0x95,0x4e,0xbd,0x42,0x72,0xc2,0x63, + 0x1,0xac,0x99,0x1a,0xa3,0xd7,0x8c,0x93,0x2,0x7a,0x81,0xb0,0x56,0xb1,0xe5,0xc0, + 0xd9,0x64,0x29,0xe6,0x2e,0x7c,0x51,0x67,0xb0,0xd3,0x76,0x36,0xf6,0xcd,0x73,0xd4, + 0xb3,0xd0,0x8e,0xd2,0xd6,0x22,0x67,0x15,0x9,0xa3,0x0,0x4a,0xc2,0x4a,0xf9,0x58, + 0xf5,0xd7,0xc5,0x7f,0x4,0x69,0xb3,0xbb,0x28,0x40,0x12,0x59,0x4c,0xc3,0x71,0x4a, + 0xb9,0x1,0xcf,0xf0,0xa9,0xe6,0x7d,0x1d,0xb,0x5a,0xeb,0x6a,0x74,0x30,0x91,0x95, + 0xd4,0x9d,0x8,0xf,0xa4,0x7,0xe0,0x28,0xc9,0x1a,0x45,0xb9,0x3d,0x22,0x94,0x8, + 0x98,0x4f,0xec,0xfe,0xce,0xf1,0x81,0x75,0xcb,0xcf,0x76,0x13,0x91,0xef,0x33,0x4c, + 0xff,0x5,0x67,0x7c,0xf9,0x88,0x18,0x24,0x90,0xf2,0x30,0xe6,0xc9,0x7f,0x86,0xe4, + 0xb4,0x2d,0xcd,0x28,0xb1,0x42,0xa5,0x50,0x4a,0x69,0x93,0xf8,0x24,0x2,0xd2,0xe6, + 0x52,0x4,0x4d,0x4b,0xfc,0xa4,0x43,0xf0,0x98,0x62,0x8a,0xb6,0x55,0x7f,0xfe,0x61, + 0xd2,0x54,0xea,0x12,0xa2,0x8,0x10,0xc3,0xd9,0x62,0x11,0x72,0xa8,0xab,0xd9,0xe6, + 0xcf,0xac,0x21,0xab,0x7c,0x7,0x67,0x94,0x35,0x6b,0xea,0xce,0x2c,0x9f,0xaa,0xab, + 0x26,0xab,0x1e,0x1f,0x1,0x41,0x13,0x14,0xe1,0x98,0xb2,0x2c,0x8a,0x51,0x14,0xc4, + 0x2c,0xb9,0xa4,0x5d,0x39,0xca,0x3e,0x7,0x54,0x76,0x61,0xde,0xa4,0xfb,0x6c,0xd3, + 0x84,0xb1,0xb1,0x8b,0x45,0xd8,0xd4,0x90,0x47,0xba,0xe1,0x8f,0x12,0xc8,0x81,0xb1, + 0x36,0xdb,0x6c,0x8e,0x62,0x34,0x3,0xc4,0xfe,0xdc,0x9f,0x66,0xe5,0x51,0xbc,0xdb, + 0xa0,0x85,0x2,0xed,0x96,0xc2,0xcf,0xf9,0x83,0xbc,0x13,0x97,0xa,0xe,0xf4,0x40, + 0xd,0xf6,0xe7,0xc7,0xcf,0x2f,0xdd,0x8e,0x3a,0x9b,0xb8,0xe4,0x10,0x31,0x89,0x38, + 0x5b,0x18,0x34,0x6b,0xd7,0xb4,0x4c,0x6,0x35,0x6,0x15,0x56,0xb8,0x35,0x67,0xad, + 0x85,0x75,0xcf,0x66,0xfc,0x83,0x41,0x6a,0x9e,0x6b,0x42,0xc1,0x52,0x52,0x98,0xce, + 0x4d,0x80,0x49,0xff,0x13,0x51,0x26,0xe1,0x62,0x7d,0x12,0xc8,0x11,0x44,0x1d,0xc6, + 0xd7,0x69,0xc4,0x8d,0x50,0xe9,0xe0,0x8d,0x5a,0xf3,0x7b,0x3b,0xb2,0x0,0x94,0xd5, + 0x79,0x29,0x25,0x96,0x3d,0xe7,0x81,0x26,0x4d,0xe,0x18,0xfe,0x94,0x62,0xba,0xe1, + 0xd1,0xb7,0x6a,0x53,0xfb,0xa1,0xdb,0x6d,0x3c,0xf5,0xb1,0x95,0xb4,0x2a,0x9a,0x53, + 0x4b,0xa6,0x91,0x67,0xde,0x42,0x36,0x7c,0xa7,0x1c,0x7b,0x47,0x94,0x66,0x1a,0x25, + 0x3c,0x89,0x72,0xe8,0xfe,0xd8,0x87,0xdd,0x8d,0x79,0xdf,0x4b,0x27,0x3e,0x3c,0xeb, + 0x8d,0x79,0x87,0x30,0xc0,0x4e,0xc4,0xc2,0xc6,0x8e,0x2f,0xc2,0x6a,0xd2,0xb5,0x30, + 0xb9,0xc2,0x9a,0x2e,0x2b,0xd,0xb,0x5f,0xb7,0xc3,0x5e,0xd4,0xd1,0xaf,0x6d,0x7e, + 0xee,0x3b,0xb1,0x5,0xf,0xf9,0xd2,0x11,0xee,0x4b,0x7f,0xf6,0x3a,0x77,0x2e,0x3, + 0x51,0x40,0x11,0xb9,0x1a,0xbc,0x7a,0xd1,0x8e,0xd0,0xb,0xf7,0x79,0xd9,0x38,0xef, + 0x1e,0x14,0xfc,0xa3,0x1e,0x7c,0x9f,0xd3,0xc3,0xfd,0xac,0x6e,0xde,0xd5,0xe6,0x4e, + 0xae,0x9,0x11,0x13,0xd7,0x4,0xcd,0x99,0x1e,0xb9,0xdc,0x85,0xd8,0x10,0xb7,0x31, + 0xe7,0x20,0x80,0x67,0xa1,0xa,0x41,0xa3,0xb3,0x92,0x2c,0x52,0x87,0x68,0x8d,0xc0, + 0x4c,0x76,0x81,0x87,0x8f,0xc5,0xc7,0x92,0x2d,0x94,0xed,0xaa,0x29,0xc4,0x39,0x1f, + 0x26,0x34,0x26,0xee,0x5,0x99,0x2,0xa2,0xbd,0x23,0xab,0xf7,0x60,0xfe,0xac,0x8, + 0xdd,0x98,0x44,0x51,0x2a,0x9a,0xcd,0x3b,0xec,0xa9,0x8d,0x71,0x20,0xfa,0x96,0xb8, + 0xf9,0x1f,0xae,0x2e,0x88,0x4b,0x6a,0x18,0x89,0xbd,0x62,0x2b,0x4c,0x58,0xf0,0x4b, + 0xa5,0x9e,0x31,0x2e,0x3c,0x32,0xc,0xe5,0x7a,0xdc,0x33,0x1e,0xdc,0x63,0xf3,0x6c, + 0x95,0x68,0x41,0xed,0xae,0x3d,0x58,0x3a,0xe3,0xd5,0xfa,0x2f,0x52,0x46,0xcf,0x49, + 0x70,0xe1,0x61,0x24,0x33,0xb,0x5e,0x88,0x79,0x2,0x86,0x7c,0x12,0xce,0xcc,0x7f, + 0xd8,0x4,0xb5,0x93,0x24,0xf0,0x9,0x83,0x6e,0x4c,0x3c,0x51,0x41,0x12,0xa1,0xb3, + 0xe8,0x11,0xc3,0x4a,0x82,0x67,0x35,0x1e,0x75,0x44,0xa8,0xda,0xba,0xdb,0x1,0x91, + 0x21,0x70,0xb7,0xdb,0xb8,0xfb,0xd3,0x55,0xf9,0x7,0xd0,0x62,0x76,0x94,0xf4,0x5b, + 0x67,0xdb,0x40,0x2a,0x7b,0xf5,0xc1,0x69,0x10,0x98,0xfc,0xd4,0x41,0xf3,0xc7,0x6b, + 0x3e,0x58,0x6d,0x8f,0xed,0x83,0xa,0x2c,0xa4,0x49,0x88,0x44,0xfa,0x24,0x5d,0x2e, + 0x2c,0x90,0x33,0x54,0x29,0xb1,0x2f,0xcc,0xa3,0xc6,0xf9,0xe6,0x61,0x6b,0x6e,0xfe, + 0x49,0x97,0x31,0xbd,0x68,0x52,0xd0,0x35,0xef,0x26,0x77,0xe3,0xfa,0x23,0x2b,0x94, + 0xd0,0x5f,0x7b,0xad,0x3b,0x4e,0xca,0xa1,0x91,0xe4,0xf0,0x84,0x31,0x79,0xb2,0x6a, + 0xa7,0x25,0x4b,0x90,0x9a,0xe8,0x65,0xfe,0x4c,0x69,0x9d,0xa8,0x66,0xf4,0x16,0x1e, + 0x1f,0x8b,0x6c,0xe4,0x34,0x49,0xda,0x99,0x8b,0x92,0x3d,0x37,0x34,0xb2,0x1,0x15, + 0xec,0xae,0x5,0x88,0xf0,0x0,0xd,0xe2,0xc,0x68,0x90,0x5d,0x12,0x7a,0xe9,0xc7, + 0x1c,0x7,0xa1,0x47,0xd7,0x7a,0x61,0xc0,0xd3,0x8c,0x26,0x35,0xe2,0x95,0xc4,0x64, + 0xf4,0x98,0x67,0x54,0x6d,0x6a,0x39,0xb8,0xb8,0xed,0x24,0x77,0x8a,0x62,0x17,0x5b, + 0x7b,0x39,0xed,0xa1,0x19,0x30,0x19,0xa8,0xf4,0x66,0x90,0x4,0xea,0xd2,0x54,0xfa, + 0x58,0x2e,0x87,0xe3,0xa0,0x63,0xd8,0xd,0xd5,0xfc,0xa4,0xea,0xbb,0x66,0x20,0xf5, + 0x74,0x9,0xc7,0xcd,0x1f,0x81,0xc1,0x8,0x86,0x92,0xbe,0x9b,0x18,0x4e,0x19,0x3b, + 0x6c,0xa7,0xd5,0xa8,0x27,0x5b,0xa6,0xf5,0xa9,0x5b,0x9,0x9b,0x7b,0xd3,0xc2,0x8b, + 0x4d,0x6d,0x27,0xd,0xc1,0xec,0x8,0xef,0xe4,0x8c,0x12,0x4e,0x75,0x85,0x89,0xe3, + 0x6c,0xc8,0xa,0x4b,0x40,0xa,0xb2,0xa7,0x75,0x40,0xee,0xf2,0xd1,0x34,0xe5,0xcb, + 0x56,0x5a,0x80,0xf6,0x89,0x94,0xac,0x27,0x30,0x83,0xd5,0xb0,0xea,0x6a,0x1f,0x6b, + 0x9f,0x6e,0x23,0xf7,0x38,0xd2,0x13,0xe6,0x1d,0x60,0x12,0xaa,0x65,0x73,0xf8,0x54, + 0xb,0x64,0x2a,0x69,0x99,0xe5,0x8e,0x72,0x71,0xc7,0x33,0xa3,0x99,0x2e,0x27,0x39, + 0xad,0xb4,0x5a,0x84,0xf9,0xcf,0x36,0x52,0x11,0x24,0xac,0x6d,0xc9,0xf2,0x26,0x76, + 0xa1,0x1f,0x88,0xa9,0x6e,0x72,0x9e,0x6b,0xe3,0x8e,0xae,0xd0,0x69,0xd1,0x36,0x68, + 0xaf,0x90,0xd8,0xcb,0x6e,0xa9,0xe5,0xeb,0x34,0x34,0xdf,0x64,0x94,0x92,0x25,0x11, + 0xfa,0x3c,0xbd,0xa3,0x8d,0x71,0x2e,0x1a,0x8,0x5a,0x9d,0x54,0x61,0x83,0xd1,0x4f, + 0x61,0x11,0x85,0x3f,0x2a,0x55,0xfb,0xca,0x5c,0x5d,0x58,0x36,0x38,0x42,0xd,0x9c, + 0xb8,0xee,0xc9,0xcf,0xa5,0x71,0xff,0x1d,0xa8,0x21,0x5,0x9d,0x57,0xe9,0xd5,0x7b, + 0x9f,0x69,0xa6,0x7e,0x77,0x69,0x6a,0xa8,0x34,0x15,0x35,0x14,0x62,0xa3,0x39,0xfc, + 0xc0,0xe1,0x29,0xa5,0x25,0x9d,0xe6,0xe6,0x4,0xe9,0x99,0x41,0x47,0xd4,0xc6,0xd9, + 0x1f,0xd5,0xca,0x10,0x36,0xfb,0x22,0xe3,0xa9,0x5d,0x4,0x18,0xa8,0x3f,0xdb,0x45, + 0x8c,0xc1,0x89,0x67,0x84,0xa4,0x92,0x83,0x44,0x37,0x62,0xf4,0x57,0x2c,0x68,0x94, + 0xe8,0x52,0x2b,0x6b,0x90,0x2e,0xf2,0xb4,0x29,0x57,0x17,0xcf,0x92,0xcd,0xc0,0xb7, + 0x22,0xda,0x54,0xa3,0x7e,0x1a,0x14,0x6c,0x8,0x2d,0xbf,0x9c,0xaa,0x47,0x44,0xb3, + 0x3a,0x25,0xd3,0x92,0x75,0x10,0xaa,0x92,0xee,0x25,0x56,0xc4,0x65,0x6a,0xb,0x7a, + 0x49,0xc4,0x61,0x37,0xc7,0x9d,0x76,0x86,0xcc,0x70,0x3d,0x39,0x93,0x26,0xd1,0xd9, + 0x1,0xd4,0x12,0x59,0x13,0x2c,0x80,0x9b,0x10,0x4a,0xde,0xb9,0x6e,0xac,0x40,0x6c, + 0x91,0x47,0xc2,0x6d,0x9,0x55,0x45,0x6b,0x1a,0x7d,0x3,0x83,0xd0,0x13,0xfa,0x9e, + 0xd8,0xc5,0x33,0xaf,0x33,0xd6,0xee,0x54,0x80,0x69,0x52,0xc1,0xcc,0x49,0x4c,0xc, + 0x2,0x9a,0x7b,0xe0,0x25,0xfc,0x9b,0x98,0xf1,0x92,0x6,0x64,0x9a,0xab,0x88,0x66, + 0x33,0x77,0x4d,0xb4,0x3b,0x1f,0x40,0x28,0x75,0xe9,0xcc,0xbe,0xc,0xfd,0x87,0x7d, + 0xb8,0x42,0xb6,0xbf,0x1c,0xa,0x53,0x4a,0xc4,0xe4,0xb0,0x5d,0x58,0x1b,0x5b,0xd2, + 0x27,0x6,0x24,0xd4,0x9b,0xde,0xc7,0xdb,0xca,0xfb,0x54,0x77,0xee,0x98,0x80,0x2f, + 0x72,0xa3,0xe7,0xaa,0xe,0xc9,0x52,0xea,0x79,0xe0,0x16,0x9e,0xe4,0x77,0xfc,0x18, + 0x11,0xc2,0x2d,0xa1,0xfe,0x2,0x29,0x4a,0xec,0x73,0x74,0xc5,0xee,0x74,0x0,0x69, + 0xba,0x2c,0xf2,0x7b,0xd2,0xf6,0x8c,0x14,0x1b,0xe,0x8b,0xee,0x98,0x0,0x16,0x2a, + 0x5a,0xf7,0xee,0x96,0x71,0xa0,0x7a,0x7a,0x87,0xd6,0xc7,0x19,0x4f,0xea,0xcf,0x84, + 0x51,0xa,0x63,0xdf,0xac,0xd2,0xd0,0xf,0x66,0xdc,0x2a,0x44,0x9a,0xb4,0x3e,0x33, + 0xde,0xbb,0x27,0xb1,0xc6,0xcb,0xcf,0x4c,0x7c,0xf3,0xd0,0xb0,0x52,0xba,0x64,0x96, + 0x64,0xec,0x76,0x68,0x35,0x4,0xd0,0x61,0xd3,0x53,0xb3,0xb5,0x99,0xb2,0xdf,0x52, + 0xf9,0x86,0x7a,0xdb,0x2c,0x91,0x34,0x22,0xa3,0x56,0xbb,0x91,0x98,0x4d,0x24,0x27, + 0xa2,0x6d,0x8,0xd8,0x56,0x38,0x9b,0x2c,0xbf,0x5e,0xfa,0xa5,0xd2,0xd7,0x30,0xaa, + 0x3a,0x59,0xdc,0x50,0x6,0x9a,0x64,0x71,0x3b,0x74,0xb9,0x45,0xb9,0x54,0xe3,0x8b, + 0xad,0xb3,0x14,0xdd,0xd4,0x3c,0xb3,0xaa,0x25,0xff,0xfd,0x75,0x37,0x50,0xe,0x8f, + 0xdc,0x81,0x3a,0x40,0x47,0x1d,0xef,0xd3,0x86,0x8f,0x36,0x1d,0xf2,0x48,0x11,0x1, + 0x2d,0x49,0xf1,0x38,0x5b,0x31,0xf1,0xf6,0x38,0x8b,0x37,0xa0,0x18,0x9c,0x85,0x9, + 0xd0,0xe2,0x9a,0x3f,0x50,0xf4,0xfc,0xed,0x43,0xd9,0xf5,0x62,0x97,0x7d,0xf3,0x8a, + 0xd5,0x47,0x57,0xf1,0x82,0xa5,0x71,0x5d,0x1a,0xb5,0x7b,0x12,0x8c,0x92,0x5c,0x6f, + 0x4e,0x9c,0xb9,0xc8,0x52,0x27,0x95,0xce,0x4a,0xbf,0x31,0xab,0x9c,0x1f,0x73,0x61, + 0x19,0xd8,0xaa,0x54,0x57,0x96,0x42,0xe4,0x95,0x7b,0xd1,0xd7,0xf3,0xba,0x19,0x25, + 0x4d,0x40,0xf9,0xeb,0x9e,0xe1,0x5f,0x8,0x3f,0x85,0xfb,0x56,0x35,0x61,0x78,0x93, + 0x4,0x40,0x4b,0xce,0x3a,0x18,0xbc,0x46,0x55,0x88,0xdb,0x3f,0x51,0xb0,0xc0,0xf3, + 0x2e,0xd4,0x48,0x9b,0x9b,0x62,0x29,0xc2,0xe2,0x12,0x17,0x5f,0x65,0x19,0x53,0xdb, + 0xb2,0x72,0x76,0xc1,0x14,0x65,0xef,0xb9,0xaf,0x94,0xb2,0x28,0xce,0x35,0xd7,0xd4, + 0xe5,0x4d,0x1c,0x76,0xf5,0xb0,0xc6,0x65,0xe5,0x45,0xd0,0xb8,0xc9,0xf5,0xc0,0xbb, + 0xf1,0x14,0x8e,0x13,0xef,0x1c,0xa8,0x3,0xa0,0x65,0xfd,0xda,0x11,0xa7,0x69,0x78, + 0x7a,0xd7,0x69,0xfa,0x87,0x40,0x89,0x6b,0x96,0xc4,0x68,0x55,0xdd,0x10,0x48,0x50, + 0x69,0xa0,0xd7,0x90,0xd0,0x40,0x50,0xb2,0x97,0xb7,0x78,0x4e,0x95,0x13,0xfb,0x5c, + 0x76,0x47,0x22,0x39,0xf5,0x4e,0x8a,0xf,0x2e,0x6,0x17,0x22,0x5,0xea,0xd1,0x3b, + 0xc,0x9a,0x60,0xa8,0xce,0x52,0x87,0x73,0xba,0xab,0xe5,0x6c,0x76,0x91,0x1a,0xcd, + 0x15,0x48,0x88,0xd4,0x5d,0x85,0xcc,0x76,0x3b,0x2c,0x97,0x24,0x38,0x3b,0x84,0xa1, + 0x5a,0x1,0xa6,0x1a,0x79,0xa3,0xc4,0x91,0x18,0xbf,0xb5,0x79,0x24,0x57,0x37,0xae, + 0x69,0x8b,0xc7,0xd5,0x7e,0xbe,0x99,0x11,0xa1,0x2c,0x68,0x34,0x59,0x82,0x7,0x9f, + 0xcc,0xf7,0x5d,0xeb,0xa2,0x25,0xa2,0x39,0x85,0x55,0x81,0x10,0xed,0x6e,0xc5,0xb2, + 0xb5,0x5a,0x17,0xc3,0xa0,0x4d,0xd1,0x98,0x84,0xa6,0x23,0x68,0xaa,0x1,0x63,0x91, + 0xa2,0xb9,0x59,0xa7,0x5b,0xbe,0x3e,0x54,0x90,0xbb,0x5,0x2d,0xf7,0x88,0x81,0x15, + 0x1f,0x9f,0xff,0x2e,0x6a,0x4f,0x9d,0x31,0xd0,0x11,0xa8,0x45,0x56,0x8,0x9b,0xb4, + 0x5a,0x27,0xa1,0x29,0x57,0x62,0xbe,0xc3,0xe4,0x28,0xb1,0x6d,0xad,0xc,0x4,0x9e, + 0x81,0x87,0xe6,0x71,0x69,0x91,0xc4,0x26,0x18,0x94,0xc1,0x27,0x6b,0x26,0xc7,0x50, + 0xf6,0x81,0x2e,0x7a,0x5b,0x3f,0x3b,0x91,0xed,0x6a,0xc0,0xbe,0xb3,0x56,0x8a,0x97, + 0x3c,0x27,0x57,0x66,0x3,0xba,0x86,0xc3,0xb5,0x8c,0xc0,0x52,0xc2,0x9b,0xe6,0x4b, + 0xa,0x94,0x83,0x31,0x54,0xee,0xb4,0xff,0xee,0x2d,0x76,0xe9,0x82,0x72,0xb1,0xd3, + 0x56,0x1,0xd9,0x20,0xb4,0xc1,0x22,0x47,0x4a,0x94,0x59,0xb5,0x1c,0x9a,0x3f,0x2, + 0x35,0x85,0x35,0x94,0xb0,0x69,0xc3,0x30,0xab,0x49,0xf9,0xa1,0x69,0x7c,0xe7,0x2d, + 0xb8,0x4e,0xf7,0x83,0xdb,0xb5,0x15,0x15,0x1d,0x12,0x82,0x86,0x21,0xf1,0x1d,0xa, + 0x7c,0xde,0x4,0x84,0xf8,0x40,0xc1,0xb0,0x8e,0x19,0x5f,0xea,0x11,0x8b,0x92,0xba, + 0x6d,0x9f,0x5,0xf4,0xac,0x53,0xd2,0x96,0xac,0x99,0xf4,0x19,0x62,0xd,0xae,0x77, + 0xa5,0x66,0xee,0xa8,0x23,0xbb,0xdc,0x87,0xb5,0x41,0xdf,0x12,0xd9,0xd4,0xac,0x51, + 0x5,0x1f,0x27,0x95,0x26,0xa1,0x1b,0xab,0x6e,0x13,0x3b,0xc0,0x7d,0xb2,0xe0,0xcc, + 0x9c,0x89,0x14,0x25,0x4a,0x8c,0xc9,0x53,0xc3,0xfc,0xbc,0x7c,0x29,0x1,0x2c,0x4a, + 0xbe,0xc7,0x5c,0x40,0xb0,0x52,0x9e,0xbf,0x26,0xd3,0xcb,0x85,0x16,0x20,0xdc,0xf5, + 0xd6,0xe,0x34,0xd,0x9b,0xd6,0xc8,0xd5,0x35,0x60,0x24,0xb3,0x16,0xf9,0xed,0xe4, + 0x5c,0x13,0xce,0x85,0x8d,0x96,0x9f,0x82,0x78,0x28,0xa8,0x5b,0x5c,0x30,0x61,0xba, + 0x88,0xf0,0x98,0xd2,0xbe,0xca,0xfd,0xbf,0x8c,0xfe,0x9d,0x1,0x24,0xf6,0xe8,0x36, + 0x41,0x1e,0xa5,0x8,0x71,0xc6,0xa5,0x88,0x20,0x62,0x97,0xa7,0xdc,0xfe,0x5,0xaa, + 0x2d,0xad,0xae,0x28,0xc5,0xae,0xc7,0xce,0x3c,0xf6,0xae,0x2,0x34,0x6b,0x43,0x7c, + 0x0,0xec,0x23,0x6f,0xcb,0xcf,0x70,0x83,0x1,0xed,0x83,0x73,0xc8,0xce,0x82,0xc6, + 0xd,0x1,0x61,0xbc,0x4a,0x4a,0x67,0x8d,0x27,0xaf,0x50,0xa7,0x91,0x48,0x84,0x25, + 0xfc,0x84,0x2e,0xab,0xc,0xc0,0x8b,0xcf,0x3e,0xe,0x5c,0xa4,0xe7,0x8a,0x7f,0xea, + 0xaa,0x59,0xa7,0x12,0x1,0x4b,0x5e,0x40,0x3a,0x1f,0xa3,0x14,0x38,0xd8,0x98,0x3e, + 0xf6,0x5c,0x33,0x53,0xd4,0x62,0x64,0x46,0x68,0x9d,0x64,0x5,0x93,0x40,0xd1,0x14, + 0x55,0x42,0xe4,0xaa,0xdb,0x66,0x82,0x6a,0x8f,0x89,0xd2,0x80,0x3a,0xbb,0x6c,0x46, + 0x3d,0xbc,0x4a,0x4a,0xde,0x6f,0xec,0x1f,0x65,0x86,0xac,0xcc,0xc9,0x52,0x9b,0x6c, + 0xfa,0xe1,0x43,0x37,0xb5,0xae,0x8b,0xce,0xf,0x52,0x64,0x2d,0x5c,0xb7,0xae,0x1e, + 0x1d,0xa,0xfe,0x39,0x67,0xa5,0x14,0xaf,0x11,0x5c,0x42,0xa1,0xce,0xda,0x20,0x77, + 0x40,0xd2,0x20,0x84,0xb5,0x45,0xcd,0x2c,0x15,0x19,0xf7,0x2d,0x72,0x9c,0xd5,0x2e, + 0xf7,0xa6,0x71,0x34,0xaa,0xc7,0x28,0xf5,0x94,0xa2,0xdc,0x22,0x8a,0xd0,0x21,0x59, + 0x61,0xd3,0x83,0x17,0x95,0x9e,0x78,0xec,0x96,0x36,0xef,0x32,0x3a,0xa5,0xa7,0xc9, + 0x56,0x94,0x72,0x9e,0x84,0x28,0xc9,0xba,0x91,0x96,0x20,0xab,0x67,0x8a,0xc7,0x45, + 0x76,0x96,0x5a,0xcc,0x42,0x72,0xe2,0x68,0xa3,0x59,0x1a,0xb,0x59,0xe7,0x28,0xbf, + 0x51,0xb1,0x6b,0xb1,0xae,0x34,0x45,0x3f,0xc4,0x41,0xcc,0x21,0x35,0x89,0x3b,0xaa, + 0x57,0x6e,0xdb,0x27,0x97,0x95,0xee,0x1c,0x68,0xd2,0xdc,0x87,0x5e,0xb3,0x5c,0x63, + 0xee,0xaf,0x8b,0xb2,0xc6,0xc2,0x2b,0xa0,0x6b,0x51,0x13,0xd7,0x87,0xd,0x5e,0x15, + 0xd0,0x44,0xd8,0x20,0xa8,0x99,0xa6,0xcc,0xf3,0x8,0x20,0x2b,0x1d,0xb3,0x8f,0x84, + 0x5a,0x52,0x3a,0xa9,0x8e,0xf8,0x29,0xfb,0x36,0x2,0xe3,0x18,0x54,0x83,0x8e,0xe, + 0x27,0xc6,0x4f,0xa2,0x95,0x26,0x98,0xb7,0x4,0x3c,0x87,0x3c,0x88,0x9d,0xef,0x3, + 0xbb,0x79,0x4a,0x4e,0x49,0x1c,0x7c,0x9a,0xa9,0xc5,0xad,0x15,0x1d,0x84,0xe6,0xf0, + 0x21,0x65,0xac,0x8c,0x4a,0x2,0xd6,0xa0,0xf9,0x5c,0x1a,0x74,0x4,0xb9,0x57,0x7d, + 0xaa,0xb3,0x19,0x25,0x9,0xe8,0x22,0x80,0x4a,0xd9,0x33,0x73,0xde,0xbc,0x64,0x39, + 0xae,0x95,0xfc,0x66,0xc6,0x2e,0x8b,0x87,0xe0,0x26,0xa9,0xc8,0x5b,0x7,0x73,0x19, + 0x4c,0x29,0xd0,0xec,0xcc,0x70,0x39,0xb4,0x28,0x54,0x77,0xd,0x60,0xe7,0x1c,0x1c, + 0xd1,0x1c,0x29,0x24,0xd6,0x75,0x77,0x1e,0xb9,0xb7,0xd9,0xf6,0x60,0xaa,0xb0,0x9, + 0xfe,0x4,0x7e,0x7,0x10,0xc8,0x7a,0x48,0x12,0x9e,0xa4,0x84,0x43,0xf,0x86,0x91, + 0xb0,0x11,0x25,0x41,0x5b,0x15,0xd4,0xf1,0x68,0x8f,0x62,0x43,0x73,0x26,0xf,0x6, + 0xd1,0x2a,0x25,0xde,0x52,0x7a,0x5,0x92,0x31,0xf,0x7c,0x93,0xc4,0x3f,0x6d,0x43, + 0x56,0x6c,0x4a,0x3d,0x4d,0xe,0xda,0xb1,0x86,0x5a,0x2c,0xa5,0xbc,0x36,0x54,0xe4, + 0x51,0x7d,0x8e,0xea,0xb3,0x2,0x1,0x59,0xa3,0x37,0x92,0x41,0x12,0x3c,0x4b,0x41, + 0x7b,0x50,0x16,0x20,0x11,0x71,0xb8,0xa5,0x49,0x18,0x24,0x61,0x36,0x9,0x8e,0x48, + 0x5c,0xc,0x46,0x36,0x73,0x10,0x94,0xbd,0x65,0xc4,0xe0,0x2f,0x1a,0xa3,0xad,0x15, + 0x26,0xfd,0xba,0x6d,0x5e,0xf1,0x22,0xba,0x48,0x60,0x9c,0x99,0x48,0x47,0x49,0x20, + 0x1b,0x34,0x1a,0xac,0x56,0x7c,0x7d,0xae,0xc,0x70,0x36,0x0,0x19,0xc5,0x98,0xf1, + 0xaa,0xbc,0x6,0xc9,0xa2,0x2a,0x1b,0x58,0xf7,0xc6,0x6c,0xf3,0xd9,0x7d,0xcf,0x6, + 0x23,0x74,0xbd,0x76,0x91,0x1,0xbc,0x52,0x34,0x14,0xf1,0xe2,0x9a,0x10,0x82,0x1, + 0xf2,0xea,0x74,0x2a,0x3f,0x41,0x4e,0x80,0xa9,0xcd,0x4d,0xab,0x5f,0x6d,0xe4,0x92, + 0x1a,0xff,0x8e,0xa1,0x3c,0x61,0x8d,0x75,0xe3,0x95,0x9b,0x5d,0x71,0x8d,0xc1,0x5, + 0x91,0x7,0x51,0xac,0x3c,0x94,0x78,0x3,0x69,0xae,0x50,0x32,0xb1,0x23,0x72,0x25, + 0xf,0x53,0xef,0xc3,0x3,0xa8,0x86,0x4d,0xcd,0x9a,0x30,0x96,0x85,0xd3,0x84,0x48, + 0x21,0xe9,0xbe,0x29,0xb3,0xf2,0x16,0x41,0x19,0x41,0xfe,0x5c,0x3a,0x28,0x7f,0xbc, + 0x73,0x72,0x69,0xde,0x23,0x70,0xc1,0x66,0x63,0x19,0x53,0xdc,0x63,0x31,0x58,0xf3, + 0xe,0xbd,0x45,0x1c,0x6d,0x46,0x83,0x96,0xc,0x6d,0x13,0x44,0xd0,0xad,0x93,0x44, + 0x6f,0x9a,0xa5,0xef,0x4e,0xe7,0x2c,0x89,0x4c,0xaa,0xe9,0x1e,0x11,0xf,0x86,0xb2, + 0xd6,0xa8,0xd5,0x19,0x4,0x7f,0xbb,0x3a,0x6d,0x6d,0x60,0xf5,0x76,0x54,0x84,0xd1, + 0xf,0x58,0xca,0x93,0x66,0xb6,0x35,0xb7,0xbe,0x4c,0xf,0x90,0xe0,0x9d,0x13,0x33, + 0x97,0xc3,0x90,0xb1,0x95,0x1a,0x2b,0x4d,0xba,0x48,0xa6,0x35,0x51,0x61,0xa2,0xa4, + 0xfc,0x45,0x21,0x51,0x70,0xb4,0x3c,0x88,0xe1,0x6b,0x4f,0x6b,0xf,0x81,0x3f,0xab, + 0x1,0x5c,0x5f,0x9e,0x97,0x81,0x53,0x37,0x1b,0x29,0xb1,0x62,0x5e,0x14,0x3b,0x90, + 0xbc,0x91,0x69,0xcd,0x45,0x46,0x96,0xf6,0xa3,0xac,0x44,0x35,0x1b,0xf2,0x1c,0xe7, + 0x9b,0x5e,0xa1,0xf0,0xba,0x59,0xea,0x3b,0xb9,0xf6,0x61,0x82,0xe7,0x64,0x40,0xd, + 0x6e,0xbf,0x26,0xc3,0x43,0x5,0x93,0xf8,0x94,0x88,0xd5,0xc8,0xa1,0x56,0xb7,0xfa, + 0xa2,0xf3,0xfe,0x81,0xe0,0x70,0x50,0x42,0xa9,0xc5,0xc8,0xdb,0xbd,0x50,0x1d,0xe5, + 0x70,0xa2,0xf1,0x80,0xef,0x6d,0xb5,0x14,0xa9,0x84,0x27,0xe5,0x5c,0x86,0xde,0x32, + 0xbf,0xbc,0x67,0x78,0x9b,0x7b,0xfc,0x55,0x80,0x4e,0x3c,0x1,0xe7,0xc1,0xf,0x8b, + 0xc,0x28,0x3c,0x40,0xfc,0xf0,0x11,0xa9,0x52,0xc1,0xb0,0x85,0xd9,0xb1,0xd5,0x54, + 0x4a,0xc,0xb9,0xcc,0x9c,0x3,0x21,0x38,0xa,0x90,0x8,0x12,0x39,0xd,0x2c,0xd, + 0xef,0x53,0x7c,0xb1,0xd0,0xbe,0x9b,0xec,0x15,0x18,0x6a,0x6d,0x3,0xd1,0x81,0x43, + 0xe6,0xd5,0x57,0x17,0x8,0x6b,0x69,0x50,0xe,0x52,0xa8,0x5e,0xce,0x93,0x4f,0x8f, + 0x71,0x4c,0x8c,0x80,0xba,0x1e,0xca,0x2d,0x1e,0x2d,0x15,0x3d,0xb4,0xa6,0x8c,0x3f, + 0x9b,0x6,0x6b,0x3e,0x7c,0x6e,0xb5,0x8e,0xdd,0xe8,0xc3,0x25,0x9,0x44,0xbd,0xed, + 0xa4,0xc3,0x9b,0xa4,0xdf,0x35,0xc4,0x72,0x3e,0x81,0x6d,0x16,0x46,0x94,0x61,0x33, + 0x58,0x11,0xb0,0x33,0xac,0x31,0xfc,0x7f,0x8d,0x38,0x46,0x18,0xb8,0x55,0x92,0xba, + 0x6a,0x52,0x57,0x92,0x61,0xc5,0xde,0x6f,0x84,0xa8,0xd9,0x82,0x4a,0x62,0x95,0x2f, + 0x6e,0xa2,0x70,0x9d,0x43,0xb3,0xf2,0x48,0xe1,0x4a,0x8d,0xc6,0xa0,0x47,0x2d,0xa2, + 0xd0,0x3c,0x15,0xc,0xda,0xe7,0x40,0xee,0xd2,0x3e,0xc4,0xab,0x8c,0xae,0x54,0xde, + 0x29,0xbf,0x9b,0x10,0x4,0x78,0xc7,0x98,0xdf,0x4e,0x76,0xd7,0x94,0x92,0xc9,0x5d, + 0x8d,0xea,0x52,0x58,0xa9,0x50,0x93,0x36,0x9e,0xb8,0x4e,0xd9,0x51,0xe2,0x91,0xbb, + 0x53,0x54,0x3a,0xe3,0x73,0xb5,0x47,0xea,0x65,0xd6,0xb1,0xb8,0x63,0x62,0xd9,0x7d, + 0x27,0xd4,0x5,0x5f,0xba,0x1a,0x97,0xb9,0xc6,0x7,0x2b,0xe,0x69,0xb3,0x96,0x42, + 0x4b,0xfe,0x79,0xf1,0x9f,0x6b,0xdd,0xb5,0x23,0xe4,0x3,0xb9,0xc8,0x54,0x22,0x49, + 0x85,0x60,0xf3,0x50,0x5a,0x73,0xda,0xd0,0x2a,0xa7,0x5f,0xc7,0x51,0x28,0x5b,0x7c, + 0xb0,0x33,0x18,0x39,0x10,0x93,0xf,0x46,0x4b,0x96,0x28,0x97,0x42,0xe,0xa4,0x9, + 0x40,0x8a,0x45,0x76,0xfa,0x47,0xe4,0xd5,0xa0,0x68,0x32,0x8,0x37,0x2e,0x30,0xe, + 0xc4,0xbd,0x4,0x81,0x83,0x52,0xe5,0xc7,0x1,0x51,0xf4,0x65,0x2b,0x82,0xae,0xbe, + 0xb,0x1f,0xb9,0x37,0x1e,0x35,0xad,0x59,0xb4,0x8e,0xe9,0xa6,0x31,0x7a,0x14,0x3, + 0x94,0x38,0xe2,0xf,0xf7,0x3c,0xb9,0xc3,0xac,0xc1,0x12,0xe1,0xdc,0x1d,0x6b,0x8a, + 0xf4,0x64,0x9c,0x5c,0x3a,0x91,0x23,0xac,0x8d,0x9f,0x9a,0x58,0x75,0xa6,0xb5,0x48, + 0xf3,0x54,0x20,0x6c,0xb5,0x27,0xe3,0xb8,0x19,0x5b,0xe,0xdb,0x2f,0xdb,0x61,0x13, + 0xcf,0x8a,0x30,0xb,0xdb,0x7d,0xb9,0x11,0x48,0x6a,0x5f,0xbb,0xe7,0x9d,0xa6,0xae, + 0xcd,0xbe,0x56,0x57,0xf5,0x33,0xef,0x60,0x10,0x30,0x1d,0x92,0xa2,0x1,0x2c,0xb7, + 0xb9,0x5c,0xc2,0x29,0xe4,0x5d,0x3f,0xf3,0x4,0xfc,0xbc,0xe4,0xb8,0x45,0x8d,0x97, + 0x4c,0x96,0x29,0x13,0x89,0x28,0x59,0x35,0x3c,0x26,0x5,0x9e,0x87,0xe,0xeb,0xa2, + 0x50,0x6c,0x8f,0x49,0x64,0x48,0xc8,0xb3,0x79,0x4f,0xf7,0x12,0xf0,0x90,0xd7,0x3d, + 0xa9,0xdd,0x9e,0x48,0xab,0x74,0xd8,0x63,0x65,0xd1,0x53,0xa4,0x67,0x5a,0xcd,0x18, + 0xd7,0xd5,0xf5,0xff,0xf1,0x22,0x78,0xc7,0x13,0x91,0xe5,0x4c,0x47,0x1b,0xc5,0x59, + 0xe4,0x1e,0x4f,0xcf,0xd6,0x40,0xf1,0x7a,0x2c,0x82,0x47,0xa4,0xb2,0xbe,0x43,0x88, + 0x32,0x6f,0xa9,0x66,0xcc,0xc8,0x2f,0xea,0x60,0xe,0x45,0xd1,0x7a,0xa1,0xf2,0x94, + 0x52,0x65,0xa9,0xc6,0xd4,0x30,0xb0,0xf6,0x87,0x2a,0xa9,0x45,0x1b,0x92,0xe8,0x76, + 0xa2,0x93,0x5c,0x79,0x92,0xad,0xb4,0x9b,0xe7,0x51,0x79,0x36,0x5a,0x51,0x6,0xb1, + 0x62,0x3b,0x5b,0x4f,0x45,0x78,0x2f,0xa7,0x61,0xaf,0x9b,0xf,0x51,0x9f,0xea,0x92, + 0x9d,0x8,0x1a,0xc2,0xea,0x84,0x22,0xc6,0x95,0x98,0x78,0xb8,0xb2,0x6e,0xe8,0xc2, + 0x2d,0xc9,0x69,0xf6,0x30,0xf3,0xd7,0x66,0xff,0xa3,0x75,0x83,0xb,0x12,0x45,0x15, + 0xa4,0x48,0xf7,0x0,0x21,0x9d,0x48,0x61,0xd3,0xba,0x20,0x24,0x4c,0x88,0xe7,0xde, + 0x3e,0xbd,0x32,0x32,0x8d,0xf5,0x65,0x10,0x43,0x9a,0xc3,0x3f,0xd5,0x83,0xb4,0xe0, + 0x11,0xc6,0x61,0x34,0x30,0x0,0x9c,0xee,0xa3,0x50,0x26,0xb5,0xbc,0x46,0xf4,0x2e, + 0x1,0x2,0x12,0xd,0x83,0x0,0x65,0x36,0xe1,0xf0,0xf1,0x9c,0x3a,0xd2,0x7a,0xc6, + 0xda,0xb9,0x84,0x61,0x4c,0xa7,0x31,0x79,0x11,0x16,0xd6,0xb9,0x91,0xd0,0x54,0x2e, + 0xef,0x64,0x7f,0xd6,0xf2,0x65,0x64,0xbb,0x23,0x19,0xa4,0xb7,0xfc,0xea,0x44,0xfa, + 0x13,0xd9,0x78,0xfe,0xc8,0x9b,0xac,0xba,0x14,0x94,0xe2,0xe9,0x33,0xb6,0x9d,0x6e, + 0x72,0x8,0xd5,0x45,0x4,0xa7,0x8b,0xb4,0xd,0xe9,0x7,0x97,0xd,0x1c,0xd4,0xfc, + 0x37,0x2d,0xf3,0xb6,0x3a,0xf6,0xd5,0x25,0xfc,0x25,0x61,0x3d,0x5a,0x20,0xa3,0x94, + 0x98,0x90,0xe2,0xb8,0xd3,0x26,0x91,0x6f,0x2b,0x33,0xd4,0x99,0xa0,0x5d,0x84,0x42, + 0x74,0x21,0x85,0xed,0x84,0x1b,0x7f,0x19,0x14,0x6c,0x2f,0x4a,0x62,0xa7,0xfc,0xfd, + 0xa2,0x4c,0x4b,0x20,0xc4,0x47,0x21,0x83,0x1e,0x94,0xd6,0x2f,0xf9,0xc3,0x5e,0x6c, + 0xcf,0xa0,0x99,0x11,0x8,0x96,0xb1,0xd8,0xa3,0xfd,0x20,0x54,0x2d,0x0,0xa2,0x3c, + 0xbd,0xa2,0xae,0xaa,0x16,0x27,0x2c,0x58,0x5a,0xc4,0x15,0x65,0x18,0x9b,0xd5,0xc0, + 0x4e,0x8d,0xb0,0x58,0xec,0x68,0xc6,0xcb,0xb8,0x51,0x43,0x43,0x41,0x73,0x46,0xd, + 0xd5,0x1c,0xaf,0x9f,0x93,0x68,0x58,0xe3,0x92,0x9a,0xdb,0x1d,0xcf,0xd0,0x71,0x1b, + 0x62,0x54,0x31,0xe,0x8a,0x9f,0x9d,0x39,0xe1,0x4c,0x53,0x15,0x6a,0xd3,0x1a,0xd0, + 0x8c,0xe,0xfc,0xdc,0xce,0x73,0xad,0x53,0x21,0x41,0xba,0x2a,0x36,0xc3,0x4d,0x16, + 0x41,0x13,0xca,0x20,0xf4,0xd4,0x24,0x2c,0x97,0x10,0xef,0xc3,0x4b,0xc8,0x8b,0xd0, + 0x5a,0x47,0xa4,0xd6,0x20,0xf1,0x75,0x48,0xa4,0x6c,0x42,0xb7,0xd6,0x12,0x61,0x55, + 0x63,0xa5,0x74,0x4c,0xb6,0xf2,0xb,0x19,0x2b,0x32,0x1e,0xa6,0xb4,0xa2,0x18,0x8f, + 0x4b,0x42,0x93,0x5a,0x70,0x16,0x3f,0x4d,0xe8,0x76,0x5f,0x55,0xac,0x2b,0x3e,0x40, + 0x53,0xd7,0x44,0x7b,0x57,0xbe,0x1c,0x81,0x22,0x6b,0x5a,0x80,0x45,0x42,0xb0,0x21, + 0x2f,0x3b,0x62,0x5d,0x1e,0xd1,0x92,0x74,0xb0,0x5,0xd1,0x8,0x2b,0xb2,0xb3,0x6d, + 0xa8,0xc2,0x29,0xee,0x52,0x73,0x22,0x64,0x29,0xd8,0xf9,0x82,0xa5,0x6d,0x93,0xa, + 0xf,0x2a,0x8,0x6b,0x1c,0xc1,0x97,0x6e,0x83,0x89,0xb2,0x1c,0x21,0x6d,0xca,0x27, + 0x35,0x2b,0xfa,0x5d,0xc,0x4f,0x91,0xac,0xce,0xbf,0xa0,0x91,0x54,0xa3,0xdc,0xcd, + 0xd0,0x9f,0xf0,0x4a,0x82,0x84,0x5e,0x1a,0x47,0xe9,0xdc,0xe0,0x98,0x1e,0xa7,0x13, + 0xcb,0x88,0x8a,0xd0,0x9,0xf6,0x8a,0x6f,0xd,0x25,0x78,0x2b,0x26,0x44,0xb3,0x61, + 0x73,0xda,0xf4,0xb4,0x38,0xc6,0xca,0x52,0x7b,0xa8,0xa3,0xc0,0x5,0x94,0x32,0xf, + 0x3f,0x78,0x74,0xd0,0x99,0x11,0xe1,0xe5,0x38,0x1,0x95,0x1a,0x1c,0x69,0xc9,0x7a, + 0x96,0x81,0xd2,0x8c,0x89,0x27,0x22,0x1c,0xcc,0x36,0xb4,0x1a,0x45,0xe9,0x58,0x2f, + 0x3a,0x36,0x38,0x9b,0xcc,0x4a,0xa4,0x32,0x89,0x38,0x5,0x75,0xc5,0xa8,0x21,0x83, + 0xa9,0x9c,0x7f,0x96,0xa6,0xb7,0x50,0xcc,0x43,0xb6,0x2f,0xe8,0xc5,0x61,0xe1,0xf1, + 0xac,0xe9,0x6b,0x49,0xd3,0x72,0x50,0xe0,0xc5,0xa1,0x1c,0x54,0xce,0x2c,0xfb,0xe5, + 0x74,0x7d,0xe9,0xa,0x7f,0x96,0x95,0xf,0xbd,0x6,0xaf,0xa7,0xf0,0x76,0xf5,0xce, + 0x62,0x8b,0x88,0xc6,0x79,0x8b,0xd5,0xde,0x16,0xc9,0x3a,0xac,0x79,0x23,0x5f,0xea, + 0x94,0x81,0x76,0xf6,0xab,0xf3,0xd6,0xb6,0x2a,0xd7,0xb5,0x8a,0x5b,0x24,0x9b,0x65, + 0x17,0x9d,0x0,0xa,0xcc,0x20,0xbe,0x94,0xd8,0xdd,0xb9,0xd7,0x75,0x39,0xb,0x40, + 0x97,0x5,0x95,0xbf,0x8b,0x27,0xa0,0x6f,0xe4,0xe8,0xa0,0x8a,0x84,0x72,0xa1,0x31, + 0xe3,0x44,0x67,0xe7,0x2c,0x65,0x94,0x9d,0xb1,0x67,0x71,0xf8,0x70,0x14,0x24,0xd9, + 0x2d,0x7b,0x2a,0xb7,0x94,0x34,0x78,0x92,0xb4,0x76,0xf5,0x67,0x98,0x88,0x76,0xb4, + 0x66,0x89,0xf5,0xde,0xea,0x1b,0x5,0x4f,0x74,0x9c,0x3c,0x86,0xd8,0xc1,0x26,0x20, + 0x4e,0x4c,0x2f,0x34,0xf,0xf2,0xb7,0xa5,0xa5,0x6,0xfd,0x61,0xa5,0x54,0x43,0xe, + 0x4e,0xb0,0x9f,0xa5,0x92,0xaf,0x56,0x8b,0xb7,0xc9,0xf2,0xeb,0x35,0x73,0x70,0x41, + 0x2c,0xdf,0xfa,0x33,0xb4,0x5b,0xa7,0x73,0x3d,0x6f,0x2c,0xca,0x16,0x8b,0xee,0x28, + 0xe2,0x92,0xe,0x72,0x25,0xda,0x69,0xac,0xba,0xed,0x57,0x5d,0x79,0xcb,0xb8,0x68, + 0x5a,0x36,0xf2,0x9a,0x78,0x37,0x83,0xe1,0xeb,0x53,0xda,0xd3,0x22,0x98,0x33,0xf6, + 0x75,0xb5,0xc8,0x82,0xdd,0x48,0xea,0xdb,0xb2,0xe7,0xc4,0xa0,0x3c,0xa,0x4e,0xa5, + 0x29,0x6,0xd,0x1a,0xcd,0xaa,0x7,0x54,0xe3,0x2d,0x69,0x1,0x48,0xb7,0xe0,0x90, + 0x3c,0xa5,0xea,0x55,0xb,0x3f,0x80,0x27,0x46,0x45,0x79,0xb6,0x21,0xd6,0xac,0x8b, + 0x45,0x48,0xe2,0xb2,0xa7,0x5f,0xdb,0xef,0xee,0xc8,0xf9,0xef,0xbe,0x2e,0x93,0x20, + 0x91,0xdb,0xb9,0x69,0xd4,0x94,0x9e,0xf7,0xf0,0x64,0x80,0x6b,0x1,0xa8,0xe3,0x1d, + 0x3a,0x1,0x7f,0x18,0xdd,0x5b,0xb0,0x23,0x8,0xe1,0xa7,0x86,0xc8,0x6c,0xf9,0x5d, + 0x62,0x58,0xe1,0xb8,0xb0,0x28,0x76,0xce,0x78,0x12,0xc4,0xbf,0xdb,0x38,0x96,0x35, + 0xa8,0x9f,0x7e,0xc,0x6b,0xc4,0x32,0x13,0x17,0x8e,0x6c,0x4,0xfe,0x1c,0x7a,0xe2, + 0x65,0x59,0x4b,0xc6,0x8f,0x7a,0x2e,0x74,0x52,0x7,0x6a,0x79,0xe0,0x42,0xda,0x6e, + 0x46,0x3b,0x4f,0x60,0x50,0xfd,0x29,0x5a,0xf0,0x4e,0xb,0x2d,0x96,0xc4,0x88,0x7d, + 0x4,0xa7,0xa6,0x41,0x67,0x43,0x5e,0x93,0x21,0x7d,0xdf,0x49,0xe,0xab,0x42,0x49, + 0x51,0xa1,0x59,0xea,0x9e,0x7b,0xd2,0x38,0xa3,0xcb,0xd3,0xf5,0x92,0x30,0xb0,0xd8, + 0xa3,0xb3,0x85,0x3b,0x4d,0xa7,0xa8,0xd4,0x2b,0x4d,0x5a,0xe8,0xcf,0x4c,0x4b,0xc6, + 0x8a,0x6f,0x39,0x44,0xdb,0x7a,0x49,0x35,0xe1,0x5d,0x75,0x69,0x33,0x6b,0x72,0x4c, + 0xcb,0x6c,0x6c,0x9a,0x8,0xaf,0x7,0xc1,0xe7,0xfd,0x5f,0x79,0x74,0x6c,0x4,0x68, + 0x43,0x56,0x90,0x72,0x95,0x5a,0xa,0xaa,0x7a,0x85,0xb5,0xe8,0x4e,0x30,0x6a,0x24, + 0xf7,0x5f,0x52,0xb5,0xaa,0x12,0x29,0xbf,0x40,0x8b,0xf1,0x40,0xc1,0x1f,0x32,0x58, + 0xd7,0x8a,0xd2,0xf1,0xf9,0xf9,0xd5,0x32,0xe9,0x67,0xcb,0xcb,0x9b,0xfe,0x7e,0x1a, + 0x9f,0x42,0x56,0x84,0x31,0x8d,0xf2,0x62,0x86,0x19,0x7,0x4b,0xcc,0x43,0xa7,0xc3, + 0xaa,0x69,0xda,0x5f,0x4e,0x48,0x78,0xe4,0xec,0x6,0x21,0x6d,0xf5,0xd9,0xae,0x36, + 0xa9,0x74,0x29,0x66,0x87,0x42,0xe4,0xbc,0xd4,0x15,0x4c,0xe3,0x61,0x16,0x3d,0x53, + 0xe1,0xaf,0x42,0x7a,0x89,0xd2,0x8e,0xb2,0x31,0x12,0x10,0x1c,0x11,0xeb,0xe5,0x9e, + 0x51,0x6,0x2,0x29,0x2b,0xba,0x3c,0xc3,0xae,0x1d,0x4e,0xc7,0x28,0x47,0xe8,0xf2, + 0x28,0x51,0xe,0x80,0xfd,0x6,0x14,0x95,0xbe,0x7,0xbb,0x2c,0xde,0x38,0x37,0x21, + 0xc7,0x5a,0x72,0x33,0x24,0x8e,0x7c,0xe9,0xfc,0xdc,0xd5,0x5,0xd,0xd,0x86,0xb6, + 0x34,0x8f,0xa8,0x5e,0xe0,0xe5,0x70,0x63,0x2f,0x8a,0x66,0x91,0xd8,0xe4,0x9f,0xab, + 0x48,0xc1,0xaa,0xd1,0xa8,0xad,0xfb,0x8,0x0,0x9b,0x85,0xb8,0xd2,0x51,0x2f,0x7b, + 0x38,0x5,0xf9,0xc2,0x9c,0x80,0x92,0xf9,0xb5,0x2a,0x9,0x2e,0xfd,0xc2,0xb,0xc, + 0xac,0x48,0x9,0x4b,0xca,0x5b,0x4b,0xcd,0x5,0x2f,0x74,0x59,0xaf,0x2e,0xcd,0x52, + 0x12,0x78,0x4a,0xed,0xbe,0xf2,0x99,0xa0,0x90,0x92,0xb7,0x2d,0xc9,0x64,0x22,0xb2, + 0x8c,0xf5,0x59,0xa0,0x58,0x8a,0xab,0xb8,0xd4,0x47,0xa5,0x3,0xd0,0x36,0xc3,0x61, + 0x29,0x8,0x73,0x80,0x10,0xa9,0xe,0x46,0xc6,0x24,0x60,0x13,0xd7,0x26,0x11,0xe3, + 0xd9,0x72,0x41,0xe2,0xf5,0x29,0x45,0xc7,0xce,0xa4,0x3a,0x7f,0x7e,0xe3,0xbf,0x85, + 0x30,0x5a,0x68,0x5c,0x60,0xf4,0x33,0xf4,0x88,0xd2,0xb9,0x7f,0xf4,0xd0,0x1a,0x49, + 0xca,0x70,0xc5,0xaa,0xef,0x26,0x8b,0xb2,0x6e,0x6a,0x38,0x3,0xf2,0xdd,0xd8,0xb7, + 0xaa,0x68,0x9e,0x83,0x53,0x86,0x4e,0xaa,0x49,0x60,0x4d,0x6a,0x21,0xb,0xd3,0x10, + 0xad,0xa2,0xce,0xe0,0x59,0xc3,0x61,0x60,0x3e,0x43,0x89,0xff,0x7e,0xda,0x8b,0x4b, + 0x1a,0x33,0x61,0x29,0xb,0x5b,0xe8,0x9d,0xe8,0xf9,0xe0,0x15,0x13,0x4f,0x72,0x7b, + 0x79,0x36,0x91,0x27,0xeb,0xae,0x55,0xf2,0xe7,0x6f,0x40,0xc,0xa3,0x21,0x6e,0x74, + 0x17,0xc0,0xac,0xb9,0xb9,0x4b,0x3a,0x44,0x6b,0xb2,0x17,0xa9,0x90,0xaa,0xd4,0x56, + 0x66,0xf9,0x84,0x6,0x22,0x3d,0x6d,0xfa,0x1f,0xcd,0x1e,0x49,0x3a,0xe9,0x96,0x60, + 0xb5,0x8d,0x24,0x19,0x4e,0xdd,0xcc,0x1,0xf1,0x3e,0x23,0x87,0xe7,0xfb,0xf9,0x4b, + 0xc5,0xbe,0xc9,0x0,0xa5,0x4a,0xf,0x43,0xb4,0xf0,0xb,0xa3,0x91,0xa1,0x9a,0xfe, + 0x78,0x1a,0xc3,0x25,0xad,0x47,0xf0,0xa0,0x73,0x95,0xce,0x3f,0x98,0x18,0xf9,0x65, + 0x5a,0x9b,0x44,0x51,0x92,0xbc,0xe5,0xbc,0x7d,0xc4,0x22,0x13,0x8f,0x87,0xa5,0x97, + 0xae,0x43,0xf9,0xcf,0xf1,0x8b,0xc3,0x89,0x42,0x64,0xed,0x33,0xd5,0x26,0x29,0xa9, + 0x93,0x21,0x39,0x3f,0xb0,0x5b,0xc0,0x15,0x29,0x94,0x1b,0x94,0xfd,0x95,0xdb,0x77, + 0x54,0xb2,0xf5,0x2b,0x49,0x65,0x4d,0xbd,0xe4,0xa3,0x94,0xa2,0x8a,0x47,0x2a,0x24, + 0xb2,0x4c,0x70,0x13,0xd4,0xc0,0xa0,0x69,0x92,0x9a,0x7,0xe2,0x8a,0x75,0x77,0x48, + 0x5f,0xbf,0x2c,0x3a,0x2b,0x7b,0x39,0xe3,0x3c,0xd0,0xc5,0x26,0x26,0xa4,0x7a,0xe6, + 0x70,0x94,0xa5,0xd8,0x13,0x42,0x22,0x83,0x8c,0x8,0x8a,0x32,0x7,0xc9,0x41,0x1f, + 0xc2,0xfa,0x47,0x37,0x46,0xe8,0x3e,0x96,0xc0,0x9e,0x2e,0x34,0xf3,0xb4,0x59,0xc6, + 0x80,0xc8,0x63,0x40,0x8a,0x75,0xd4,0x54,0x8d,0x23,0xe7,0x3c,0x9b,0xc,0x3a,0xdd, + 0xfe,0x20,0x51,0x54,0x36,0x3e,0x92,0x4d,0x20,0xbf,0xae,0x9a,0x9d,0x13,0x43,0xf7, + 0xe5,0x1e,0x7f,0xa4,0x8d,0x80,0xa6,0xc2,0x4e,0xeb,0x58,0x1e,0x36,0x11,0xd4,0x85, + 0x79,0x11,0x53,0x14,0x59,0x57,0x50,0xda,0x92,0x89,0x0,0xb6,0xc9,0xcb,0xe3,0x22, + 0x7f,0x9e,0x81,0xe8,0xbc,0x29,0xcc,0x28,0x8a,0xc7,0xe5,0xbf,0x9e,0x17,0xbe,0x1c, + 0x64,0x42,0x45,0x1b,0x34,0xb2,0xc9,0x7c,0x20,0x39,0x50,0xb8,0x22,0x83,0xbb,0x61, + 0xb7,0x4c,0x8b,0xf4,0x18,0x65,0xc4,0x8,0xf3,0xf8,0x91,0x2,0x3e,0x24,0x80,0x7c, + 0x12,0x2f,0xe4,0x24,0x9f,0x6a,0x73,0xea,0x99,0x8f,0xe0,0x13,0x9c,0xb1,0xec,0x49, + 0xa2,0xd8,0x44,0xd7,0x75,0x25,0xcb,0x9a,0xaa,0xc0,0xb,0x85,0x21,0xb2,0x8b,0x67, + 0xab,0xf8,0x42,0x9c,0x6,0x5c,0xa,0xf5,0xd4,0xca,0x18,0xf3,0xa8,0x8e,0xdc,0x58, + 0x81,0xec,0x24,0x65,0xd8,0x79,0x61,0x91,0xb5,0x58,0x6a,0x31,0x83,0x91,0x26,0xc8, + 0xa9,0xd4,0xf4,0x2b,0x52,0xaf,0x46,0x9e,0x15,0xb1,0xb1,0x6c,0xc9,0xe1,0x7,0x8b, + 0xae,0x3e,0xf2,0x7c,0x16,0x94,0xb0,0x94,0x4,0x81,0xe0,0x28,0x37,0x2d,0x2c,0xd9, + 0xa2,0x8,0x95,0x1c,0x66,0x13,0x70,0x37,0x95,0xfa,0x94,0xc7,0x64,0x68,0x7d,0x3f, + 0xe,0x3,0xc0,0x43,0x3b,0x12,0x1a,0xe3,0xb2,0x28,0x25,0xd4,0xce,0x6d,0x19,0x62, + 0xd1,0x68,0x3c,0x3f,0xa5,0xc5,0xf2,0xb6,0x88,0x5f,0x6a,0xca,0x8c,0xea,0x46,0xdc, + 0xb0,0xcd,0x44,0xb4,0xe8,0x1e,0x1d,0x63,0x89,0x3c,0x14,0x97,0x65,0xec,0x66,0x67, + 0x19,0xfb,0xb3,0x39,0xdd,0x73,0xd3,0x1c,0x2d,0x99,0x2c,0x56,0xb5,0x97,0x7e,0x5d, + 0xb4,0x7d,0x69,0xa7,0xba,0x2d,0x74,0x20,0x25,0x9d,0x2e,0xa2,0x1a,0xcd,0xf6,0xf1, + 0x2c,0xc0,0x48,0x91,0x2e,0xbc,0xfb,0xcb,0xa0,0x9a,0x5c,0x54,0xd9,0xc1,0xa4,0x95, + 0x92,0x6,0xb6,0xce,0x31,0xb2,0x17,0x45,0x4,0xb8,0xc8,0x87,0x14,0xad,0xa5,0x7e, + 0x39,0x7d,0xed,0x3c,0xc3,0xa5,0xf9,0xfb,0xfc,0x9c,0x92,0x5a,0x56,0x93,0xea,0x58, + 0xb7,0x40,0xc,0x39,0x7f,0x2f,0xc7,0x11,0x71,0x86,0x6f,0x2c,0xe7,0x34,0x2b,0x9a, + 0x53,0x75,0xad,0x21,0x74,0x4,0xb0,0xf1,0xc4,0xc4,0x4e,0x76,0x75,0x94,0xf2,0xf, + 0xb8,0x84,0xa3,0x14,0xa6,0x32,0xef,0x83,0xd1,0xca,0x6a,0x5,0x7c,0xe4,0x49,0xb2, + 0x6f,0x69,0xfd,0xc1,0x27,0xab,0x4a,0x7d,0xb7,0xb0,0x91,0x14,0x88,0xf0,0xe7,0x86, + 0x5b,0xcd,0x4,0x7a,0x8e,0xff,0xe,0x85,0x6d,0x7c,0x6f,0x2a,0x1,0xd6,0x57,0xb3, + 0x38,0x8,0xdf,0xf6,0x5a,0x7c,0xef,0x5a,0xec,0x36,0x69,0x62,0x56,0x34,0x1a,0x33, + 0xa,0x9b,0x3a,0x7a,0xfe,0xfe,0xa1,0xeb,0xa,0x4a,0xd2,0x4e,0xb7,0x94,0x2b,0x61, + 0x61,0x2b,0xcb,0x28,0x8d,0x9d,0x22,0x17,0x20,0x69,0xc7,0x4c,0xbc,0x9,0x2f,0xe0, + 0x43,0x91,0xa1,0xed,0xf3,0x68,0x5f,0xe1,0x47,0xf,0x11,0xaa,0x8,0xf1,0xe9,0x59, + 0xcc,0x21,0x60,0xec,0x3b,0x19,0x5d,0xe6,0xa,0x58,0x19,0x63,0x61,0x79,0xa9,0x3b, + 0x37,0x6b,0x68,0x61,0x59,0x1a,0x9a,0xb1,0xf9,0xde,0x38,0xb3,0x9e,0x78,0xa5,0x4, + 0x96,0x38,0x48,0x9f,0xad,0x1e,0x9d,0x8b,0xc0,0xba,0x8b,0xd8,0xf0,0x9f,0x22,0xa4, + 0xd4,0xdc,0xbd,0x24,0x4c,0x5b,0xe8,0x66,0xa0,0x64,0xdf,0x23,0x7,0x4,0xf1,0xfc, + 0xb5,0xc,0x94,0x7c,0x44,0x0,0xd,0xf6,0x1c,0x7f,0xe6,0x6b,0xd3,0xd1,0xca,0xcb, + 0x62,0x9a,0xea,0x45,0x42,0x3e,0xc0,0xed,0x6a,0x58,0x42,0x64,0x1f,0xbd,0x4d,0xc0, + 0x48,0x0,0xa7,0xfe,0xfe,0xf8,0xed,0x22,0x48,0x32,0x68,0x9e,0x44,0x29,0xfb,0x18, + 0xd6,0xc7,0x13,0x49,0x83,0xb4,0xa5,0x4a,0x93,0x7d,0x36,0xde,0xed,0x2,0x7d,0x1d, + 0xbb,0x23,0x9d,0xc1,0x2a,0x87,0x72,0x40,0x5f,0x54,0xaa,0xf4,0x2,0x98,0xe,0x32, + 0x17,0xb0,0x52,0xf,0x8a,0x3d,0x17,0x57,0x4d,0x93,0x59,0xff,0xba,0x6b,0x4e,0xdb, + 0xe0,0xcb,0x48,0x41,0xaa,0x6a,0x53,0x3d,0x4b,0xda,0xe8,0xf9,0xbf,0xdf,0x49,0x46, + 0x11,0x5d,0x6e,0x70,0x93,0xec,0x25,0xea,0xd5,0xef,0x20,0xf1,0xc2,0xf1,0x85,0xc8, + 0x2,0xb9,0xc4,0x18,0xe5,0x95,0xb9,0x50,0x50,0x89,0xac,0xdc,0xf5,0x64,0x49,0x28, + 0xf,0x98,0x6c,0x7c,0x46,0xd8,0x18,0xa7,0x8b,0x4,0x1f,0x3a,0x7d,0xe4,0x9,0x41, + 0x9,0x7a,0xa7,0xeb,0x8c,0x1b,0x75,0x9f,0x16,0x63,0x5f,0x21,0xce,0xbe,0x63,0xb4, + 0x5a,0xb2,0xa2,0x20,0x95,0xb6,0xb6,0xf2,0xd0,0xec,0x19,0xa7,0x94,0x29,0x4d,0x4f, + 0x7b,0x2d,0x2,0x22,0x58,0x52,0x37,0xbf,0x67,0x49,0x9d,0x6,0x78,0x77,0x6f,0x4, + 0xa8,0x6c,0x1,0x75,0xe3,0x2c,0x5f,0x18,0xa6,0xe8,0xcd,0x2f,0x13,0xaa,0x5f,0x2e, + 0x8d,0xcd,0xa3,0xf3,0xca,0xdb,0x2c,0xce,0x74,0x49,0xff,0x96,0x2a,0x47,0xcd,0x95, + 0xb7,0x57,0xf6,0x94,0x95,0x6b,0x75,0xcf,0x8c,0x84,0xba,0xe2,0x48,0xba,0xb9,0xf0, + 0xc,0xd0,0xbe,0x5f,0xf3,0xa8,0x6f,0xc9,0x56,0xde,0x76,0xa9,0x68,0x1a,0x1,0xab, + 0xa0,0x7c,0x22,0x1e,0x73,0x3c,0x9d,0xe,0x93,0xf3,0x54,0x3a,0x89,0x89,0x4c,0xa6, + 0xb6,0x93,0xc7,0x20,0x50,0x8e,0xe4,0xc5,0xe2,0xd9,0xee,0xf4,0xef,0x68,0x7c,0x76, + 0xe,0xe6,0x70,0xbd,0x57,0xb6,0xf4,0x65,0xe4,0x18,0x65,0x2,0x40,0x57,0x5f,0x78, + 0x14,0x72,0x2d,0x69,0x79,0x56,0x41,0x1f,0xb2,0x87,0x3e,0x62,0xef,0xf3,0x88,0xb1, + 0xfe,0x4c,0x84,0xd6,0x56,0x69,0xf2,0x28,0x6b,0xf0,0xf,0x58,0xf4,0xd5,0x9c,0xe8, + 0x12,0xf1,0xcc,0x8c,0x6f,0x1a,0x7f,0x4f,0xb5,0xa,0x67,0x9a,0x15,0xd9,0xea,0x17, + 0xbf,0x1b,0xad,0x69,0x9d,0x24,0xb9,0x38,0xc7,0xcc,0x2e,0xee,0x39,0x1e,0x7b,0xfe, + 0xbd,0xf4,0xfc,0x23,0x3d,0x81,0xe1,0x3b,0x45,0xee,0x82,0xc5,0xf7,0xb6,0xca,0xb6, + 0x9b,0x96,0x6d,0xad,0x34,0xd5,0xd2,0x8d,0xcb,0xb,0x4b,0xa2,0x88,0x50,0x90,0xba, + 0xad,0x2,0x24,0x6f,0x28,0x51,0x27,0xa2,0xad,0x62,0xc5,0x97,0x9,0x1f,0x72,0x28, + 0x4c,0x84,0x29,0x94,0xb3,0x7,0x59,0x84,0x1a,0x13,0x5b,0x58,0x6,0x82,0x8a,0xac, + 0x45,0xe5,0xf6,0x65,0xbc,0xae,0x45,0x65,0x63,0x6d,0x99,0x79,0x8d,0x5c,0xac,0x27, + 0x37,0x1,0x1b,0x4c,0x13,0xea,0x50,0x37,0xd6,0x80,0xe3,0xdf,0xf,0xf4,0x2b,0x72, + 0x9a,0x56,0xd2,0x10,0x53,0x60,0xbb,0x6c,0x79,0xe1,0x20,0x15,0xd4,0xb4,0xf9,0x31, + 0xd3,0xc,0x9b,0x3,0xcf,0xf3,0xcd,0xce,0xff,0x4d,0x2a,0xf1,0xe1,0x4a,0x9b,0x48, + 0x1f,0x23,0xb5,0x68,0x28,0xb3,0x95,0x55,0x81,0x59,0x1d,0x8c,0xcd,0x8f,0xbe,0x55, + 0x8f,0xb9,0xe4,0x30,0x70,0xcd,0xd3,0xb,0xaa,0x2,0x7b,0xba,0x23,0x52,0x90,0x9f, + 0x91,0x8b,0xb4,0x42,0x54,0x91,0x1a,0xfd,0xa8,0xa8,0xbb,0x84,0x19,0xcb,0xb2,0xe6, + 0x11,0x58,0xca,0x32,0x96,0x55,0xb7,0xf6,0x81,0xc7,0x9c,0x9b,0x7b,0x46,0x6c,0xf0, + 0x86,0xd9,0x45,0x90,0x47,0x39,0xbc,0x77,0x50,0x84,0xc5,0x2d,0x33,0x2,0xf6,0x46, + 0xbd,0xa2,0x74,0xb6,0x54,0x10,0xb7,0xd2,0x6,0x24,0x71,0x92,0x56,0x55,0x29,0x8a, + 0xb7,0xd7,0x7f,0xa6,0xa0,0x2,0xdd,0xed,0x59,0xe1,0x6f,0xa9,0x16,0xcb,0x7d,0x23, + 0x2b,0x56,0xa1,0xc6,0x69,0xd6,0x18,0xf0,0x96,0x58,0xdf,0x50,0x62,0x8c,0xa7,0x28, + 0x83,0x26,0x75,0xf4,0xac,0xb2,0xf,0x3c,0xc2,0xbc,0x71,0xb2,0x5e,0x94,0xf,0x54, + 0xa5,0xec,0xd5,0x83,0xd9,0xe0,0x9c,0x4,0xe5,0x39,0xfe,0x6,0xf8,0x24,0xdb,0x2b, + 0x93,0xd,0x12,0x9e,0x18,0x5d,0x74,0x2f,0x59,0xb7,0x31,0x16,0xc5,0xbe,0x3b,0xd1, + 0xa,0xa9,0xd0,0x35,0x25,0xa,0x6c,0xf,0x4,0x7d,0x36,0x5a,0x57,0xea,0x79,0xb9, + 0xd9,0xdc,0x5e,0x80,0xc4,0x28,0x47,0x3c,0xbd,0x5d,0x73,0xd1,0x5,0xd9,0x26,0x72, + 0xf5,0x75,0xe,0x66,0xd,0x81,0x64,0x36,0x42,0x1a,0x6f,0x11,0x1f,0x82,0x95,0xe9, + 0x95,0xc2,0x57,0xd4,0xcf,0x1b,0x2b,0x8f,0x85,0x98,0xa8,0x69,0x6e,0xeb,0x1f,0x46, + 0x3a,0x73,0x90,0xd2,0xa2,0xfd,0x32,0x45,0xcb,0x37,0x36,0xa8,0xbc,0xdf,0x28,0xe, + 0xcb,0x74,0x89,0x27,0xa3,0x33,0xed,0xcf,0x5d,0x39,0xc1,0xbe,0xef,0xe4,0x99,0xd2, + 0xe8,0x3a,0xa1,0x3c,0x19,0xac,0xc5,0xf,0xfd,0xf7,0xeb,0x7f,0xbd,0x6f,0xae,0xca, + 0x38,0x4d,0xc7,0xd6,0x1d,0x2d,0x55,0xac,0x5d,0x95,0x2,0x91,0x40,0xa,0x37,0x72, + 0x98,0xb4,0x55,0x29,0xa2,0x1b,0xd3,0xd8,0x74,0x94,0x41,0xd2,0x3b,0xc7,0x79,0x21, + 0xeb,0x3,0xa4,0x85,0x4d,0xbd,0x46,0x48,0x63,0x63,0x0,0x9f,0x9f,0xb6,0xd0,0xe8, + 0xb3,0x76,0xa7,0x67,0x5f,0xc9,0x64,0x7,0x24,0x8b,0x6b,0x72,0xb7,0xa0,0x4e,0x3, + 0x8a,0x66,0x68,0x5d,0x89,0x8e,0x7f,0x36,0x48,0x71,0xf4,0x3b,0x3a,0xb6,0x5a,0x7b, + 0x49,0xf9,0xe7,0x69,0x2c,0xb8,0x31,0x2a,0x48,0x56,0x9e,0x14,0xb,0xa1,0x1,0x3e, + 0x40,0x15,0xb6,0xe7,0x11,0x1c,0x77,0x24,0x48,0x49,0x3d,0xcd,0x57,0x95,0x2a,0x89, + 0x72,0xaa,0x55,0x30,0x93,0xc6,0xfe,0x49,0x5c,0x91,0x2f,0x8f,0xba,0xea,0xce,0x5e, + 0xef,0xd2,0xf5,0x72,0x8,0x3,0x77,0x17,0x52,0x7d,0xb,0x42,0x88,0x4c,0xee,0xba, + 0xa5,0xaa,0x5f,0xca,0xfe,0x8b,0x15,0xd7,0xd5,0x37,0xbb,0x5a,0xe9,0x64,0x63,0x2, + 0xc2,0x76,0xa8,0x5e,0x5e,0x3b,0x4d,0xea,0x92,0x5c,0x2c,0x7b,0xbd,0xd4,0xe2,0xb2, + 0xcc,0xaf,0x6d,0xbe,0xa4,0xb0,0x8c,0xa9,0xa5,0x88,0x8c,0x24,0xa9,0xc4,0x85,0xc5, + 0x69,0x99,0x8c,0xc4,0xbc,0x6e,0x66,0x14,0x69,0x8a,0xb2,0xac,0xaa,0xaf,0xbc,0x2f, + 0x6,0xb2,0x3c,0xdc,0x91,0x43,0xe9,0xf0,0x26,0xb9,0x45,0xd4,0x19,0x58,0x4,0x66, + 0x89,0x93,0xdb,0x78,0xb5,0xd4,0x16,0x71,0xa4,0x8b,0xef,0x66,0x41,0xdc,0x79,0x7, + 0x97,0xfe,0xf4,0x96,0x1d,0x8,0x52,0xec,0x3f,0x9b,0xdd,0x3a,0xf6,0x88,0x47,0xc9, + 0x62,0x87,0xac,0x94,0x35,0xb0,0x10,0xa5,0x7e,0x47,0xcb,0xc3,0x63,0xf4,0x78,0x96, + 0x35,0x6f,0x35,0x34,0xb1,0xc5,0x55,0xf6,0x84,0x4a,0xa4,0x4b,0xcd,0x22,0x91,0x50, + 0x58,0x15,0x61,0xa9,0xa2,0x2,0x5,0x1b,0x95,0x95,0x5d,0xec,0xc9,0xce,0x83,0x24, + 0x36,0xdb,0xd0,0xc,0x84,0xad,0x2d,0x41,0xf2,0x3a,0xad,0x71,0xc6,0xc4,0x4f,0x33, + 0xac,0x4b,0x65,0x39,0x20,0xf9,0x19,0xe7,0x89,0x2e,0xd6,0xc2,0xac,0x14,0x15,0xb9, + 0x7c,0xe6,0xfd,0xb3,0x12,0x2b,0xc9,0x44,0x14,0x83,0x4c,0xa8,0xca,0x3f,0x77,0xc3, + 0xd7,0x78,0xf4,0xb7,0xe3,0x38,0x36,0x18,0xf5,0x21,0x24,0x53,0x21,0xdf,0x87,0x54, + 0xdd,0x1f,0xaf,0x44,0x72,0x91,0x68,0x70,0x99,0xa4,0x5f,0x1,0xc2,0x39,0x84,0xb4, + 0xa,0x65,0x46,0x17,0x5,0x5e,0xa4,0x40,0xae,0xca,0x1,0x4b,0x67,0x8a,0x3f,0x12, + 0x98,0x38,0xb8,0x98,0x10,0x36,0xf,0xd7,0xa3,0x0,0x1a,0x2a,0x2a,0x5a,0x96,0x8f, + 0x69,0x8c,0xdc,0xed,0x74,0x84,0xb2,0x7a,0x50,0x13,0x4d,0x19,0x5c,0x64,0x9a,0x64, + 0x5d,0x79,0xc5,0x88,0xb5,0x10,0x73,0x70,0xa3,0x96,0xc2,0xa1,0x54,0xf9,0x7c,0x91, + 0xe5,0xcc,0x6a,0x37,0xdd,0x63,0x63,0x77,0x6c,0x42,0x91,0xfd,0xe3,0xf5,0x5a,0x8c, + 0xc7,0xe2,0xbd,0xd3,0xa7,0x44,0xa4,0x13,0x7f,0x47,0xc3,0x87,0x2e,0x9a,0x97,0x59, + 0xd,0x1b,0x73,0x7e,0x48,0xa,0x6e,0xdf,0x20,0xd1,0x67,0x8a,0x92,0x8d,0x70,0x5a, + 0xe2,0xa9,0x88,0xef,0x69,0x95,0x11,0x82,0xa1,0x1c,0x21,0xdb,0x4b,0xdf,0x1c,0x85, + 0xe6,0x2,0xa3,0x7,0x25,0xda,0x9,0x69,0x1e,0x4c,0x41,0x9d,0xb4,0x6a,0xfd,0x4e, + 0x38,0x8e,0xae,0xf2,0x7b,0xb6,0x2a,0x6e,0xda,0xcc,0xf9,0x58,0x97,0x84,0x33,0xc8, + 0x23,0xaf,0x6c,0x99,0xdb,0xf2,0x16,0x17,0xb,0x60,0x9,0x68,0xd8,0xe0,0x6,0x6e, + 0x8c,0x6d,0xc8,0x6a,0x67,0x86,0x4f,0x36,0xc8,0x90,0x40,0x83,0x3d,0xa5,0xfb,0xc6, + 0x46,0x75,0xf4,0xcb,0x0,0x85,0x45,0xf0,0x88,0x72,0x39,0xdb,0x77,0xd5,0x36,0x46, + 0x50,0x30,0x88,0x88,0xfa,0x74,0x60,0xdf,0x95,0x55,0x14,0xb1,0x92,0xe1,0xbe,0x99, + 0xe2,0xc9,0x9d,0xb6,0x81,0x6a,0xa2,0xc3,0x52,0xb,0xe4,0xb,0x95,0x5e,0xcb,0xfb, + 0xe9,0xad,0xae,0x2b,0x7d,0x7b,0xa8,0x23,0x32,0x9a,0x1a,0x70,0x72,0x56,0x7c,0x1d, + 0x70,0xa6,0x1,0xb2,0x62,0xda,0xf9,0xf7,0xc,0xbe,0xe6,0x62,0xa5,0xbe,0x5f,0x55, + 0x10,0x56,0xa0,0x14,0xbc,0x4a,0xc1,0xc6,0x3f,0xc3,0xd2,0x47,0x68,0x2a,0xec,0xc0, + 0xc,0x3b,0x89,0x1d,0x70,0x47,0x9e,0x39,0x6d,0xed,0xeb,0x53,0xcf,0x46,0xab,0xb8, + 0xac,0x7e,0x4e,0x81,0x10,0x25,0xd1,0x4c,0xca,0x34,0x49,0x53,0x97,0x58,0x38,0xb6, + 0x69,0x82,0x96,0xd3,0x65,0x1a,0xc5,0x70,0x3b,0x60,0x97,0x0,0x0,0x20,0x0,0x49, + 0x44,0x41,0x54,0x57,0x4e,0xdc,0x9e,0x16,0x8f,0x7b,0x71,0x6,0x64,0x30,0x7,0x36, + 0xa8,0x98,0xe5,0xf3,0xe3,0x9f,0xbd,0xd2,0x88,0x48,0xca,0x8e,0x38,0xd9,0x39,0x68, + 0x32,0x61,0x67,0x54,0x9,0x68,0xea,0x8b,0x34,0xd8,0xa2,0x3c,0x63,0x6d,0xd8,0x93, + 0x6f,0x2b,0x5b,0x99,0xd0,0x90,0xbe,0xb4,0xa,0xd1,0x2b,0x5a,0x21,0xac,0xb4,0xb1, + 0xb2,0x25,0x33,0x7b,0xd7,0xea,0x50,0xc8,0x7f,0xbe,0x6a,0x16,0xa0,0x96,0xe7,0x31, + 0xe9,0x5d,0x52,0x71,0x17,0x27,0x93,0x6c,0xaf,0xc1,0x52,0xf,0x1f,0x97,0x72,0x5b, + 0x7,0x20,0x4b,0xa4,0xed,0xd8,0xd,0xf7,0x96,0xef,0x15,0x2e,0xce,0x21,0xeb,0xe8, + 0x1c,0x84,0xe6,0xc6,0xc6,0x5a,0x6d,0x4b,0xdf,0x95,0xb4,0x22,0xf4,0xbc,0x29,0x22, + 0x5c,0x65,0x29,0xb0,0x4b,0x6f,0xbd,0x69,0x50,0x96,0x2d,0x57,0x7,0x81,0xc9,0x0, + 0x42,0x6d,0xe7,0x55,0xa1,0xad,0x28,0xe7,0xe,0xdd,0x5e,0xef,0x96,0x5f,0x7e,0xea, + 0x26,0xbc,0x53,0x2e,0xca,0x1d,0xb4,0xfa,0x33,0x59,0x47,0x38,0xfb,0x2f,0x8d,0xc, + 0xc0,0x43,0x75,0xed,0xa7,0x3,0x91,0x66,0x28,0xe2,0x6a,0x47,0x17,0x5b,0xa1,0xda, + 0x77,0x26,0xe0,0x1,0xf4,0x5f,0xe8,0x65,0xb8,0x8c,0x44,0x7c,0x53,0x76,0xc3,0xf9, + 0x44,0x10,0x1b,0x4,0x72,0xee,0xe0,0xbb,0x92,0x40,0xb8,0x65,0x4c,0x6e,0x16,0x9, + 0x41,0x6a,0x3a,0x3c,0xd6,0x39,0x42,0xea,0xcc,0x34,0x75,0xe9,0x4d,0x16,0x39,0x74, + 0xdd,0xd5,0x4e,0xc7,0xc2,0x18,0x8f,0x17,0xf7,0xc2,0x2f,0x49,0x3,0x2a,0xa8,0xb6, + 0x2a,0x3e,0x23,0x82,0x5f,0x79,0x6,0x2a,0x10,0xbb,0x24,0x21,0xf9,0x87,0xd8,0x48, + 0x3f,0x21,0x1a,0x97,0xfb,0x9a,0x5f,0x99,0xbb,0x2f,0x4f,0xae,0x93,0x6c,0x9,0xa0, + 0x57,0xdc,0x8a,0xde,0xee,0x93,0x1d,0x8f,0x7b,0x4c,0x90,0xa2,0x8a,0x5b,0x5c,0x5a, + 0xd3,0x32,0x66,0x83,0xb0,0x36,0x83,0xa2,0xa3,0xc2,0xde,0x23,0x11,0xb8,0x91,0x89, + 0x40,0x29,0x11,0xa8,0x6c,0xeb,0xd3,0xf3,0x96,0x15,0x7b,0x79,0x54,0xbb,0xee,0x61, + 0x25,0x53,0x3d,0xf6,0x4c,0x2d,0x96,0x35,0x96,0x2e,0xaa,0xa7,0xec,0x9d,0xf,0x7b, + 0x5f,0xfc,0x88,0x49,0x45,0x39,0x53,0x4c,0xc0,0xe4,0xbc,0x32,0xe6,0x9e,0x5,0x2b, + 0xb2,0x23,0x43,0x56,0xd1,0x6b,0x99,0x9e,0x61,0xa1,0x60,0xe4,0xbb,0x13,0x6b,0xd3, + 0x17,0x6b,0x92,0xb6,0x8f,0xf2,0xa6,0xb2,0x9d,0xd6,0x4e,0x87,0xa5,0xf2,0x2a,0x85, + 0x68,0x8c,0x28,0xeb,0xf3,0xaa,0x1d,0xda,0xca,0xa5,0x20,0x81,0xd5,0xbe,0x2,0x9c, + 0xcf,0xbb,0x2e,0x1e,0x19,0xe5,0x79,0xa5,0x4a,0x54,0x48,0x9d,0x55,0xb1,0xa5,0xc1, + 0x75,0xb5,0x69,0x8a,0xe1,0x6e,0xe7,0x27,0xad,0x9a,0x63,0x9e,0xd3,0xde,0xb6,0x90, + 0x19,0xb1,0x4d,0xc2,0xeb,0xfe,0xed,0x85,0xc0,0xae,0x4f,0x37,0x80,0x2,0x79,0x85, + 0xa1,0x12,0xca,0x75,0x80,0xa3,0x77,0x4b,0x81,0x90,0x27,0x82,0x20,0xf3,0xbe,0x69, + 0x24,0x14,0x5,0x98,0xa5,0x41,0x1b,0x81,0xae,0xe2,0x59,0xe2,0x99,0x5,0xc7,0x4d, + 0xdb,0x56,0xd3,0x55,0x2e,0xf0,0x2c,0x6a,0x86,0x20,0x13,0x39,0x29,0xd,0x20,0xbb, + 0xb3,0xe2,0x61,0x48,0xab,0x57,0x73,0x39,0x28,0x96,0x46,0x80,0xf5,0x40,0xaa,0xc2, + 0x39,0xb8,0x89,0x2f,0x90,0x6b,0x41,0x95,0xec,0x91,0x93,0x82,0xd7,0x5d,0x2f,0x79, + 0x6e,0x98,0xc7,0xdf,0x8d,0x4b,0xf8,0x70,0xf2,0x74,0xc5,0xf6,0x29,0xba,0x48,0xe9, + 0xb3,0x22,0x74,0x51,0x7e,0x12,0xa5,0x4a,0x37,0xba,0x2c,0xae,0x26,0xea,0x91,0x26, + 0x5c,0x6d,0xfa,0xe8,0x32,0x14,0x11,0x66,0xf,0x59,0x3b,0x93,0x5a,0xe5,0x48,0xd9, + 0x1f,0xb7,0xf2,0x5d,0xc4,0x5f,0x43,0x97,0x84,0xac,0x32,0x7a,0xc6,0x46,0xa8,0x9, + 0x8d,0xc2,0xa5,0xa4,0xa4,0xa5,0x0,0x9a,0x8d,0xfd,0x56,0xea,0x36,0x90,0x4,0x57, + 0xa9,0xf8,0x90,0x75,0x8f,0x8f,0xd,0x3b,0x4e,0x56,0x10,0xd7,0x82,0x67,0xbd,0x38, + 0x90,0x83,0xbf,0x18,0x81,0x4a,0x9d,0xe,0xed,0x57,0x94,0x7e,0x5e,0x8d,0x3b,0x4d, + 0x52,0x2d,0xfb,0xe8,0x36,0xa,0xd,0x5d,0xaa,0x5f,0x5d,0xb5,0x16,0x2a,0x8b,0x75, + 0x3,0x79,0x41,0x59,0x4e,0x8f,0xf5,0xa,0xd8,0x10,0x35,0x61,0xe3,0x72,0xd0,0xae, + 0x64,0x31,0x4a,0x18,0xb6,0xb6,0x5e,0x46,0xe5,0xc3,0x4f,0xec,0x92,0x79,0x51,0xa1, + 0x8e,0x31,0xb9,0x60,0x48,0x48,0xf3,0x28,0xc2,0xd8,0x10,0xd1,0xa5,0x5e,0xc,0x95, + 0xb,0x1d,0x6f,0x73,0xfc,0xa7,0xe0,0x3f,0xa7,0xb0,0xc,0x71,0xa9,0x48,0xef,0x17, + 0xad,0x3a,0x74,0x9,0x52,0xda,0x3f,0x89,0x90,0xad,0x60,0x92,0x85,0x56,0xc7,0xdd, + 0xd3,0x76,0x78,0x33,0x5c,0x61,0x9f,0x7a,0xb,0x52,0x5f,0x83,0xf6,0x18,0x59,0x3d, + 0xd5,0x59,0xb7,0xc2,0x5a,0x92,0xcf,0x89,0x13,0x4c,0x40,0x98,0xbc,0x33,0x95,0xc4, + 0x9f,0xca,0x71,0xe6,0x94,0xe6,0x87,0xd4,0x41,0x6a,0xc3,0xa6,0x58,0xb3,0xbe,0x53, + 0x1b,0xe4,0xf6,0xb2,0xd1,0xd4,0x74,0xa8,0xa7,0x2d,0x10,0x3d,0x3f,0xd4,0x5a,0xc3, + 0xcf,0x25,0x37,0x18,0x30,0x5f,0x79,0xd5,0x85,0x54,0xd1,0x91,0x4a,0x15,0x88,0x65, + 0x71,0xa6,0x6b,0x71,0xd2,0xfb,0x1e,0x28,0x6a,0x24,0x41,0x9d,0x2c,0xe7,0x18,0x58, + 0xc4,0xb8,0x8e,0xef,0xd3,0x4,0xa3,0xf3,0x8,0x8d,0x9e,0x5b,0x4a,0xdd,0xe3,0x11, + 0xb9,0xbd,0x5f,0xa4,0x8f,0xd4,0xbc,0xfa,0x94,0xf5,0x68,0xec,0x25,0x69,0x30,0x89, + 0x1a,0xb5,0x7c,0x26,0xa4,0xb4,0x77,0xd,0xbd,0x99,0xe,0x92,0xb0,0x73,0xc3,0x1a, + 0x3a,0x6d,0x94,0xeb,0x33,0xa7,0x6b,0x77,0x54,0x84,0x94,0xa0,0xc1,0x4,0xaa,0xbd, + 0x68,0x23,0x52,0x5c,0xf6,0x38,0x58,0x2a,0xed,0x7d,0x1f,0xa2,0xd8,0x45,0x71,0xb6, + 0x43,0x47,0x4,0xc9,0x3a,0xa1,0xc8,0xbe,0xd9,0xae,0x9b,0x3a,0x5c,0xa9,0xf1,0x60, + 0x5b,0x17,0x53,0xaa,0x4a,0xaa,0xda,0x9d,0x1b,0x4f,0x68,0x9,0x86,0xa1,0xb8,0xc2, + 0x6d,0xd7,0x6e,0xc1,0x38,0x22,0x55,0x2d,0x75,0x3e,0xa3,0xe,0x47,0xa0,0xbd,0x57, + 0x82,0xcd,0x24,0x50,0x42,0xb1,0xf4,0xc8,0x22,0x1e,0x4b,0x7c,0xa7,0x3a,0x7e,0xaa, + 0x87,0x7f,0x2b,0xda,0x2f,0xa8,0x50,0x78,0x18,0x61,0x3c,0xf7,0xed,0x53,0x36,0x26, + 0x96,0xe0,0xdd,0xd6,0x6,0x73,0x9f,0x33,0xbd,0x55,0x45,0x36,0x69,0x5f,0xf9,0xeb, + 0xd6,0x65,0xe4,0xb8,0x16,0x12,0x79,0x78,0x44,0xd9,0xcd,0xc8,0x7d,0xaf,0xad,0xc6, + 0x3b,0xb2,0xc2,0xcc,0x26,0x3a,0x29,0x38,0x2b,0x55,0xbc,0x20,0xa,0x9a,0x16,0xb7, + 0x67,0xcb,0xbb,0x13,0x9a,0x26,0x68,0x56,0xcb,0x85,0x76,0x21,0x92,0xb7,0x82,0x15, + 0xba,0x54,0xc1,0x39,0x75,0x6c,0xbb,0xdb,0xd3,0xbc,0x43,0x63,0x65,0x37,0x15,0x7b, + 0x14,0xe1,0x56,0x12,0x8,0x53,0x0,0x69,0xda,0xf3,0xf6,0x32,0x45,0xa8,0xa3,0x5f, + 0x4e,0x86,0x43,0x32,0x33,0x91,0xb0,0x8f,0x9e,0xab,0x4e,0x8a,0x64,0x2e,0xa,0x12, + 0x7e,0x98,0xd0,0xb1,0xb5,0x50,0xd2,0xcd,0xc3,0x46,0xb2,0x52,0x5,0x92,0x8b,0x23, + 0xdd,0xa3,0xb0,0x5f,0xf4,0x36,0x75,0x5a,0xa0,0x7b,0xf5,0x1,0x7b,0xce,0x2c,0x91, + 0x25,0x3a,0x98,0x46,0xe7,0x26,0xa4,0x6b,0x9c,0xbf,0xbd,0x45,0x87,0xab,0xd0,0x2b, + 0xa2,0xbc,0xc9,0x1a,0x9e,0x81,0xb2,0x75,0xcd,0x54,0xaf,0xc4,0xa5,0x5f,0xa,0x10, + 0x94,0xd5,0xab,0x1a,0xd4,0x3c,0x4d,0x16,0x91,0x9d,0x2c,0x29,0x6e,0x82,0xde,0x4c, + 0x84,0xe3,0x3,0x7c,0xee,0x6e,0x84,0x19,0xc6,0xcf,0xb8,0x65,0x47,0x5f,0xcb,0xe9, + 0x47,0xfb,0x45,0x5f,0x1b,0x8d,0x84,0x16,0x2a,0xc,0x17,0x7f,0x95,0x3b,0x2,0x2d, + 0x3b,0x7a,0xa5,0x55,0x2e,0xd7,0xb0,0x1a,0xc1,0x4a,0xe,0xa2,0x29,0xcf,0x24,0x65, + 0x7f,0xbb,0x3e,0x44,0x13,0xb5,0x31,0xe0,0x3a,0xcc,0x0,0x91,0x96,0x5e,0xf3,0xcf, + 0xa3,0x82,0x62,0xe3,0x27,0xdc,0xa5,0x14,0x88,0xa5,0xd1,0xe2,0xf7,0x39,0x2d,0xa5, + 0x58,0x5c,0x9e,0xce,0x77,0xa5,0xa7,0xad,0x6a,0xa6,0xdb,0xfa,0x99,0x4a,0xc9,0x91, + 0xdf,0x57,0xe5,0xcc,0xdf,0x73,0x28,0xad,0xed,0x71,0x91,0x6f,0x8c,0x9e,0x44,0xb6, + 0x3b,0x66,0x3a,0x3c,0xf7,0xf9,0x68,0xa3,0xa3,0x97,0x65,0xc7,0xb5,0x8c,0xdc,0x96, + 0x8e,0x8c,0xc2,0x60,0x94,0x53,0x42,0x87,0x70,0x2e,0x58,0xd8,0x4a,0x96,0x37,0xa5, + 0xf3,0x9e,0x2a,0xc3,0x32,0x22,0xa9,0x82,0x17,0xf0,0xb,0x5a,0x26,0x9c,0x35,0x3a, + 0x52,0x7c,0xfc,0xc7,0xf9,0x63,0x79,0x8f,0x12,0x40,0xc1,0x9,0xcd,0x10,0xec,0x41, + 0x67,0xb2,0x3e,0x60,0x43,0x60,0xb2,0x21,0xda,0xd3,0x82,0x24,0x5d,0xd6,0x31,0x4b, + 0x96,0x7a,0xdd,0x25,0x4a,0xbe,0x6c,0x5d,0x64,0xa4,0x1b,0xd6,0x5,0xe6,0xa8,0x53, + 0x6c,0x8a,0xb9,0x16,0x9a,0x8d,0xd0,0x1d,0x8f,0xeb,0xa3,0xa0,0x5a,0x74,0x2c,0x23, + 0xdf,0x54,0x9c,0xe5,0x68,0x53,0xa1,0x69,0x46,0x46,0x65,0x51,0xb0,0xa4,0x84,0x1d, + 0x4a,0xfc,0xb0,0xac,0xe3,0xe5,0x50,0xcb,0xe6,0xea,0x58,0xf3,0x3b,0x51,0x2f,0x6e, + 0x89,0x74,0x1e,0x45,0xe6,0xbc,0x4b,0x6b,0xcb,0x7b,0x91,0xf1,0xc2,0x5b,0xa2,0x32, + 0x5d,0x6c,0x2d,0xeb,0x48,0x54,0xcb,0xcf,0x21,0xbf,0x77,0x58,0x78,0x7,0x75,0x72, + 0xe1,0x5c,0xeb,0x65,0xa2,0x84,0xba,0xae,0x1,0x6d,0xd4,0x55,0x43,0xdf,0xc2,0x90, + 0x95,0xb2,0x5f,0x5c,0xb,0xc2,0xfc,0xa5,0xf4,0x65,0x6b,0xa3,0xc2,0x6,0xd0,0x25, + 0xcb,0xbb,0x8,0xde,0xfc,0xf0,0x76,0x1f,0x8b,0xd6,0xb8,0x8e,0x12,0x6b,0x2b,0x4, + 0xc4,0x5b,0x5d,0x2e,0xba,0x31,0x39,0x5a,0x9e,0x6f,0xc9,0x14,0x11,0x14,0xb6,0x3, + 0x4d,0x6b,0xd6,0xb3,0xb,0x4a,0xa9,0x33,0x15,0x3a,0x42,0x4f,0x9b,0x89,0x68,0x53, + 0xd2,0xa0,0x4a,0xce,0x27,0x88,0xf4,0x3c,0x91,0x44,0x14,0xa4,0xc4,0x79,0xa6,0x86, + 0xa9,0x8b,0x6c,0xd7,0x70,0x2c,0xad,0x0,0x42,0xa7,0x1b,0x6a,0x5d,0x29,0x15,0xf2, + 0x63,0xda,0xa4,0x2d,0xe2,0x39,0x8d,0xf5,0x53,0x29,0x5,0x91,0x1c,0x37,0x7c,0xc5, + 0xb5,0xe2,0xbe,0xd8,0xa2,0x5f,0x5a,0x4b,0x55,0x4c,0xf4,0x44,0xed,0xdf,0x67,0x91, + 0x6,0x9a,0xbf,0xf3,0x16,0x3e,0xb3,0x3d,0x17,0x5e,0x82,0x7b,0xf2,0xaa,0x63,0x36, + 0xe,0x51,0x18,0x84,0xb0,0x91,0x8d,0x7f,0x5d,0x65,0xf,0x59,0x33,0xfe,0x9b,0x15, + 0xed,0x9a,0xb,0x81,0xe2,0x18,0xe0,0x90,0x70,0xa,0xc5,0x2,0x68,0x52,0x5a,0xba, + 0x7c,0xa5,0xd1,0x93,0xfd,0xf3,0x43,0xb4,0x8,0xaf,0xb0,0x18,0x4c,0xab,0xec,0x97, + 0x3b,0x75,0x99,0xce,0x96,0x7,0x56,0x78,0xec,0xa1,0x7b,0x6a,0xff,0x2a,0xf4,0x41, + 0xc2,0xf1,0xe7,0xa2,0x85,0xd2,0x6c,0xb6,0xb9,0xd5,0xf4,0x82,0x66,0xe5,0xe0,0x7a, + 0x68,0x6a,0xd8,0xc3,0xa,0xe0,0x1d,0x54,0x61,0x87,0x6a,0xbd,0x64,0x80,0x13,0x4b, + 0x1b,0x45,0x21,0x1b,0x3f,0xe0,0x40,0xf0,0xad,0x63,0x23,0x5d,0xb,0x88,0x32,0xe, + 0xcc,0xda,0x1,0xaa,0xde,0x4b,0x9a,0x24,0x36,0xdb,0x96,0xda,0x1f,0x63,0xbb,0xdb, + 0x5a,0x26,0xd9,0x4d,0x42,0xed,0x3c,0x47,0x52,0xba,0x71,0x88,0x92,0x7d,0x4e,0x9d, + 0x5b,0xcf,0xaa,0xe9,0x2c,0x40,0xaa,0x21,0x7,0x19,0x25,0xb9,0x7a,0x48,0x84,0xe0, + 0xbb,0x49,0xab,0x91,0x3e,0xbb,0x55,0x71,0xbf,0x6e,0x60,0x37,0x5e,0xfc,0x45,0xc0, + 0xc7,0xe3,0x48,0x49,0x7c,0x74,0x56,0x35,0xf3,0x8,0x7e,0x29,0x3a,0x69,0x15,0xa5, + 0x7b,0x5,0x68,0x21,0x6c,0x92,0xd,0x37,0xbc,0xa7,0x7,0x25,0x3b,0x7b,0x2e,0x22, + 0x96,0xb1,0x8c,0xdb,0x49,0x59,0x3f,0xd1,0x24,0x7,0x26,0xe5,0xcf,0x21,0x69,0x59, + 0x50,0xde,0xcb,0x46,0xda,0x14,0x9a,0x2e,0xb8,0xf6,0x84,0xe,0x10,0x8,0x36,0x6d, + 0xa6,0x5b,0x7,0xac,0xb,0x54,0x89,0xac,0x66,0x2,0x33,0xcb,0x9e,0x5f,0x2e,0xd4, + 0x3a,0x21,0x62,0x2a,0x23,0x7d,0x7a,0x5e,0x20,0x7e,0x8e,0x3b,0x80,0x3f,0xb6,0xac, + 0x78,0x47,0xd6,0xca,0x24,0x3,0x8d,0x2e,0x13,0x95,0x9c,0xaa,0x90,0x87,0x3c,0xb9, + 0x38,0x28,0xa3,0xa7,0x1c,0xf,0xb6,0xae,0x93,0x28,0x41,0x64,0x5d,0xb7,0x49,0x54, + 0x85,0xd,0xd4,0x6f,0x4b,0x5a,0x23,0x4a,0xf2,0x8c,0x6f,0xad,0x91,0xb2,0xf8,0x2f, + 0x15,0xc7,0xdc,0xbd,0x67,0xc5,0xdb,0xc6,0xb3,0xbc,0x7e,0xbe,0xd8,0x8c,0x17,0x25, + 0xa4,0xb4,0x64,0x46,0x47,0xf6,0xbd,0x64,0x7e,0xfe,0x3e,0xf9,0x2f,0x92,0x4f,0x7e, + 0x41,0x85,0x6d,0x44,0x9a,0xe8,0x76,0x17,0x4c,0x2b,0x54,0x17,0xd8,0x15,0x8b,0xf6, + 0xfa,0xae,0xc7,0xef,0x5d,0xa7,0xf,0x1b,0x53,0x4e,0x29,0xeb,0x4f,0xe8,0xca,0x85, + 0xae,0xc9,0x6c,0xf5,0xbf,0x3f,0xbb,0xaa,0xae,0x9a,0xa4,0xab,0x79,0x7d,0x56,0xcf, + 0xbf,0xd9,0x38,0x29,0x91,0xe2,0x9c,0x67,0x5d,0xaa,0x7c,0x2c,0x3f,0xb6,0x32,0x4a, + 0x92,0xed,0x2a,0x45,0x58,0x2d,0x9b,0xc0,0x2d,0xb4,0x4b,0xd3,0xbc,0x57,0x61,0x51, + 0x80,0x83,0xf0,0x5d,0xf5,0x19,0x41,0x22,0x4b,0x6a,0xd9,0x86,0xb8,0x4d,0x37,0xc4, + 0xd,0x5e,0xe9,0x6b,0x1,0xe4,0x1b,0x19,0x6a,0xe9,0xe0,0x75,0xef,0xe8,0xbb,0xee, + 0xe5,0xd7,0x11,0x3f,0x55,0xec,0x15,0xc8,0x80,0xfc,0xb5,0x25,0x64,0xae,0x56,0x95, + 0xbd,0x6e,0x8,0x4d,0xea,0xf6,0x45,0x97,0xee,0xcc,0xf6,0xe4,0x29,0xf9,0x8c,0x3b, + 0xfd,0x96,0xa3,0xc8,0x9d,0x71,0xbe,0x74,0x4d,0xcd,0x62,0x11,0x53,0xa7,0x87,0x8d, + 0xbd,0x22,0xea,0xee,0x54,0x73,0x22,0x37,0x80,0x39,0x6a,0x6c,0x41,0xb2,0x96,0x56, + 0x3a,0x65,0x2d,0x16,0xae,0xad,0xe,0x80,0xbe,0xce,0x14,0xd2,0xae,0xfb,0x84,0x1c, + 0xfb,0xc5,0xfc,0x1c,0x31,0xbb,0x39,0x7a,0x94,0x8d,0x95,0x43,0x15,0xda,0x48,0xb2, + 0xf1,0x4,0x4,0x46,0x8b,0x12,0x3d,0x8a,0x33,0x10,0x10,0x26,0x71,0xa0,0x25,0x17, + 0xaf,0xba,0xa8,0x65,0xb7,0xf6,0xaa,0x2d,0xb1,0xe9,0x73,0xb7,0xd,0x9f,0x20,0x2d, + 0x64,0x2f,0x8e,0xa0,0x54,0xf5,0xf7,0x4b,0x1b,0x97,0x4c,0xad,0x40,0xf9,0x74,0x7d, + 0xc7,0x96,0x7b,0x9c,0x12,0x4c,0x36,0xf2,0x1c,0xb6,0x42,0x7f,0x64,0xaf,0xcb,0x1, + 0xcb,0x44,0xae,0x16,0xe8,0x4c,0x30,0x83,0x64,0x30,0x95,0x50,0xa,0x95,0x15,0xe9, + 0x3d,0x8d,0xb7,0x63,0x22,0x11,0xdd,0x6d,0x2b,0x85,0x81,0x96,0xa7,0xaf,0x15,0xea, + 0x60,0x4a,0x14,0xc8,0xe4,0x89,0x46,0xe2,0xb,0xad,0xbb,0xf6,0x96,0xc5,0x63,0x69, + 0x8f,0x8b,0x45,0xd,0x53,0xb9,0x1c,0x69,0x5,0xd5,0xb6,0x83,0xde,0x91,0x56,0x13, + 0xba,0x8a,0x2b,0xf7,0xae,0x44,0x56,0x7e,0x1,0xf6,0x94,0xcf,0x39,0xad,0x52,0x6b, + 0xb4,0x40,0xce,0x96,0xdf,0xf0,0xb3,0xc7,0x5d,0x82,0x3d,0x65,0x48,0xa3,0xf5,0xa5, + 0xfd,0x8c,0x5b,0x7e,0xf5,0x5,0x39,0xb2,0x92,0x34,0x3f,0x89,0x19,0x52,0xa7,0xb1, + 0xe5,0x68,0xe8,0xdb,0x1e,0x8e,0xd,0xf,0x84,0x2e,0x81,0x5d,0x71,0x97,0x21,0x83, + 0x8f,0xf6,0x68,0x2d,0x62,0x90,0x81,0x8d,0x22,0x4d,0x69,0x5a,0x54,0x47,0x42,0x45, + 0xbc,0x39,0xcf,0x50,0xfb,0x2c,0xe,0x71,0x50,0xab,0xc4,0x96,0x3b,0x6e,0xd9,0x27, + 0x52,0x2f,0xb9,0xe0,0x5,0x89,0xca,0x41,0x9b,0xf9,0xf7,0xa8,0xec,0xdb,0xc8,0xaf, + 0x55,0xaa,0x10,0x8e,0x74,0xed,0x52,0x3a,0xa9,0x5e,0xb3,0x9d,0xac,0x8,0x64,0x18, + 0x7a,0x41,0xf,0x42,0xe7,0x96,0xb7,0xc5,0xb8,0x45,0xdd,0xcb,0x8a,0x94,0x13,0xcd, + 0xa2,0xa5,0x34,0x4e,0xa4,0x51,0x68,0xd8,0xd5,0x5b,0x22,0xeb,0x68,0xcb,0x5f,0xc7, + 0x3e,0x84,0xe8,0x3e,0xab,0x4e,0x8a,0x30,0x4a,0x23,0x72,0xd9,0x8,0xa1,0x97,0x3c, + 0x65,0xa0,0x3c,0xf1,0xaa,0x42,0xdd,0x12,0x88,0x55,0xe2,0x42,0xe7,0x9a,0x97,0x27, + 0x1d,0xce,0xc5,0x5e,0x11,0x8d,0x32,0x23,0x4f,0x63,0xc2,0xa3,0x85,0x9a,0xb4,0x56, + 0xfa,0x9b,0x54,0xa5,0x42,0xf2,0x43,0x8a,0x37,0x6d,0x11,0x92,0x91,0xbc,0xa3,0x65, + 0xff,0xb,0x6c,0x78,0x2c,0x75,0xcf,0x82,0x56,0x97,0xbf,0x95,0x87,0xb,0x48,0xb6, + 0x16,0xe7,0x81,0x57,0xbb,0xd8,0xd2,0x3d,0x6a,0xe5,0x5e,0xfb,0xb3,0xb6,0x3d,0xe, + 0xce,0x85,0x12,0x24,0x63,0x8a,0x42,0xc3,0xa9,0xce,0x9f,0x4f,0xcc,0x5,0x2e,0x4c, + 0xcb,0xe5,0xd9,0xe5,0xf3,0xa7,0x5d,0x58,0xba,0x1f,0xa6,0x21,0x62,0x59,0xdf,0x14, + 0x68,0xac,0x7f,0x1e,0x79,0x13,0xba,0xa,0x6e,0xf3,0xe7,0xba,0x5,0xeb,0xd0,0xe4, + 0x76,0x88,0xf3,0x4c,0xa9,0xd0,0x6c,0x65,0x62,0xb1,0xa1,0x15,0xa9,0xd6,0xaa,0xc5, + 0xcb,0xae,0x44,0xed,0xca,0x72,0xa,0x6c,0xec,0x90,0x43,0x38,0x19,0x6b,0x97,0x8, + 0x60,0x29,0xee,0x83,0xa6,0xe5,0x2a,0xb0,0x77,0x8d,0x4,0xa5,0xa6,0xa7,0x28,0x93, + 0x8e,0xae,0xeb,0xbe,0x4c,0xcb,0xbe,0x3a,0x65,0x50,0x80,0x89,0x71,0x3c,0x36,0xaf, + 0x54,0xbc,0x3a,0xa9,0x42,0x50,0x31,0xe7,0x67,0x11,0xaf,0x32,0x9,0xb1,0x90,0xcb, + 0xf8,0xcc,0x40,0xd0,0x24,0xa8,0x5d,0x2d,0x18,0x5b,0x24,0xc3,0xfd,0xe7,0x5e,0x2a, + 0xda,0x44,0x16,0xe8,0x15,0x40,0xa2,0xe3,0xd,0x5b,0x98,0xff,0xec,0x36,0x2c,0xc9, + 0xeb,0xe4,0x82,0x5,0xcc,0xa0,0x7b,0x40,0x64,0x8b,0xee,0x9,0xda,0xbf,0x6b,0x99, + 0x4e,0x6,0xf8,0x89,0x68,0xa7,0x9f,0x93,0xbb,0xa0,0x89,0x3c,0x29,0x45,0x1f,0x84, + 0x7c,0x7f,0x90,0x6e,0x20,0x9,0x33,0xad,0x49,0x1a,0x69,0x6b,0xa4,0xce,0x4c,0x54, + 0x36,0x94,0xb1,0x28,0xb6,0xb0,0x49,0xf1,0x45,0xb6,0xb2,0x70,0xd6,0xad,0xec,0xf3, + 0x7d,0xad,0x52,0x11,0x66,0xa2,0x64,0xef,0xa2,0x86,0x15,0x6b,0x56,0xad,0x4b,0x8, + 0x43,0x20,0x1b,0xcf,0x12,0x1d,0x25,0x8b,0x3e,0x60,0x45,0x87,0xa6,0x1d,0xa4,0xe7, + 0x2e,0x3b,0xf8,0x1f,0x94,0xbb,0x4e,0x4a,0xcf,0xb6,0x25,0x22,0x91,0xe5,0xb2,0xca, + 0x3f,0x8a,0xb5,0xf2,0xab,0xd0,0xff,0x75,0x7d,0x91,0x41,0x46,0xac,0x13,0x90,0xb4, + 0xbf,0x85,0x8f,0xd3,0xd9,0x4a,0x96,0xf7,0x3a,0x1a,0x87,0x10,0xef,0xf,0x45,0x37, + 0x3e,0xbf,0x72,0x58,0xea,0xe7,0x88,0x97,0x36,0x96,0x2d,0x28,0x9e,0x87,0xba,0x42, + 0x0,0x72,0x22,0x56,0x46,0x81,0x22,0xf9,0xb6,0xa3,0x9b,0x35,0xeb,0x4a,0x74,0x4e, + 0x6b,0xda,0x93,0x48,0xe,0x0,0x58,0x1a,0xf4,0xe4,0xd3,0x8f,0x5a,0x35,0x3f,0x4f, + 0x48,0x21,0x29,0xf9,0x79,0x5b,0x64,0x9b,0xe6,0x7c,0xa0,0xcb,0x2a,0x8b,0x39,0x9b, + 0xe3,0xb1,0x37,0x29,0x7e,0x25,0x19,0xcc,0x30,0xbb,0xfc,0xe5,0x2f,0xf4,0xc0,0xa6, + 0x45,0x40,0xb3,0xe7,0xe7,0xa1,0x7b,0x1e,0x4e,0x17,0xea,0x71,0x3c,0x50,0x62,0x3a, + 0x6c,0x8b,0x91,0xdc,0xe5,0xd2,0x36,0xfc,0xf4,0xba,0x3d,0xe1,0x50,0xb7,0x63,0x25, + 0xd7,0xa5,0x8f,0xf,0x4b,0x2d,0x96,0xbb,0x14,0x95,0xb0,0x29,0x36,0xba,0xc4,0x91, + 0xc1,0x38,0x7b,0xf4,0xea,0xee,0x1e,0x48,0x2b,0x8b,0x6c,0x1d,0xd4,0xe4,0xa7,0xc7, + 0xca,0x96,0xf0,0xaf,0x76,0x6b,0x14,0xca,0xce,0x3,0x5d,0x6b,0xcb,0x2a,0x4e,0xe2, + 0x3c,0x71,0x29,0x29,0x4f,0xe9,0xe6,0x6d,0x31,0x89,0x54,0x95,0x7a,0xac,0xbb,0xf6, + 0x81,0xbe,0xe7,0x9e,0x9e,0xa7,0x66,0x9,0xed,0x69,0x57,0xaf,0x99,0xb5,0x9e,0x43, + 0x44,0x24,0x21,0x98,0x23,0x38,0xa4,0x14,0x12,0xfc,0x75,0xf4,0x4d,0xa7,0x3b,0x59, + 0xbe,0x8a,0xf0,0x1c,0x5b,0x71,0x8e,0xac,0xed,0x68,0x28,0x6f,0x32,0x28,0x25,0x52, + 0xb7,0xd5,0xe7,0xfb,0xce,0x23,0x7,0x64,0x68,0x16,0x9f,0xb1,0x32,0x7f,0xeb,0xac, + 0x93,0x2d,0x36,0xdd,0x5a,0x4,0xc8,0xd2,0xed,0x6b,0x1a,0x85,0xf6,0x74,0xbe,0x90, + 0x0,0x53,0x91,0x58,0xfc,0x5a,0x4,0xcb,0xaa,0x42,0xfc,0x90,0xe2,0x3f,0x27,0x21, + 0xed,0x60,0xb9,0xcf,0xf,0xa6,0xab,0x50,0x24,0xd0,0x7c,0x79,0x95,0xc9,0x59,0xba, + 0x71,0x16,0x68,0xe9,0x22,0xea,0x3,0xa6,0x6e,0xa9,0xa9,0x6c,0xff,0x54,0x74,0x31, + 0x39,0xcd,0x13,0x67,0xb2,0x78,0xcc,0x33,0x66,0xd3,0xce,0x6a,0x6b,0x5f,0x58,0xfc, + 0xdd,0xfe,0xe7,0xb6,0x5c,0x30,0x14,0xad,0x86,0xd6,0x2b,0x95,0x80,0x1,0xe2,0xc8, + 0xcd,0x95,0xda,0xb6,0xb5,0xaf,0xf,0xe,0x38,0x16,0xe1,0x9,0x57,0x6e,0xf5,0x6b, + 0x7,0xef,0x4e,0x45,0xf6,0xc4,0xa8,0xea,0x62,0xa3,0xc8,0xfb,0xc7,0x2c,0x5e,0xea, + 0x69,0xe2,0xa7,0xb1,0x23,0x4e,0x19,0xf6,0xc1,0x2c,0x47,0x92,0xf,0xa8,0x54,0x19, + 0x5f,0x15,0x11,0xb2,0x16,0x22,0xd9,0xa6,0xa6,0xca,0x5b,0xb7,0x2c,0x6a,0xc4,0xdf, + 0xdf,0x5b,0x9d,0xa7,0xef,0x55,0x23,0x64,0x64,0x4b,0x11,0xad,0x45,0x67,0x90,0x46, + 0x9f,0x58,0x5,0x3d,0xc4,0x3a,0xe8,0x58,0x45,0xd3,0x9d,0xb8,0xc,0x31,0xa1,0xc0, + 0xa6,0x80,0x2f,0x56,0x3e,0x15,0x0,0x53,0x84,0x8c,0x96,0x99,0x4c,0x45,0x44,0xcd, + 0x91,0x54,0x1f,0xf,0x6a,0x1a,0xc1,0x8a,0x6c,0xd0,0xa3,0xea,0x21,0x97,0x4,0x93, + 0xd1,0xd9,0x46,0x1d,0xdc,0x4,0x9b,0x8e,0xf0,0xea,0xc2,0x6d,0x92,0xa7,0xb7,0x5b, + 0x62,0x46,0xa6,0x64,0xb5,0xb5,0xdb,0xdd,0x48,0x5e,0xd4,0xa2,0x84,0x7,0xe8,0x70, + 0x6a,0x48,0xd9,0xce,0x8b,0xc8,0xa8,0x14,0xe6,0x9a,0xc4,0xb1,0xf9,0x22,0x15,0xfa, + 0xac,0xfd,0x1c,0x13,0x49,0xa3,0x71,0x9e,0xf2,0xa0,0x44,0x5f,0x4a,0x21,0xc3,0x81, + 0x19,0xf4,0x1b,0x5,0x92,0xa6,0xf5,0x92,0xa4,0x55,0x87,0x6c,0xc,0xcf,0x54,0xf7, + 0xa5,0xe6,0xd5,0x30,0x2b,0xd6,0x4a,0x44,0xe2,0x50,0x2a,0x96,0xd2,0xba,0x87,0x95, + 0xd1,0xba,0x58,0x20,0xad,0x8,0xef,0xfc,0x4e,0xf2,0x6b,0xd3,0xf2,0xcf,0x6d,0x71, + 0xdd,0x68,0x4b,0xbb,0xf7,0x14,0xce,0x27,0x4c,0xa8,0x24,0x3f,0x79,0xd1,0x6f,0xc0, + 0x27,0x2b,0xeb,0xd8,0x1b,0xb,0xec,0x54,0x32,0x52,0xd9,0xa7,0x92,0x9a,0xf5,0xaa, + 0x29,0x2,0x97,0xc1,0x94,0xfb,0x9d,0x1c,0x4c,0xfe,0xdc,0x1e,0xa6,0x6f,0x23,0x78, + 0x40,0xb4,0xd2,0x3c,0x2,0x57,0xd9,0x84,0xe5,0x95,0xe9,0x6a,0x42,0x9c,0xd6,0x69, + 0xc3,0x46,0xb1,0xce,0xdf,0xb3,0x88,0xac,0xa8,0xe5,0xd2,0xd4,0x8a,0x58,0x7c,0xaa, + 0xca,0xc6,0xe,0x19,0x9b,0x15,0x76,0x55,0xcb,0xfa,0xf8,0x1a,0xb9,0x4e,0x45,0x11, + 0x7e,0x10,0x97,0xb8,0x74,0xcd,0x9a,0x78,0xd9,0xfc,0xc3,0xe5,0x57,0xb0,0xcf,0xbd, + 0x89,0x24,0x48,0xc8,0xda,0x78,0xb9,0x58,0x29,0xed,0xe5,0xe9,0x43,0x17,0x3a,0x3c, + 0xa8,0x90,0x80,0xac,0x17,0xf6,0xfa,0x53,0xfa,0xbc,0x9,0x3,0xb2,0xed,0x80,0xc7, + 0xbf,0xd3,0x4e,0x11,0x21,0x14,0x1b,0x7b,0xab,0xd2,0x59,0x61,0xb3,0x2f,0xcf,0x5d, + 0xfb,0x42,0xe9,0x4b,0x23,0x30,0xa4,0x3,0xad,0xdb,0x88,0x50,0x9,0x6e,0x41,0x15, + 0x4d,0xbd,0xb4,0x72,0xa7,0x55,0xc4,0x4e,0x55,0x1c,0xc2,0xea,0xe3,0x74,0x88,0xd6, + 0xa9,0x89,0xd2,0x67,0x3e,0x3b,0x55,0x94,0x54,0x7a,0x91,0xc5,0x86,0xc7,0xaa,0xf6, + 0x0,0x43,0x6e,0x6b,0x1e,0x12,0x39,0x6b,0xb9,0x94,0xf6,0xed,0x6f,0xb1,0x69,0x51, + 0x64,0xd7,0x1,0x96,0x9f,0xad,0x2c,0x4e,0xf,0xf6,0x82,0xb3,0x5b,0x66,0x7d,0x16, + 0xd7,0x98,0x58,0x94,0x45,0x7,0x92,0x60,0x33,0x6c,0x97,0x34,0xca,0x48,0x60,0xa6, + 0xf4,0xd,0xb5,0x6a,0x17,0xcd,0xef,0x57,0x75,0x58,0xf4,0xe5,0x42,0xc9,0x13,0x2d, + 0x2d,0xef,0x3e,0x4f,0xcb,0x7c,0xfc,0x2d,0x48,0x6a,0xfd,0xbc,0x8a,0x40,0xfa,0xbe, + 0xd5,0x47,0x93,0x9f,0x3f,0xfa,0x67,0x2a,0x5a,0x7a,0x1e,0x69,0x7f,0xbe,0x58,0x19, + 0xa9,0x9b,0xd5,0x32,0x5d,0xb1,0xcf,0x3f,0x46,0xc9,0xf9,0xf9,0xdd,0xf4,0x5,0x17, + 0x56,0x2,0x8,0xf8,0x64,0x1a,0x8,0x21,0x2a,0xa3,0x29,0xae,0x8b,0x84,0x62,0x53, + 0x3c,0xb9,0x5a,0xc6,0x4c,0x5f,0xa1,0x89,0x8c,0x82,0x14,0xc9,0x5a,0x8c,0xc3,0x9a, + 0xe9,0x99,0xaa,0xb2,0xe8,0x39,0xb6,0x34,0x47,0x81,0x8c,0xc5,0xfa,0x73,0xe7,0xe9, + 0x18,0xef,0x80,0x49,0x47,0xe1,0x2a,0xfb,0x2d,0x97,0x4d,0x7a,0xf7,0x75,0x13,0xd7, + 0xbc,0xee,0xeb,0xd7,0xa2,0xde,0x75,0x6,0x1b,0x82,0x4e,0xc7,0xdf,0x5b,0xc4,0x62, + 0x13,0x17,0x5b,0x76,0xd6,0xd,0x2c,0xfe,0x2d,0x2d,0xc3,0xf,0xdd,0xd0,0x85,0x91, + 0xc5,0x19,0xec,0xbe,0xc8,0x15,0x1a,0x4a,0xb5,0x96,0xf2,0x91,0xe8,0x39,0x93,0x14, + 0x26,0xa3,0x1b,0xa7,0x7b,0x71,0xa6,0xab,0x16,0x34,0x3a,0x29,0xf3,0x92,0xc3,0xa5, + 0x2d,0x67,0xd6,0xa1,0x1c,0xb4,0xcd,0x3,0x4d,0xb7,0x90,0x9e,0x5c,0x1,0x16,0x7, + 0x38,0x5f,0x4a,0xcb,0xde,0x70,0x41,0x9a,0x6e,0x2d,0xf8,0xc9,0xf7,0x37,0x85,0x3e, + 0xf5,0x90,0x64,0x55,0x26,0x38,0xad,0x86,0xd8,0xb6,0x59,0xa9,0x5a,0xa3,0x5d,0x65, + 0xff,0x21,0x48,0x55,0x7e,0x95,0x6d,0xe4,0xd0,0x1a,0x2,0x33,0x2e,0xde,0x6d,0x1a, + 0xf6,0xf1,0xc2,0xbe,0xd5,0x3d,0x76,0x4d,0x56,0xd3,0x65,0xc3,0xa3,0x1b,0x14,0xb1, + 0x88,0x8c,0x45,0x70,0x9e,0x79,0x35,0x62,0xc2,0xbb,0x12,0xd9,0x87,0x2d,0xd1,0x5e, + 0x15,0x9d,0xcb,0xa,0x80,0x9,0x70,0x8a,0x16,0x5d,0x44,0xcc,0xcd,0xd6,0xc3,0x2a, + 0xa7,0x78,0xd5,0xfe,0x2f,0xd9,0x38,0x34,0xf6,0xaf,0xa0,0x13,0x9,0x64,0x38,0x91, + 0xc,0xa3,0x98,0xcf,0x57,0xf1,0x82,0xab,0x6e,0x2a,0xcd,0xeb,0xa5,0x59,0xe0,0x77, + 0x45,0x85,0xbc,0x7a,0xb6,0x63,0x4f,0x4e,0xcf,0x74,0xd3,0x4,0x77,0xd9,0x46,0x37, + 0xd6,0xbf,0xb7,0x7e,0xae,0x4b,0x8f,0xc6,0x97,0x14,0xf2,0x8a,0x20,0x8d,0x6e,0x4d, + 0xc0,0x69,0xf1,0xb5,0x44,0x89,0x72,0xb6,0x83,0xae,0x5f,0x17,0x52,0x31,0x96,0x31, + 0x4c,0x96,0x5e,0x18,0x23,0x48,0xcf,0xcd,0x4e,0x99,0xdb,0x86,0xd7,0x65,0x81,0x55, + 0x77,0x12,0x79,0x11,0x60,0xa5,0x41,0xf5,0x6,0xd1,0x8b,0xce,0x17,0x25,0x1,0xa9, + 0xb2,0xe,0xc7,0x2e,0xd4,0x12,0x98,0xb2,0xee,0xe4,0xdb,0x6,0x41,0x40,0x97,0x45, + 0x56,0xba,0xc4,0x73,0xa0,0x44,0xba,0x8,0xe3,0xb9,0x2d,0xa1,0x32,0x34,0x9e,0xb6, + 0xf7,0x4f,0x36,0xf9,0x1,0xfb,0x54,0xff,0x79,0xd7,0x97,0x77,0xb6,0xb9,0xb,0x16, + 0x95,0xc5,0x5e,0xa5,0xde,0x21,0x13,0x43,0xa3,0xa0,0x60,0x3a,0x89,0xf7,0xfc,0x27, + 0xee,0xd3,0xba,0xc2,0x90,0x60,0xbb,0xe4,0x46,0xfc,0x2d,0xa4,0x3c,0xaf,0xda,0xb6, + 0x35,0xe,0xb2,0x15,0xd3,0xb2,0xa7,0x1,0x4a,0x79,0x1,0x28,0xeb,0xb0,0x6c,0xf9, + 0xc1,0xc6,0x8e,0x88,0x27,0x44,0xeb,0xaf,0xf7,0xa8,0xd0,0xf5,0x73,0xd6,0x1c,0xa9, + 0xd0,0x5,0x4d,0x31,0xd9,0xae,0x9c,0x85,0xb3,0xeb,0x1c,0x78,0x6d,0x0,0xf3,0x24, + 0x89,0x84,0x83,0x64,0x7,0xcd,0xac,0x7c,0x22,0xbe,0x69,0xe,0x7,0xb,0x5d,0x56, + 0x76,0x15,0xe5,0x64,0xc1,0xf9,0x1c,0xbf,0xf6,0x17,0x3f,0xff,0x81,0x26,0x31,0x9, + 0x12,0x77,0x3c,0xef,0x5a,0xb2,0x46,0x43,0xab,0x30,0x6e,0xd3,0xf2,0x51,0x52,0x70, + 0x58,0x40,0x6,0x59,0x11,0x81,0x89,0x6b,0xbe,0xad,0x72,0xae,0x87,0xf9,0x2f,0xdb, + 0xc9,0xcb,0x3e,0xbc,0xe8,0x5e,0xe,0x6a,0x7e,0x44,0x45,0xb5,0x98,0xc0,0x74,0xd9, + 0xa,0xaf,0x7f,0xe0,0x1e,0x1f,0xb9,0xbf,0x90,0x34,0xc6,0x99,0x1f,0xbe,0x32,0xfe, + 0x4f,0xd6,0x51,0x30,0xf6,0x7c,0xd9,0xba,0xe7,0x9f,0xed,0x7b,0xbd,0x50,0x56,0xaa, + 0x48,0xac,0x79,0x1b,0xc1,0x63,0xe9,0xf0,0x72,0x8e,0xf6,0x3a,0xb7,0x59,0x7d,0xeb, + 0x22,0x5b,0x9,0x67,0x9b,0xc1,0x60,0xb2,0xa7,0x75,0xa9,0x19,0xf4,0x1b,0x44,0xa5, + 0x2d,0xc1,0x26,0x90,0x9,0xe4,0xca,0xc2,0xb1,0xff,0xb7,0xb4,0x2b,0xf,0xd6,0xb3, + 0xae,0xce,0xe7,0xfc,0xbe,0x4b,0x36,0x72,0xb3,0xb1,0x84,0x0,0x12,0x8,0x21,0x10, + 0x40,0x8,0x48,0x9d,0xb1,0x75,0x6c,0xed,0xd4,0x5,0xa7,0x9d,0x76,0xfa,0x47,0x47, + 0x56,0x97,0x29,0x2e,0x14,0x1c,0xa7,0x38,0xc5,0x2e,0xe3,0xb4,0xe,0xd6,0xd1,0xa9, + 0x9d,0xa2,0x56,0xea,0x54,0x1,0x5b,0x6a,0xc7,0xa5,0x15,0x1d,0x1d,0x15,0x6b,0x37, + 0x7,0x47,0x11,0xbd,0xc1,0x5,0x12,0x3,0x9,0x84,0xc5,0x40,0x2,0xd9,0x6e,0x9a, + 0x5c,0x42,0xbe,0xd3,0x3f,0xbe,0xef,0x7d,0xdf,0x73,0x9e,0xf3,0xfc,0xde,0xef,0x32, + 0x66,0x86,0x21,0xb9,0xf7,0x5b,0xde,0xf7,0xf7,0xfe,0x96,0x73,0x9e,0xf3,0x9c,0xe7, + 0x9,0x38,0xb7,0xfb,0xda,0x90,0x61,0xb4,0xce,0x30,0x54,0x98,0x16,0xe9,0x91,0xc1, + 0xcb,0x1d,0x1e,0x82,0x41,0xe9,0x21,0xb6,0x35,0x91,0x3a,0x9c,0xb2,0xbe,0x6d,0x49, + 0xf6,0x3a,0xcc,0xc9,0x30,0x11,0xcc,0x12,0x1b,0x5c,0x82,0xcd,0x35,0x2a,0xec,0xf4, + 0x77,0x4,0x54,0xd6,0x47,0x42,0x95,0xfc,0xcb,0xc,0x9a,0x99,0x2d,0x6f,0xf0,0xae, + 0x5d,0x35,0xa2,0x17,0xd1,0xa2,0x55,0x13,0xa2,0x62,0xd4,0x38,0x46,0x13,0xf6,0x12, + 0x37,0x58,0x16,0x73,0xa9,0x64,0x94,0x32,0x56,0xe2,0xa3,0x16,0x62,0x26,0xf7,0x11, + 0x59,0x38,0xff,0x59,0xde,0x22,0x56,0x41,0x93,0x3,0xfb,0xba,0xc,0x84,0x7c,0xaa, + 0x9,0x51,0x3f,0x5e,0xd8,0x96,0xfd,0x80,0x2e,0x20,0x94,0xb4,0x29,0x60,0x78,0x9a, + 0x9,0x9a,0x2a,0xd1,0xa4,0x2a,0x3c,0x23,0x8d,0x6a,0xed,0x8a,0x89,0x98,0x75,0xfa, + 0x2,0x6d,0x42,0x46,0xba,0x25,0x54,0x90,0x7,0x98,0xc9,0x94,0xc8,0x1f,0x4b,0xed, + 0xd2,0x66,0xf1,0xfc,0x76,0xc1,0x61,0xcb,0x1,0x31,0x83,0xee,0x18,0xd6,0xa6,0x28, + 0xd4,0x74,0x5b,0x7a,0x3a,0xbf,0x94,0xa3,0xf5,0x3c,0xce,0x97,0x6c,0x9f,0x2a,0x9, + 0x51,0x31,0xc2,0x15,0x68,0xbd,0xe8,0x42,0x70,0xa4,0x22,0xa3,0x1a,0x7a,0xb,0x39, + 0x15,0xb,0x6,0xe,0x11,0x16,0x27,0x35,0x85,0x70,0x23,0x9d,0xef,0x75,0xd7,0x92, + 0x51,0xc6,0xed,0x6b,0x26,0xd4,0xe,0x35,0xcc,0x5f,0xd,0x10,0x69,0xe,0xf,0x98, + 0x35,0xa2,0x66,0xfe,0x2c,0xa2,0x12,0x32,0x82,0xf7,0xd4,0x9,0xa7,0x50,0x6,0x74, + 0x4c,0x74,0x43,0xd,0xd5,0x12,0x23,0x12,0x33,0x60,0x62,0x3f,0x2a,0x7c,0x11,0xb6, + 0xf5,0x12,0x54,0xc6,0x33,0x2f,0x36,0xc0,0x32,0x4d,0x62,0x92,0xe1,0x33,0x69,0x27, + 0xc2,0x61,0xa1,0x5e,0x63,0xce,0x6d,0x38,0xf6,0x96,0x9b,0x4a,0x78,0xbe,0x9a,0xbc, + 0xed,0x39,0x1c,0x35,0x54,0xf4,0x21,0xc7,0x60,0x2d,0xd6,0x88,0x2,0xe3,0xd7,0x9c, + 0x9d,0x9a,0x10,0xc2,0xb,0x9,0xac,0x34,0xb8,0x58,0xa1,0xcd,0xaa,0xf2,0xf6,0x34, + 0xa7,0x9e,0x16,0xea,0xaa,0xa4,0x6d,0xa7,0xe,0x8d,0xd6,0x18,0xb9,0x40,0xf6,0xf3, + 0xf2,0xbe,0xda,0x5,0xc6,0x58,0x5a,0xca,0xe5,0xe7,0xa6,0x8d,0x8a,0xf1,0x13,0xba, + 0xec,0xd0,0x80,0xed,0xdc,0x74,0x1b,0x18,0x74,0x5d,0x48,0xe7,0xc0,0x19,0xc7,0xa6, + 0xb8,0x80,0xad,0x62,0x92,0x22,0xb4,0x46,0x4f,0xec,0x8f,0x25,0x46,0xf7,0xa8,0x29, + 0xe1,0xb3,0x1a,0x81,0x1e,0x5f,0x7e,0x28,0xe5,0x8c,0x9a,0x95,0x3,0x62,0x99,0x43, + 0xc1,0x7e,0xd8,0xcf,0x73,0x37,0xa7,0xc7,0x3f,0x1b,0x26,0xe,0x41,0xac,0x48,0x66, + 0x5,0x44,0x3,0xb1,0x1f,0x47,0x86,0x1c,0x6b,0x9c,0x7b,0xd2,0xa6,0x17,0x19,0x69, + 0xda,0x11,0x2d,0x45,0xe3,0x1a,0x9,0xa7,0x55,0x4,0xa9,0xeb,0x2f,0x57,0x10,0xad, + 0xb2,0xe0,0xb8,0xe2,0x21,0x78,0xd2,0x91,0xdd,0x20,0x5d,0xc1,0xa0,0xc9,0xad,0xa1, + 0x52,0x3f,0x2c,0x2,0xa1,0xc3,0xd,0xbc,0xf9,0x9a,0xb1,0x60,0x69,0x31,0x12,0xb9, + 0x4c,0x33,0xf,0xc2,0x4b,0xa0,0xa2,0x6a,0x67,0xc7,0x5f,0xc1,0xdd,0x7f,0xdc,0x97, + 0x6d,0xfe,0x99,0xba,0x92,0x6e,0xfb,0x7d,0x44,0xb1,0xb3,0x25,0x2c,0x47,0xd7,0x3e, + 0x25,0x84,0xc6,0xe6,0xbe,0xd4,0x22,0x82,0x91,0x33,0xa9,0xc2,0x89,0x96,0xae,0x54, + 0x11,0xe5,0x5,0xb4,0xd2,0xc9,0x22,0x89,0x87,0x13,0x3b,0x6c,0x9a,0x20,0xa5,0x50, + 0x75,0x44,0x23,0x52,0xe3,0x26,0x36,0x82,0xdc,0x73,0x6b,0x8d,0x27,0x9d,0x29,0x5a, + 0x62,0x4a,0xc4,0x9a,0x1,0xbe,0x2d,0x20,0x28,0xe2,0xea,0x57,0x11,0xea,0x8a,0xb0, + 0x2c,0x66,0x23,0xcd,0x82,0x19,0x12,0xe5,0xd,0x2f,0x52,0x31,0x6a,0xdb,0x19,0x1f, + 0xbe,0xe,0x2a,0x35,0x89,0x19,0xc8,0x30,0x1d,0x12,0x4,0x12,0x4b,0x3,0x9a,0x25, + 0xe,0xd5,0xe9,0x6e,0x1a,0xa9,0x15,0x8a,0x6b,0xa1,0xf2,0x16,0x77,0x4c,0x20,0x4, + 0x8f,0xa,0x83,0x9a,0x92,0x26,0x75,0x2f,0x84,0x2d,0xb1,0x2,0xc3,0x5a,0x2,0x33, + 0xb1,0x8c,0xa5,0xc7,0x46,0xe4,0x63,0x55,0xb2,0xfe,0xd3,0x30,0x40,0xa4,0x92,0x94, + 0xb1,0x1a,0x62,0xa3,0xaf,0x5d,0x37,0xc6,0x12,0xc4,0x5,0x29,0xc0,0xcd,0x9e,0x19, + 0xaa,0x86,0xed,0x31,0x9d,0x63,0x9f,0x5a,0x14,0x85,0x49,0x1,0x82,0x11,0xab,0x71, + 0x5f,0xfa,0xa8,0x5a,0x41,0xf2,0xfa,0xb1,0x38,0xc8,0x2d,0x35,0x5f,0xb7,0xce,0x6a, + 0xe2,0x4,0x75,0x72,0xab,0x8e,0x55,0xe1,0x23,0x71,0x9b,0x56,0xee,0xc2,0x88,0x5a, + 0x1,0x5d,0x24,0x6e,0x2d,0xfc,0x3e,0xba,0x86,0x21,0x24,0xc4,0xc9,0x2f,0xd9,0xc1, + 0xe7,0x9,0x59,0x70,0xac,0xdb,0xf0,0xbc,0x7d,0x3b,0x95,0x7a,0x38,0x1f,0x82,0x1a, + 0x8b,0x4,0x33,0xda,0x7e,0xd8,0x7,0xa1,0x11,0x33,0x16,0xb5,0x6c,0xa8,0x81,0xea, + 0x7b,0xb1,0x36,0x5f,0x42,0xac,0xe7,0x6b,0xe9,0x3c,0x48,0xf5,0xcf,0x4e,0xb3,0x45, + 0xaf,0xdf,0x40,0x3d,0x27,0xc7,0x9,0x7f,0x78,0xb,0xd2,0xe4,0xf1,0x20,0xa4,0x94, + 0x15,0x4a,0x1e,0xbe,0x1d,0x30,0x66,0xbc,0xad,0xbd,0xa6,0x69,0xe0,0x29,0x59,0x0, + 0x5d,0xbc,0x3f,0x1,0x5a,0x1b,0x2b,0x68,0xce,0x63,0x2,0xe4,0x78,0x2f,0x22,0x3d, + 0x7e,0x19,0xe2,0xf6,0xb3,0x2,0x6b,0x5b,0x9c,0x15,0x68,0xd,0xce,0x1,0x8f,0x76, + 0x48,0x86,0x4d,0x62,0xb6,0x9f,0x89,0x7d,0xb1,0x26,0x6f,0xa1,0xfc,0x85,0x87,0x34, + 0xba,0xea,0xe5,0xbd,0xcc,0x93,0x5e,0x51,0x15,0x20,0x58,0x61,0x2b,0x66,0xe9,0x12, + 0xba,0xad,0xb4,0x91,0x75,0xe,0xda,0xb,0x9e,0x8,0x1e,0xa9,0x8d,0xc3,0x20,0x90, + 0xd6,0xa1,0xb1,0xbc,0x5d,0xd,0xe6,0x9b,0xc2,0x1e,0xa6,0x19,0xf4,0xf7,0x1e,0x26, + 0x53,0xc3,0x92,0x61,0x68,0x2f,0x71,0xd9,0x6e,0x9a,0x85,0x2d,0x2c,0xe9,0xc9,0x27, + 0x33,0xce,0x10,0x5d,0x68,0x1,0xef,0x32,0x14,0x83,0x89,0x45,0x17,0xaf,0x44,0x14, + 0xfa,0xdd,0x4b,0xcd,0xab,0x19,0x6b,0xc6,0x9c,0x51,0x8d,0xd7,0x3b,0xf4,0x70,0x74, + 0x81,0x16,0x5,0x8b,0x91,0x6b,0x16,0x4b,0x28,0x59,0xf,0xdd,0x47,0x97,0x22,0x41, + 0x9c,0x22,0x58,0x45,0x12,0xf9,0xc9,0x8e,0x10,0xa4,0xd9,0x6a,0xd8,0x13,0xad,0x68, + 0x55,0x87,0x3d,0x17,0x25,0x10,0xb9,0xb9,0xde,0x5e,0x73,0x8f,0xc3,0xb5,0x2c,0x39, + 0x41,0x14,0x9,0x3e,0xcd,0x4c,0x8f,0xbb,0xd2,0x47,0xef,0xc8,0x4d,0xe8,0xc4,0xe5, + 0xd1,0x8c,0x10,0xac,0x39,0x6,0xbb,0x15,0x27,0xda,0x0,0x34,0x29,0x73,0xd2,0x9f, + 0x42,0x6a,0x69,0xa9,0xbe,0xe0,0xa4,0x19,0xc5,0xb5,0x6d,0x1a,0x6c,0x96,0xdc,0xf8, + 0x26,0xa2,0x8e,0xd1,0xfe,0x94,0x99,0x3,0x69,0xbe,0x6,0x97,0xc5,0x2a,0xf8,0x1e, + 0x9b,0x63,0xe0,0x47,0xc7,0x56,0xd0,0xab,0x16,0xa9,0x74,0x3b,0x20,0x59,0x31,0x42, + 0xb0,0xb1,0x6d,0x4a,0xe9,0xe6,0x61,0x84,0xa0,0x54,0xb3,0xb8,0xc5,0x59,0xe6,0xcd, + 0x39,0x86,0xae,0xa4,0xe0,0x2d,0x7d,0x15,0x6a,0x4a,0x16,0x78,0x19,0x91,0x10,0x26, + 0x60,0x54,0x64,0xe6,0x35,0xd3,0xa3,0x9f,0x82,0xf,0x4a,0x4,0x7c,0xe2,0xfd,0xb3, + 0x8a,0x52,0xa7,0xc0,0x2d,0x4a,0x2d,0x51,0x7d,0xfb,0x47,0xb0,0x80,0x8b,0x1,0x11, + 0xd4,0x28,0x3,0x81,0xd3,0x5b,0x3f,0x8b,0x89,0x5a,0x71,0x44,0xc6,0x5c,0x9f,0x16, + 0x8,0xd2,0x98,0x58,0x54,0xf3,0x1d,0x5e,0xc2,0x54,0x14,0xe0,0x68,0x83,0x76,0xd8, + 0x80,0xda,0x44,0xcf,0x7a,0x6d,0x3a,0x47,0xc6,0x9c,0x15,0x24,0xae,0x29,0xd9,0x67, + 0x2,0xab,0xdd,0x20,0x3,0x5,0x4d,0x7,0xd4,0xd0,0x50,0x56,0x9e,0x2a,0x98,0x82, + 0xa1,0x40,0x8b,0xf,0xfe,0x21,0x59,0x52,0xec,0xb4,0x88,0xbe,0xbb,0x6,0x2d,0x6a, + 0xe2,0x1d,0x2a,0xb1,0x55,0x52,0xe3,0x77,0x1a,0x2d,0xcf,0x22,0x37,0xc4,0xf3,0x7d, + 0x9c,0xe8,0xd1,0xf8,0x9e,0x3b,0xc7,0x3d,0xb,0xbc,0x82,0xf6,0x61,0x17,0xab,0xb8, + 0x7,0x96,0x14,0x9c,0xfa,0xee,0x24,0x5d,0xf2,0xb3,0xc7,0x67,0xd4,0x40,0xcf,0x46, + 0x25,0xc5,0x30,0x19,0x96,0x71,0x40,0x94,0x82,0x65,0x2a,0x39,0xf3,0xad,0x72,0xc6, + 0xa4,0xe4,0xbf,0x7,0xa8,0x30,0xe2,0xe9,0x85,0x41,0x4e,0xdc,0xc,0x88,0x90,0xf9, + 0x78,0xa7,0x54,0xd7,0x7b,0x99,0xa,0x68,0x9a,0x28,0x9b,0x2f,0xae,0x96,0x2,0x6e, + 0x5d,0x21,0x32,0x32,0xc9,0x6d,0x7c,0x5e,0xd9,0xcd,0xb,0x67,0x20,0xcc,0xac,0x22, + 0xd8,0x8d,0x9e,0xab,0xfa,0xf1,0xf0,0x68,0x75,0x97,0x1d,0xfb,0x5f,0xd5,0xb7,0xc5, + 0x64,0x34,0xd5,0xaa,0x21,0x19,0xdb,0xde,0x34,0x91,0x14,0x7d,0x1b,0x89,0x6a,0x66, + 0x76,0x27,0xfb,0x2b,0x12,0x20,0x12,0x3f,0x25,0xf2,0x1c,0x53,0xda,0x52,0xe7,0x46, + 0xf8,0x72,0x0,0x29,0x2d,0x4b,0xad,0xcc,0x95,0x88,0x7d,0xa,0x73,0xbf,0x6b,0xe1, + 0x9,0x24,0x24,0xf3,0x2d,0x93,0x50,0x5f,0x77,0x45,0x61,0x23,0xac,0x0,0x5e,0xa5, + 0x47,0x57,0x61,0x90,0x26,0x36,0x8,0xf4,0x8d,0x50,0x10,0x34,0x92,0x19,0xf3,0x83, + 0xc6,0x7a,0xa2,0x10,0xda,0x4f,0xa5,0xc7,0x1b,0xeb,0x91,0x68,0x5c,0x1e,0xac,0x46, + 0x8d,0x78,0x66,0xf7,0x97,0xf0,0x21,0xb5,0xc,0xfb,0xac,0x79,0x27,0xc0,0xf4,0x70, + 0xdd,0x72,0x40,0xa7,0x33,0x75,0xdb,0xb1,0x13,0xc7,0xb1,0x14,0xfc,0x2a,0xa1,0x29, + 0x98,0x13,0x58,0x87,0x96,0x34,0xb0,0x2a,0x56,0x20,0x91,0x6,0x19,0x77,0x27,0x27, + 0x2b,0x92,0xa5,0x83,0x93,0x6f,0x90,0xd2,0xc2,0x77,0xa4,0x4c,0xf8,0x53,0x31,0x39, + 0x7d,0x59,0x70,0x95,0xd4,0xca,0xc0,0x53,0x1,0xdc,0xa,0x29,0x27,0x90,0x80,0xa1, + 0x8c,0xaa,0x8c,0x75,0x62,0xae,0x3c,0x53,0xb1,0xd0,0xce,0xe8,0xa0,0x23,0xfe,0xd6, + 0x10,0x1,0xcf,0xff,0x22,0xb,0xa7,0x97,0x32,0x35,0x89,0x93,0x14,0x22,0xe,0x4f, + 0x56,0xb3,0xd4,0x7d,0x92,0x50,0xe,0x5a,0xa7,0x97,0xfe,0xbd,0xd,0x75,0x5a,0x21, + 0x38,0xf7,0xa8,0x99,0x6f,0x7b,0xd5,0x25,0xf,0x3d,0x3e,0x33,0x1f,0x26,0x4c,0x7f, + 0x62,0x1e,0x75,0xb9,0x4d,0xdd,0x86,0xd7,0xea,0xc2,0xbb,0x8,0xcb,0xc,0x60,0x3c, + 0xce,0x8c,0xb2,0xd0,0xdb,0xec,0x7f,0x8e,0x76,0xd0,0x96,0xb2,0x58,0xf5,0x3d,0x9a, + 0x9a,0x39,0xf,0x36,0x9f,0x7,0xa,0xb4,0x68,0x75,0x6d,0x5,0x1d,0x3c,0x6a,0x1, + 0x76,0x6f,0x85,0xf,0xaa,0x84,0x2e,0x3e,0xc6,0xb5,0x8c,0x2b,0xbd,0x16,0xea,0xa4, + 0x5c,0x20,0x84,0x3c,0x75,0x91,0xa4,0xc3,0x8d,0xd8,0x9,0x31,0x1d,0x83,0x48,0xdf, + 0x5,0x43,0xfe,0x89,0x6,0x9,0x3e,0xb7,0x0,0xe9,0x58,0x1b,0x39,0xb8,0xdd,0x1, + 0xee,0x83,0x43,0x28,0xfb,0x89,0xc5,0x3a,0x3d,0x73,0x7d,0x2,0xd1,0xe8,0x68,0x66, + 0x0,0x11,0x7e,0x92,0x64,0xc,0xe2,0x45,0x56,0x7f,0x5e,0x10,0x64,0x5,0xf9,0x4f, + 0x24,0x1d,0x39,0xb2,0xa3,0xcc,0x87,0x6f,0x86,0xeb,0x2a,0xcc,0x71,0xce,0x38,0x50, + 0xcd,0x81,0x87,0x4,0x6b,0x5d,0x4b,0x5c,0xef,0x38,0xa,0xbc,0x2a,0x64,0x92,0xf, + 0x4,0x45,0x94,0xd4,0x34,0x98,0xdb,0x45,0x49,0xce,0x1c,0xfc,0x59,0x6d,0x7e,0xfb, + 0xf4,0xdb,0x8c,0x94,0xf6,0xd0,0x3,0xa0,0x56,0xc2,0xea,0xb,0xcd,0xe6,0x11,0x34, + 0xe0,0x32,0x9,0x6d,0x6b,0x56,0xd9,0x48,0x35,0x96,0x33,0x8,0xff,0x90,0xdd,0xbd, + 0xef,0x9e,0x89,0xd3,0xd6,0x82,0x9,0x8e,0x56,0xac,0x64,0x33,0xd3,0x79,0xd2,0xc1, + 0xe5,0xda,0x82,0xa9,0x42,0x9f,0x87,0x27,0xbb,0xc5,0xa7,0xbe,0xdb,0x48,0x59,0x3f, + 0xf7,0x24,0xca,0x6e,0x4f,0x22,0xa4,0x9d,0xc9,0x95,0x62,0x30,0x9,0x7b,0x5b,0xf5, + 0xd9,0x69,0xed,0x77,0x99,0x46,0x19,0x38,0x5f,0x66,0xc0,0x4d,0xf0,0x60,0x98,0xdf, + 0x6b,0xcd,0xb9,0x1c,0x5a,0xe2,0xd,0xf8,0xe,0xc,0x65,0xe5,0xdb,0x49,0x24,0x65, + 0x96,0xeb,0xe2,0x21,0x44,0xe3,0x80,0xf1,0x9c,0xf2,0xc1,0xe9,0xe2,0x9f,0x3f,0x35, + 0x83,0x51,0xa7,0xa0,0x4e,0x6d,0xe4,0xd8,0xa7,0xff,0x77,0xe2,0x1,0x35,0x78,0x57, + 0xfb,0xeb,0x2c,0xb5,0x4c,0x9a,0xc5,0xc,0x95,0x10,0xca,0x4b,0x84,0x22,0xbc,0x99, + 0x5b,0xa7,0xf2,0xa6,0xd6,0x6e,0xbe,0xc2,0x5a,0x7e,0x2c,0xea,0x6b,0xbb,0x83,0x2d, + 0x31,0x53,0xb5,0xc6,0xf5,0xaf,0x7,0xd,0x89,0x9c,0x2c,0x51,0x4e,0xd3,0xc8,0x39, + 0x92,0x94,0xa4,0x94,0x6f,0x6c,0x19,0xa0,0xae,0x74,0xe,0x4c,0x62,0x54,0x26,0xad, + 0xf4,0xf9,0x6c,0x8d,0x64,0x19,0x7b,0x6d,0x6e,0x35,0x97,0xb0,0xb9,0x16,0x1e,0x65, + 0x5f,0x43,0x32,0xd,0x72,0x70,0x89,0x54,0x24,0x16,0x61,0xec,0x52,0xd0,0x56,0x6d, + 0x27,0x60,0x2c,0xcb,0x84,0xb4,0x56,0xc1,0x2,0xe,0x1f,0xf5,0xa5,0x10,0x44,0xe9, + 0x46,0x4,0x22,0xff,0xfe,0xa0,0x20,0x23,0x36,0x48,0x6a,0x3,0xef,0x1b,0x5c,0x33, + 0xc6,0xe8,0xc4,0x96,0x9b,0x45,0xc2,0x21,0xf,0x59,0x5f,0x6f,0xb6,0xe7,0x2,0x6d, + 0x1,0xe7,0x34,0x57,0xef,0xf,0x9e,0xe6,0x2e,0x93,0xa6,0xa,0x63,0x64,0xa7,0xb1, + 0xde,0xfc,0x43,0xf3,0x9e,0xe7,0xfd,0xc,0x2c,0xeb,0xdf,0xd7,0xa3,0xe8,0x9e,0xfd, + 0x8d,0x1,0x51,0x21,0xea,0x31,0x57,0x7a,0x0,0x70,0x4,0x16,0x8d,0xf7,0x68,0x10, + 0x67,0x7c,0x23,0x41,0x69,0xcc,0x4,0xd5,0x67,0x73,0x7f,0x4,0x91,0xf4,0xf5,0xcc, + 0x74,0xb7,0xe7,0x9b,0xf6,0x10,0x8a,0x25,0x7,0x70,0x61,0x4f,0x81,0xb6,0x9a,0xd8, + 0xe0,0xe1,0x5,0x7f,0x12,0xfc,0xc4,0x4f,0x3a,0xed,0x4b,0xbf,0x94,0x51,0xe4,0x81, + 0x48,0xa,0x63,0x5c,0x6d,0x48,0x8a,0x44,0xcd,0xbc,0x45,0xe4,0xb3,0xce,0xb2,0x59, + 0x77,0xd2,0x24,0xf1,0xf6,0x3a,0xb1,0xa3,0x8b,0x44,0x90,0x38,0xa6,0x41,0x6e,0xd6, + 0x52,0x4b,0x5f,0x7b,0xa6,0x2d,0xda,0xf6,0xd4,0x8c,0xa8,0xe6,0xcd,0xa0,0xed,0xef, + 0xf5,0xe2,0x2f,0x96,0xc8,0x2f,0x32,0xb1,0x72,0x1e,0x3,0x3e,0xcc,0xfa,0x62,0x34, + 0x4e,0x53,0x4c,0x37,0xef,0x7b,0x9b,0x1c,0xea,0x1b,0xa7,0x4a,0xe5,0x9,0x2,0x9c, + 0x3e,0x61,0xd3,0x7c,0xd1,0x87,0x17,0xa9,0xe9,0x86,0xa3,0x46,0xc9,0xf6,0x43,0x4c, + 0x5a,0xba,0xf6,0x9d,0xd8,0x4a,0xa6,0xd5,0xe3,0x81,0x11,0x26,0x84,0x43,0x51,0xa0, + 0xf0,0xeb,0x99,0xaa,0xd1,0x43,0x91,0xad,0x4,0xce,0xa1,0xc8,0x35,0x7a,0xe5,0x25, + 0xd,0x2a,0xdc,0x1e,0x21,0xe9,0x1a,0x5e,0x54,0xb5,0xd,0xaa,0x2d,0xd4,0x24,0xb6, + 0x93,0xc5,0xfd,0xd,0xf8,0x5,0x3c,0xd4,0x51,0xf2,0xb1,0x11,0xf2,0x8b,0xc5,0x6f, + 0x71,0xfd,0xa7,0x70,0xa9,0xa9,0xec,0xe2,0x18,0xf2,0x2c,0x4b,0x99,0xc4,0x5c,0xf1, + 0x8a,0x65,0x34,0xda,0x17,0xde,0x22,0x58,0xcb,0xa6,0x92,0x15,0x20,0x89,0x64,0x6a, + 0x8,0x3,0x6,0xba,0x70,0xd1,0x6,0x2d,0x55,0x14,0xa7,0x62,0x71,0x64,0x0,0xbd, + 0xc0,0x57,0x1,0xbc,0x9b,0x31,0xde,0x6d,0xca,0x4e,0xb5,0xb3,0x22,0x20,0x50,0xb5, + 0xc0,0xac,0xf,0xc5,0xc3,0xb6,0x29,0x4f,0x6c,0x25,0xed,0x67,0xd9,0x6a,0x69,0x3e, + 0xf,0xaa,0xe2,0x56,0x88,0xef,0xc3,0xc9,0xe5,0x4a,0xa3,0x3a,0xe1,0x90,0xec,0xb, + 0x51,0xf2,0xd5,0xf7,0x50,0x1e,0xa1,0x97,0xbe,0xf5,0x72,0x47,0x54,0x28,0x2c,0x77, + 0x83,0x34,0x50,0x23,0x2,0x6b,0x16,0x85,0xc3,0xc,0x9e,0xbf,0xa8,0x10,0x2f,0x22, + 0x20,0xac,0x4a,0x26,0xbd,0xcd,0xf,0xee,0x94,0x24,0x35,0x9a,0x5a,0xdf,0x84,0xc1, + 0x33,0xe1,0x66,0x8d,0x9a,0x49,0xeb,0xc4,0x14,0x9,0x2f,0x15,0x13,0x14,0x11,0x11, + 0x5d,0xb4,0x7d,0xd7,0x4c,0x3d,0x1a,0xe2,0x12,0x1a,0xd1,0xa8,0xc4,0x1d,0x1d,0x9a, + 0xd9,0xdf,0x8a,0x5a,0xf0,0xc1,0x4c,0xc0,0x45,0x9d,0xe9,0xe2,0x63,0x2e,0xcd,0x38, + 0xe1,0x42,0x5,0x3a,0x62,0xd,0x91,0xd6,0xe9,0x53,0x8b,0x5a,0xa6,0x8b,0x51,0x70, + 0x93,0xd5,0x86,0x2b,0x75,0x2e,0xf5,0x19,0xd,0x10,0x3a,0x54,0xab,0x69,0xe8,0xbc, + 0x3,0x85,0x5c,0x76,0x60,0x0,0x24,0x3e,0x71,0x95,0x3a,0x40,0x66,0x19,0x55,0x8, + 0xdc,0x8,0x30,0xda,0x68,0xb2,0x31,0xc3,0xf7,0xc4,0xac,0x23,0x47,0xf0,0x13,0xcb, + 0xdc,0xbd,0xaf,0xa1,0xba,0xe4,0xc2,0x8,0x1b,0xc8,0x40,0x53,0xae,0xb3,0x3a,0xa9, + 0xbc,0x44,0xd7,0xb7,0x83,0xe3,0xe6,0x7d,0x58,0xf6,0x27,0xe7,0x55,0x54,0xc7,0xb5, + 0x47,0x75,0x28,0x92,0xb4,0xfd,0xf4,0x9d,0xde,0x33,0xb6,0x7f,0x99,0xd0,0x6,0x64, + 0x96,0xcc,0xcc,0x33,0x51,0xa7,0xaf,0x51,0xd,0x6a,0x7f,0xf9,0xb0,0x31,0xb7,0x1e, + 0x6a,0xe1,0xbe,0x0,0xe1,0x2c,0xbb,0x65,0xd3,0x1e,0x77,0x89,0xb5,0xe2,0x88,0x9c, + 0x65,0x61,0x1d,0x95,0x3e,0x68,0x36,0x3b,0x27,0xaa,0xe3,0x2b,0x30,0xf4,0x53,0x89, + 0x68,0x88,0xaa,0x81,0x93,0x18,0x43,0x4b,0xe2,0xea,0xb,0x74,0xe1,0x90,0xf8,0x70, + 0xb3,0x20,0x16,0x38,0x6b,0xe8,0xb6,0xf0,0xfd,0xee,0x13,0xab,0xc3,0xf3,0xab,0x2e, + 0x6b,0x4d,0xb7,0x9b,0xd4,0xf2,0x7f,0x89,0xe4,0x87,0xc8,0x8f,0x74,0x73,0xbd,0xd9, + 0x5b,0xcd,0x50,0xa4,0xb1,0x3b,0x2b,0x8c,0xf1,0x1d,0x78,0x50,0xa4,0x80,0xea,0x89, + 0xa0,0xf4,0xb5,0xf,0x8,0x2c,0x98,0xdf,0x78,0xbe,0x86,0x92,0x0,0x54,0x0,0xad, + 0xd3,0x4a,0xca,0x93,0xaa,0x1c,0xa2,0x4e,0xb8,0xcc,0x48,0x62,0x5,0x6d,0x27,0xb0, + 0xc6,0x75,0xd1,0xa3,0x4f,0xcf,0x58,0xdf,0x96,0x9a,0xb,0x95,0x29,0x64,0x3e,0xfd, + 0x7f,0xbe,0xbd,0x6a,0xed,0x7f,0xde,0x73,0xf2,0xbd,0x7f,0xf5,0xa1,0x2d,0xb5,0xc7, + 0xf6,0x6b,0xef,0x7b,0xef,0x79,0xdb,0x2f,0xff,0x9d,0x5d,0xbf,0x78,0xc5,0x2b,0xf7, + 0xe1,0x6f,0x4f,0x9e,0xb9,0x7f,0xd9,0xfa,0xaf,0xfc,0xdb,0xa9,0x8b,0xf7,0xec,0x59, + 0x78,0xf8,0x84,0x13,0xe7,0x7e,0x76,0xcd,0x5b,0x1f,0xdb,0xb7,0x7e,0xc3,0xe1,0x85, + 0x7b,0x9f,0x3d,0x6e,0xd3,0x27,0x3f,0x7e,0xe6,0xf4,0x13,0x8f,0x2f,0x39,0x78,0xfa, + 0x4b,0xe,0x3d,0xf0,0xf6,0x1b,0x1f,0x9d,0x5b,0xb9,0xf2,0x5,0x33,0x11,0x3d,0x76, + 0x4c,0x2f,0xbb,0xf5,0xc3,0xeb,0x56,0x3e,0xb2,0x6d,0xfa,0x9e,0x4f,0xdc,0xbe,0x59, + 0x4d,0x44,0x8e,0xd,0xf5,0xb2,0x5b,0x3f,0x34,0xfe,0xd9,0x1d,0x9b,0x25,0xe8,0x40, + 0x47,0x80,0xf9,0x35,0xd7,0xbf,0x75,0x53,0xf3,0xfd,0x2f,0x2c,0x5a,0x74,0xec,0x99, + 0x8b,0x2f,0xdd,0xfb,0xe0,0x95,0xd7,0x3e,0x69,0xc7,0x2d,0xb4,0xd7,0x5c,0xff,0x96, + 0x4d,0x22,0x22,0xdf,0xba,0xed,0x8e,0xcd,0xb1,0x5e,0x68,0x72,0xe2,0x4f,0x7f,0xbc, + 0xf4,0xdc,0x2f,0xfe,0xeb,0xe9,0x8b,0xf7,0xec,0x5e,0x78,0x64,0xd5,0x9,0x73,0x5b, + 0xfe,0xe0,0xaa,0x27,0xf6,0x5c,0x78,0xf1,0xec,0x6b,0xdd,0x7b,0xcc,0x44,0x9a,0x7f, + 0xdf,0x73,0xdb,0x1d,0x9b,0x5f,0xf5,0xde,0x77,0x9f,0xbf,0x68,0xff,0xfe,0x5,0xf7, + 0xbe,0xef,0x96,0x87,0xe,0xad,0x39,0x6d,0x6e,0xe9,0x13,0x8f,0x2f,0xfc,0xd5,0xf, + 0xbc,0x6f,0xe3,0x91,0xe5,0xcb,0x9f,0xff,0xdf,0xf,0xdd,0xfa,0xe0,0x6b,0xdf,0xf1, + 0xe6,0xf6,0xb5,0xa2,0x22,0xaf,0x7d,0x47,0xf3,0x59,0x77,0x6e,0x36,0x17,0xd,0x86, + 0x16,0x13,0x91,0x7e,0x22,0x46,0xf5,0x78,0xd4,0x14,0x38,0xa9,0xe8,0xe4,0x2,0x8f, + 0x11,0xc2,0x1f,0xe1,0xb,0x5a,0xb5,0x6e,0x27,0xa9,0xec,0x21,0xa1,0x5d,0xa7,0xb, + 0x3c,0xbc,0x4b,0x54,0x50,0x49,0x72,0xc4,0x26,0xe1,0x8,0x2d,0x25,0x9,0x5a,0x95, + 0x17,0xd1,0x33,0x52,0x24,0xf3,0x8a,0x7c,0x8,0x52,0x74,0xa5,0x6d,0x3f,0x95,0xe8, + 0x1f,0xe1,0x2b,0x21,0x70,0xa0,0xca,0x4,0x11,0x25,0x66,0x39,0x9,0x35,0x7c,0x84, + 0xff,0x8,0x41,0x90,0x1,0x64,0x4c,0x11,0xab,0x16,0x3c,0x45,0xd5,0x44,0x6c,0x98, + 0xd3,0x2a,0x60,0x92,0x2a,0x7c,0x3d,0x50,0x5f,0xd2,0xa7,0xa9,0x1d,0x42,0x84,0x93, + 0xa3,0x34,0xb,0x46,0x35,0x19,0xc2,0xa3,0x10,0x1,0x57,0x39,0xe9,0x2d,0x3b,0x19, + 0xd5,0xa6,0x3,0x2e,0x88,0xe4,0x8a,0x8a,0xa5,0xac,0xd9,0x93,0xf7,0xb2,0x12,0x68, + 0x4,0x7b,0x48,0xf9,0xd0,0xb3,0xd8,0x6b,0x81,0xbb,0xf,0xc4,0xb4,0x27,0xe7,0xf6, + 0xe2,0x47,0x82,0x87,0xf,0xc5,0x52,0xfb,0x83,0x84,0xea,0x4b,0x98,0x11,0x18,0xa9, + 0x57,0x18,0x2b,0x2f,0xb2,0x91,0x27,0xfb,0x15,0xee,0x65,0xe2,0x50,0x68,0x53,0xb2, + 0xa7,0x74,0xc8,0x86,0xe7,0xa6,0x98,0x5a,0xb5,0x70,0x19,0x4b,0xb8,0xee,0x27,0x6e, + 0x1f,0x8f,0xc9,0x7d,0xec,0x82,0x42,0x87,0x47,0xc,0xf9,0xbc,0x74,0x36,0x4b,0x5, + 0xca,0x70,0x50,0x44,0x6,0x45,0xac,0x94,0x51,0xb,0x58,0xf3,0xf7,0x41,0x19,0xb5, + 0x6f,0x94,0x22,0x36,0x50,0x91,0x81,0x8e,0x7e,0x36,0x28,0xdd,0x6b,0x4a,0x91,0x5, + 0xb3,0x7,0xa6,0xce,0xf9,0xf2,0x17,0x4f,0xdb,0x7d,0xd1,0xa6,0x7d,0x56,0x46,0x6d, + 0x40,0x56,0x54,0xac,0x94,0xf0,0xf7,0x3d,0x17,0x5d,0xbc,0x7f,0xc3,0x97,0x3e,0x7f, + 0x5a,0x39,0x3a,0x57,0x9a,0x9f,0x59,0x19,0x7d,0xe6,0xd9,0x5f,0xbd,0x7b,0xcd,0xe2, + 0x67,0xf7,0x2c,0xfc,0xe1,0xbb,0x6e,0xda,0x76,0xfc,0xee,0xa7,0x17,0x5d,0x70,0xd7, + 0xed,0x6b,0x45,0x55,0x36,0x7c,0xe9,0xb,0xa7,0x2c,0xdf,0xf9,0xe8,0xf1,0x5b,0xde, + 0x78,0xf5,0xce,0xe5,0x3b,0x1f,0x5d,0x7a,0xce,0xdd,0x5f,0x58,0x63,0x45,0x65,0xc5, + 0x8e,0x6d,0x4b,0x5e,0xfe,0x91,0xf,0x9c,0xbd,0xf2,0x91,0x6d,0xd3,0x22,0x22,0x52, + 0x8a,0x2c,0xdf,0xb1,0x6d,0xc9,0xcb,0x3f,0x72,0x4b,0xfb,0x33,0x6b,0xbe,0xdb,0x5d, + 0xaf,0x14,0x95,0xe1,0xf8,0x7b,0x9b,0x3f,0xf7,0x7c,0xe2,0xf6,0xcd,0x8f,0xfe,0xd6, + 0xeb,0x77,0x9d,0xfa,0xfd,0xef,0x9e,0xb8,0xe1,0xdf,0x3f,0xbf,0xc6,0x6,0xae,0x37, + 0x78,0xfc,0x19,0x32,0x18,0x8d,0x83,0x94,0x22,0x67,0xdd,0xf3,0xb5,0xd5,0xb,0xf7, + 0xed,0x5b,0x70,0xff,0xbb,0xff,0x64,0xdb,0x92,0x3d,0xbb,0x17,0x5d,0xf8,0x99,0x4f, + 0xad,0xf5,0xef,0x69,0x5f,0xdf,0xfc,0x29,0x2a,0xfb,0xd7,0xad,0x9f,0x15,0x11,0x59, + 0xb5,0xe5,0xc1,0xe3,0xad,0xa8,0x9c,0xb0,0xe5,0xc1,0xa5,0x22,0x22,0xfb,0xcf,0x3a, + 0x7b,0x36,0xc8,0x59,0x36,0xd7,0xe9,0x3e,0xab,0xb9,0x7,0x19,0x14,0x19,0xe,0x46, + 0xcf,0xc2,0xda,0xeb,0xea,0x9e,0x99,0x94,0xee,0x79,0x49,0x73,0x8f,0xe1,0x59,0x8d, + 0x9f,0xc9,0xc0,0x3f,0xa3,0xd1,0x6b,0x64,0x50,0x46,0xb,0xb6,0xf9,0xec,0x81,0x8e, + 0x84,0x7f,0x54,0xbb,0xef,0x1b,0x8c,0xfe,0x93,0x12,0x3f,0xb3,0x7d,0x4f,0xf3,0x6f, + 0x77,0xd,0x52,0x54,0x64,0x20,0xed,0xcf,0x6d,0x50,0x64,0xe8,0xae,0xaf,0x99,0x43, + 0xd6,0x5e,0xd3,0xe8,0x77,0xc3,0x32,0xba,0xd7,0xf6,0x3a,0x7,0xdd,0x3d,0x5a,0x51, + 0x19,0xba,0x31,0xb6,0xf,0xc6,0x83,0x0,0x0,0x18,0xc,0x49,0x44,0x41,0x54,0x18, + 0xba,0xcf,0x6e,0xef,0xbb,0xfd,0xfc,0xf1,0xef,0x7,0xa5,0xbd,0x76,0x69,0xee,0x79, + 0xfc,0xdd,0xdd,0x3d,0x97,0xf6,0x1a,0x6c,0x3c,0x1e,0x71,0xbc,0xa4,0x1d,0xb,0xf1, + 0xd7,0x5e,0xca,0xf8,0x1e,0xdd,0x9a,0x19,0xf8,0xdf,0xc7,0xf1,0xb1,0xe6,0x77,0xea, + 0xde,0x5f,0xc6,0xc2,0x18,0xed,0xd8,0xfb,0x71,0x75,0xf3,0xb8,0xc4,0x67,0xe7,0x3f, + 0x5f,0xda,0x71,0x68,0xfe,0x73,0x9f,0xdd,0x7e,0x9f,0xc6,0xb9,0x50,0x4a,0x37,0x36, + 0xea,0xef,0xbd,0x19,0x1f,0x69,0xaf,0x73,0xe8,0xee,0x37,0xdc,0xdb,0x54,0x37,0x86, + 0xc3,0x41,0x33,0xb6,0x6e,0x8c,0x6,0xf1,0x5e,0x46,0xfb,0x4d,0xf3,0x7d,0xdd,0xfd, + 0x34,0xe3,0xdc,0x5d,0xaf,0xbb,0x1f,0x37,0xf,0xa5,0x1d,0x7,0x89,0x73,0xa8,0x19, + 0xa3,0x29,0x98,0x8b,0x3,0x95,0xe1,0x40,0xe2,0xf5,0xe0,0x3a,0x18,0x74,0xe3,0x6b, + 0x5a,0xda,0xef,0xe8,0x9e,0x17,0x8c,0x2d,0x19,0xff,0x6e,0x7e,0xd,0xdc,0xf3,0x1a, + 0x8f,0x8d,0xfa,0xfd,0x33,0xee,0x91,0xa3,0xb1,0x76,0xcf,0xa8,0x5d,0xd3,0xd2,0xce, + 0x55,0x2b,0xdd,0x7c,0x35,0x37,0x77,0xdb,0xfd,0xa9,0x14,0xb7,0x76,0xb4,0x7d,0x86, + 0xcd,0xd8,0xfb,0xfb,0xc,0x7b,0xc2,0xa0,0x74,0xfb,0xe1,0x78,0xad,0xc,0x4b,0xf7, + 0xb3,0x6e,0xff,0x1c,0xe4,0xbd,0x68,0x7c,0xcd,0xc3,0xf1,0x98,0xe,0x9b,0x79,0x3f, + 0xe8,0xce,0xc,0x1c,0x1f,0x1b,0x94,0x6e,0x9e,0xb5,0xcf,0xb8,0x9b,0x83,0xed,0x1c, + 0x1d,0x94,0xb0,0x86,0xbb,0xfd,0xad,0x8c,0xf7,0x2b,0x4d,0x6b,0x4b,0xdc,0x5a,0x16, + 0xf6,0xdc,0xe8,0x5e,0x36,0x70,0x6b,0x39,0xce,0x25,0x29,0x7e,0x6f,0x95,0x6e,0xfe, + 0xf,0xdc,0x1a,0x1e,0xc0,0x1e,0x52,0xe2,0x75,0x8b,0xdb,0x7b,0xba,0x71,0x72,0xcf, + 0xb0,0xd9,0x73,0x6,0x65,0xb4,0xa7,0xd,0xe2,0x3a,0x6e,0x9e,0x49,0xb8,0xa6,0x76, + 0xf,0xed,0xf6,0xb1,0x76,0xc,0x8b,0x8e,0xed,0x53,0xdb,0x16,0xbb,0x12,0x22,0x22, + 0x6b,0x3,0x17,0x67,0xdd,0x7,0x21,0xd6,0xda,0x6f,0x7e,0xed,0xc4,0xa9,0xb9,0xb9, + 0xc1,0xb3,0xe7,0x5f,0x30,0x2b,0x83,0x22,0xb,0x9f,0x79,0xfa,0xb8,0x8b,0x3f,0x75, + 0xdb,0xda,0xe9,0x9d,0x8f,0x1d,0x7f,0x64,0xe5,0xaa,0xb9,0x9f,0xbe,0xf9,0xba,0x9d, + 0xfb,0x36,0x9c,0xf7,0x7f,0xcf,0x9e,0x77,0xfe,0xec,0x19,0xff,0xf5,0x1f,0xab,0xd7, + 0x7e,0xfb,0x9b,0x27,0x6c,0xff,0xed,0xdf,0xdb,0x6d,0x4e,0x71,0xe8,0xde,0xf7,0x7f, + 0x70,0xab,0x8a,0xc8,0x82,0xfd,0xfb,0xa7,0x44,0x44,0x16,0x3f,0xbb,0x67,0xa1,0xc, + 0x54,0x56,0x6e,0xdb,0x3a,0x2d,0x22,0xb2,0xeb,0x65,0x97,0x1d,0x38,0xff,0xb3,0x9f, + 0x91,0x95,0x3f,0xdf,0x32,0x6d,0xa5,0xc8,0xcb,0xff,0xe6,0x83,0x1b,0x66,0xd7,0x9c, + 0x7a,0xd8,0x1f,0x9a,0xec,0x67,0xea,0xdd,0x6a,0x8a,0xc5,0x9e,0xc4,0xe6,0xd0,0x3c, + 0x6e,0x20,0x4f,0xbe,0xea,0xd7,0xf7,0xae,0xff,0xea,0xdd,0xa7,0x9d,0xfc,0xc0,0xcc, + 0x8a,0x87,0xae,0x7e,0xd3,0x53,0xfe,0x33,0x22,0x4c,0x58,0xe4,0xbe,0x9b,0xff,0xe2, + 0x11,0x11,0x95,0xe5,0x8f,0x3c,0xbc,0x58,0x44,0xe4,0xc8,0xca,0x95,0x47,0x25,0x1c, + 0xe8,0x51,0x68,0xc1,0x4a,0x91,0xe7,0x36,0x9c,0x37,0xbb,0x7a,0xe6,0x87,0xab,0x56, + 0x6d,0xdb,0xba,0xf4,0xb1,0xd7,0xbc,0xfe,0xb9,0x95,0xf,0x6f,0x5d,0x2a,0x22,0xb2, + 0xf7,0xdc,0x8d,0x87,0x4,0x83,0x1,0xff,0xde,0x81,0xa6,0xc,0xcc,0x7,0xad,0x91, + 0x71,0xef,0xda,0xa8,0x24,0x2b,0xd1,0x35,0xc8,0xf3,0x30,0xa1,0xf0,0x36,0x76,0x92, + 0xd2,0x2c,0x93,0x29,0x1c,0xa6,0xaf,0x33,0x58,0x1d,0xf3,0xd9,0xd5,0x2c,0x53,0x8b, + 0x1b,0x8b,0xba,0x8b,0x10,0x62,0x1b,0xf4,0xfe,0x6,0xe2,0x9c,0xbb,0xae,0x40,0xac, + 0xe9,0xfc,0xc6,0xa3,0x75,0xac,0x57,0x31,0x14,0x27,0x82,0xa5,0x89,0x3f,0x3e,0xc, + 0x10,0x9c,0x52,0x7b,0x75,0xf,0x43,0x36,0xa2,0x30,0x41,0x5d,0xac,0x80,0xbc,0x2f, + 0x40,0x67,0x9e,0xd1,0x6b,0x50,0xce,0x30,0xa9,0xb,0xc,0x63,0x3d,0x51,0x82,0xcf, + 0x80,0x5,0x2f,0xeb,0xd8,0xf5,0xe1,0x4d,0x8d,0x34,0xd5,0x15,0x38,0x3,0xc2,0xe9, + 0x2d,0x68,0x6e,0x71,0xc,0xaa,0x63,0x66,0xc1,0x6e,0x35,0xa7,0xfc,0xd1,0xbb,0x5a, + 0xaa,0xbe,0xd4,0xdc,0x1b,0x20,0x64,0xc1,0x8d,0xce,0x3c,0x30,0x7e,0xb1,0xad,0xab, + 0xed,0xfd,0x6d,0xc4,0x3d,0x2a,0x7a,0xe3,0xd8,0xed,0x31,0xc,0xe6,0x24,0xc,0xfe, + 0x57,0xd0,0xf7,0x6a,0xfa,0xd9,0x9b,0x32,0x14,0xe8,0x55,0x84,0x36,0x3d,0xcd,0x90, + 0x6e,0x32,0xea,0xd0,0x2a,0xc1,0x19,0xc9,0x4,0xdc,0xa0,0x4a,0x3a,0x1,0xa9,0xd6, + 0x38,0x86,0x58,0x17,0x27,0xa7,0x47,0xe1,0x66,0x26,0xcd,0xdc,0xf1,0x2d,0x7f,0x28, + 0x62,0xe5,0xe7,0x52,0xf1,0x88,0x82,0x82,0x6e,0x48,0x1e,0xfb,0x50,0x55,0xf7,0xfb, + 0x9b,0x46,0x19,0xd7,0xdc,0x3d,0xc4,0x3b,0xa6,0xda,0xac,0xb7,0x68,0x57,0xda,0x2d, + 0x2a,0x4c,0xa8,0x3c,0xf5,0xfc,0x13,0x35,0x4a,0x1,0x67,0x39,0x51,0x4d,0x55,0xbd, + 0xe0,0xcc,0xa2,0x5d,0x2f,0xb9,0x54,0xc,0xb6,0x2c,0xf1,0xbd,0x70,0x1d,0x58,0x40, + 0x7,0x87,0xce,0xb3,0xc2,0x6b,0x82,0xb4,0xc2,0x3e,0xe3,0x7f,0x4f,0x35,0x87,0x56, + 0xf7,0x35,0x25,0x6c,0xdf,0x46,0xbc,0x88,0x3d,0x2b,0xf7,0xa4,0x9f,0xfd,0x64,0x85, + 0x88,0xc8,0xc1,0x33,0xce,0x98,0x1b,0x16,0x91,0xb,0xff,0xe9,0xf6,0x97,0x2c,0x7f, + 0x74,0xc7,0xd2,0x99,0x77,0xde,0xf8,0xc8,0x25,0xb7,0x7d,0xec,0xec,0xb,0xee,0xba, + 0xe3,0x8c,0xef,0xdc,0xf2,0xe1,0x2d,0x7,0xce,0x38,0xf3,0x88,0x88,0xc8,0x29,0xf7, + 0xff,0x60,0xd5,0x23,0xbf,0xfb,0xfb,0xbb,0x59,0x55,0x63,0xed,0xb7,0xbe,0x7e,0xa2, + 0x88,0xc8,0xbe,0xb3,0xd7,0x1f,0xb4,0x81,0xca,0x82,0x83,0x7,0x8e,0x13,0x11,0x39, + 0xba,0x6c,0xd9,0x31,0x11,0x19,0xfd,0x7b,0xa0,0xf2,0xdc,0xb9,0x1b,0xf,0x3c,0xf0, + 0xb6,0x3f,0xda,0xf9,0xea,0x9b,0x6e,0xb8,0x70,0x94,0x49,0x17,0x79,0xee,0xdc,0x8d, + 0x7,0x36,0xbf,0xed,0xfa,0x9d,0xbf,0x79,0xd3,0x8d,0x17,0xb6,0x87,0xb1,0x17,0x4f, + 0x70,0xac,0xca,0x0,0x11,0x17,0x95,0xb9,0x15,0x2b,0xdd,0xe7,0x97,0x78,0x38,0x7, + 0xcb,0xbc,0xf1,0x81,0xa0,0x26,0x97,0xfd,0xed,0x87,0xd6,0xcf,0x4d,0x2f,0x3b,0xba, + 0xf9,0x9d,0x37,0x3e,0xea,0xf,0xf1,0xd7,0x5d,0x77,0xed,0x26,0x3c,0x94,0xf7,0xbc, + 0xf4,0xa5,0x87,0xe4,0x73,0x22,0x2b,0xb6,0x3f,0xbc,0x54,0x6,0x2a,0xcb,0x77,0x3c, + 0xb2,0x54,0x44,0x64,0xcf,0x5,0x17,0xcc,0x7a,0xe5,0xb6,0xd7,0xfd,0x21,0xbc,0xb7, + 0x94,0x8c,0x39,0x92,0x82,0x4d,0xe7,0x64,0xe7,0x45,0x7,0xcc,0xd9,0x80,0xc2,0x54, + 0x6e,0x64,0x47,0x5b,0xa9,0x43,0x6b,0xbd,0xae,0x87,0x81,0xe,0xa6,0x89,0xab,0xc6, + 0x6a,0xcc,0xed,0xf6,0xef,0x30,0xe3,0xa1,0x5b,0xa6,0x19,0xee,0x84,0x39,0x16,0xd6, + 0x69,0x71,0x86,0x5,0x25,0xef,0x68,0x41,0xfc,0x41,0x5a,0xad,0xa1,0x68,0xd8,0xe2, + 0xea,0x61,0x49,0x7f,0x3c,0x7,0x20,0x28,0xc,0x25,0x81,0x11,0xef,0xf,0x2c,0xe9, + 0x16,0x2a,0xe8,0xc,0x98,0x39,0x86,0x71,0xbb,0x64,0x8a,0xa0,0x5f,0x73,0xf3,0xb1, + 0x5e,0x5c,0xc7,0x9b,0x35,0x18,0x8,0xa2,0x48,0x2a,0xb3,0x38,0x6b,0x58,0xed,0x8c, + 0x2d,0xcc,0xd9,0xe0,0xe,0x35,0xdb,0xff,0x70,0x91,0x25,0x64,0xe5,0x46,0x4b,0xc7, + 0x4e,0xe4,0xa6,0x0,0x74,0xcd,0x3a,0xf4,0xc7,0x9b,0x6b,0x29,0xe,0x16,0x66,0x46, + 0x48,0x4a,0x8,0xac,0x9d,0xcd,0x32,0x92,0x48,0xbd,0x9d,0xb3,0x2b,0xaa,0xc6,0x29, + 0x54,0x26,0x97,0x95,0xbc,0x40,0x93,0x59,0x5c,0x27,0x5e,0xb5,0xab,0x55,0xad,0x2c, + 0x9d,0x86,0x40,0x10,0xa7,0xf1,0x4,0xb3,0x10,0x0,0x4a,0x78,0xce,0x59,0x7f,0x3f, + 0xf7,0x5e,0xc,0xdd,0xe1,0x64,0xa0,0x40,0x29,0xae,0xb7,0x7e,0x8,0x63,0x8d,0x6d, + 0x8a,0x66,0xd1,0x42,0x33,0x1e,0xd1,0x5,0xf8,0x40,0x15,0x61,0xad,0x26,0x28,0x15, + 0xdf,0xa7,0x1f,0x6d,0x7c,0x83,0xac,0x2b,0x69,0x63,0x4b,0xe2,0x43,0x29,0x18,0xf6, + 0x24,0xbe,0xec,0xb4,0xc6,0x70,0xf2,0x61,0xb0,0xb4,0xf6,0x25,0xdf,0x32,0x86,0xbe, + 0x8b,0x13,0x35,0xf2,0x3e,0x24,0xbe,0xad,0x34,0x2a,0x5,0x32,0x3,0x1d,0x6d,0xdd, + 0x30,0x7d,0xb2,0x33,0xe,0xc6,0x4a,0x26,0xd0,0x71,0xc8,0x5b,0xd2,0x3c,0xf7,0x22, + 0x6a,0x5d,0xec,0x59,0xba,0xe7,0x5c,0x72,0xd0,0xd3,0x9a,0x52,0x89,0x42,0xcb,0x20, + 0x58,0x50,0x93,0x31,0x9f,0xb2,0x41,0x71,0x24,0x32,0xe5,0xb6,0x72,0x4a,0xe8,0xf4, + 0xe3,0xbf,0x2f,0xde,0xb3,0x7b,0xa1,0x88,0xc8,0x91,0x15,0x2b,0x5f,0x10,0x2d,0xb2, + 0x7c,0xfb,0xe8,0xb0,0x7a,0xfa,0xd2,0xcb,0xe,0x7e,0xe3,0xf6,0x7f,0xde,0xdc,0x7c, + 0xeb,0xdc,0xaa,0x15,0x2f,0x88,0x88,0x2c,0x79,0x66,0xd7,0xa2,0xe6,0x3b,0xbd,0x26, + 0xf2,0xa9,0xf7,0x7e,0x67,0xc5,0x99,0xdf,0xfa,0xc6,0x29,0x73,0xd3,0xd3,0x47,0x7f, + 0xfa,0x96,0xeb,0x9e,0x68,0x34,0x93,0x31,0x73,0xb5,0xa2,0x72,0xdf,0xcd,0x7f,0xbe, + 0x3d,0xdc,0xc5,0x40,0xe4,0xbe,0xf7,0xfe,0xd9,0xf6,0x78,0x90,0x16,0x3a,0xdc,0xa9, + 0x22,0x58,0x4a,0x88,0x5a,0xbd,0x72,0x9e,0xd,0xc6,0x6a,0x49,0x45,0xa1,0xb8,0xa8, + 0xf2,0x83,0xf7,0xdc,0xfc,0xf0,0x2b,0xfe,0xfa,0xfd,0xe7,0x5e,0xfc,0x8f,0xb7,0x9d, + 0xf1,0xdd,0xbf,0xbc,0xe5,0xe1,0xe6,0x3d,0xdf,0xb8,0xf3,0xae,0xcd,0x26,0x22,0x97, + 0xbf,0xf9,0xea,0x4d,0x4d,0x60,0x31,0x7b,0xfa,0x4b,0xe6,0xe6,0x96,0x2d,0x3b,0xba, + 0x70,0xff,0xfe,0x5,0x27,0x3d,0x30,0x33,0xbd,0xf0,0xc0,0x81,0xe3,0x9e,0x5f,0x3a, + 0x7d,0xf4,0xe0,0x19,0x6b,0xe7,0xfc,0x82,0xf8,0xfa,0x9d,0x77,0x6d,0x56,0x55,0x79, + 0xfd,0x9b,0xae,0xda,0xd4,0xde,0xb7,0x7a,0x8d,0xe7,0x5a,0x76,0xdc,0x6f,0xd7,0x62, + 0xc8,0xa,0xc,0x87,0x9e,0x6f,0x65,0x6a,0xb4,0x3,0x24,0x15,0xee,0xb2,0xd,0x22, + 0x9a,0x17,0xc4,0xcc,0xcb,0xc6,0xe,0x6d,0x48,0x76,0x4a,0x3e,0xf6,0xb0,0x4f,0x8f, + 0x14,0xb3,0x9c,0x87,0x3c,0xa9,0x8b,0x75,0x76,0x84,0x4d,0x12,0x52,0x40,0xeb,0x80, + 0x48,0x0,0xb8,0x3,0x24,0x65,0xfe,0xc5,0x40,0xd6,0xd4,0x19,0x5a,0x8,0x53,0xe3, + 0x63,0x35,0x47,0xe7,0xfa,0x94,0x6a,0x83,0xf1,0x1e,0x3b,0xa5,0x5a,0xd,0xd2,0xab, + 0xde,0xb3,0x3e,0xf2,0x8d,0x72,0x7d,0xd7,0xa8,0x6,0xba,0xb9,0x67,0xd,0xda,0xec, + 0xe1,0xe0,0x80,0x62,0xae,0x45,0x8f,0x70,0x6f,0x33,0xab,0x1a,0x69,0x6a,0x46,0x24, + 0x81,0x5,0xeb,0xa7,0x21,0xc0,0xd1,0x60,0x8b,0xac,0xa0,0xc0,0xd2,0x5,0x5d,0x25, + 0x71,0xbe,0xa3,0x49,0x50,0xa7,0x94,0x85,0x3c,0x89,0x38,0xeb,0x33,0x2d,0x34,0xb4, + 0x67,0xe5,0xd6,0x80,0x36,0xd1,0x9,0x56,0xb3,0xd8,0x85,0x62,0xa0,0xd3,0x4f,0x48, + 0x7b,0x91,0x84,0x59,0xd2,0x57,0x99,0xd7,0x90,0x90,0xee,0xf0,0x54,0xa7,0x1c,0x99, + 0x50,0x86,0x92,0x6d,0x80,0x87,0x81,0x75,0x52,0x12,0x69,0xb0,0x3b,0xc8,0xbd,0x22, + 0x9c,0x39,0x5f,0x0,0xcb,0xc8,0x59,0x8b,0xde,0x8d,0xa5,0x4d,0xc7,0x23,0x6c,0x21, + 0x30,0x67,0xca,0xe3,0x85,0x92,0x95,0x7d,0x3b,0x5c,0xa,0xe4,0x8b,0xcf,0x47,0x40, + 0x96,0xd7,0xa1,0x75,0x59,0xc7,0x42,0x13,0xb9,0xcc,0x20,0x2b,0x36,0x24,0x45,0x57, + 0x8c,0x51,0xd0,0x49,0xb4,0x73,0xbb,0xb3,0x76,0xf,0x8a,0xdb,0x68,0x9,0x4b,0x31, + 0xf7,0x4d,0x6a,0x66,0x5a,0x7,0xa4,0x45,0xa3,0xb4,0x77,0x74,0xfb,0xd,0x7b,0x69, + 0x3c,0xc0,0xdd,0xda,0x7,0xe,0x89,0x85,0x4c,0x64,0xf4,0xff,0xa9,0x70,0x58,0x11, + 0x53,0xb8,0xc8,0xc5,0x89,0x96,0xa4,0xa1,0x3f,0xac,0xa8,0xc8,0x54,0x71,0x6e,0x78, + 0xa6,0xc3,0x32,0xda,0x29,0x55,0x54,0x86,0xc3,0xc1,0x68,0x32,0xe,0xa6,0xac,0x3d, + 0x3c,0xc6,0x5a,0xc8,0xab,0xb6,0x6e,0x59,0x72,0xe1,0x9d,0x9f,0x5e,0x7b,0x68,0xcd, + 0xa9,0x87,0xef,0x7f,0xf7,0x4d,0xdb,0xf,0xaf,0x5e,0x7d,0x54,0x45,0x64,0x6e,0xd9, + 0xb2,0x17,0x16,0xed,0xdf,0x7f,0xdc,0xd4,0x91,0xc3,0x3,0x11,0x91,0xe7,0x97,0x2d, + 0x3b,0xda,0x64,0xcd,0xa1,0x25,0xb2,0xc,0x92,0x7,0x52,0x7,0x57,0x77,0xd6,0x8c, + 0xde,0x2,0xcf,0x7,0x8,0xc7,0x1d,0x38,0x30,0x10,0x11,0x39,0x7c,0xc2,0x9,0x73, + 0xe2,0x21,0xf3,0x22,0xc1,0x1a,0xd1,0xbf,0x77,0xff,0xfa,0xf5,0x47,0x44,0x44,0xa6, + 0x1f,0xdf,0x79,0xbc,0x41,0x10,0x60,0x18,0x58,0x98,0xc8,0xbe,0xb3,0xd7,0xcf,0xae, + 0x9e,0xf9,0xd1,0xca,0xb3,0xbf,0x72,0xf7,0x6a,0x11,0x91,0x7d,0xeb,0xd7,0x1f,0x92, + 0xa2,0xd1,0x3,0x7d,0x0,0x87,0xf6,0xa0,0x54,0x5a,0x5a,0xdc,0x86,0xda,0x9,0x7b, + 0x7,0x26,0x26,0xc4,0xf4,0x9d,0x40,0x2,0x5a,0x2f,0x42,0x94,0xdb,0x46,0xc7,0x1a, + 0xad,0x14,0x19,0x20,0x2b,0xc0,0x88,0xf7,0x86,0x2d,0x2d,0x72,0xe0,0x82,0x73,0x6b, + 0x56,0x32,0x55,0x8b,0x80,0x5e,0x5b,0xb0,0xfc,0x14,0xc8,0x39,0xb3,0xa7,0x71,0x94, + 0xda,0x6d,0xca,0x2c,0x66,0x5e,0xf7,0x7f,0xc,0x85,0x13,0x3,0x1d,0x13,0xa1,0x6, + 0xa,0x7e,0x2f,0x18,0x86,0xc3,0xac,0xb1,0xe,0x75,0xb,0xbe,0xd5,0x68,0xee,0x50, + 0xa0,0x4c,0x3e,0x2,0x93,0x1c,0x78,0x6,0x5c,0x78,0x45,0x5b,0x43,0x9,0x55,0x83, + 0x40,0x0,0x5f,0xd5,0x5e,0x4a,0x80,0x6e,0x23,0xd4,0x8e,0x8c,0x77,0x4d,0xed,0xaa, + 0xa3,0x40,0x36,0xc2,0x92,0x6,0x87,0x97,0x29,0xb4,0x45,0x79,0x2b,0xcc,0x16,0x62, + 0x15,0x57,0x96,0x18,0x1b,0x2,0xb5,0x3e,0xd1,0x25,0x74,0x56,0x19,0x18,0x22,0x79, + 0x5d,0x72,0x7f,0x58,0x19,0xcb,0x77,0xb5,0x93,0x1,0x56,0x29,0xed,0xe7,0x75,0x6e, + 0x54,0x6e,0x4f,0x73,0x70,0xb4,0x56,0x8c,0x79,0xc2,0xd8,0x99,0xc1,0x3a,0xc8,0xbe, + 0x16,0x89,0x3b,0x5c,0xd4,0x25,0xa5,0x71,0x5f,0x35,0x2f,0x77,0x1a,0x32,0x46,0xad, + 0x92,0xc8,0xda,0xb5,0x3,0xa5,0x9d,0x10,0xac,0xa5,0x7d,0xa,0x4c,0xa3,0x4a,0xb7, + 0xb1,0xf9,0x32,0x55,0x68,0xa9,0x54,0x28,0x11,0x0,0xfc,0x9f,0xbc,0xcb,0x53,0x9a, + 0x58,0x72,0x20,0x9,0xfa,0xf9,0x11,0xf9,0xf5,0x87,0x3d,0xb0,0x3,0x4b,0x3e,0x8c, + 0x33,0x89,0x92,0x58,0x1b,0x26,0x95,0x36,0x68,0xbf,0x6d,0xd1,0x36,0xab,0xb0,0xf9, + 0x19,0x84,0x27,0x24,0x43,0x40,0xd5,0x2b,0xab,0x3a,0xaa,0x61,0x7b,0x2b,0x79,0x58, + 0xe2,0x60,0x22,0x87,0xc8,0x56,0x6b,0x5d,0x9e,0x6e,0xdf,0xfe,0x7f,0xaa,0x81,0x8b, + 0x5b,0x71,0xf,0xd2,0xf6,0xc4,0xb2,0x8e,0x66,0xd2,0x1f,0x3a,0xe5,0x94,0xb9,0xe9, + 0x27,0x9f,0x5c,0xbc,0xe0,0xe0,0xc1,0xa9,0x23,0x27,0x9e,0x70,0x74,0xff,0xba,0xb3, + 0x67,0x57,0x6d,0xdd,0xb2,0xec,0xa4,0xcd,0x33,0xd3,0x97,0x7e,0xfc,0xd6,0x75,0xb3, + 0x6b,0xd6,0x1c,0xfe,0xce,0x87,0x3f,0xb2,0x75,0xd1,0xfe,0xbd,0x53,0x22,0x22,0x87, + 0xd6,0x9c,0x72,0xd8,0x1f,0x7a,0x26,0x22,0xe7,0x7c,0xe9,0xb,0x6b,0xf6,0x6e,0x38, + 0xf7,0xe0,0xfd,0x7f,0xfc,0x9e,0x47,0x87,0x8b,0x16,0xf,0x9b,0xe9,0xb0,0x77,0xc3, + 0xb9,0x7,0xd7,0xfc,0xe0,0xbe,0x55,0xab,0x7f,0x78,0xff,0x32,0x11,0x91,0xe7,0xce, + 0xdb,0x78,0xb0,0x35,0x7f,0x29,0xfe,0x50,0x16,0xe7,0x27,0xeb,0x36,0xd2,0xb1,0x3b, + 0x4e,0x9b,0x2c,0xba,0x8c,0xc3,0x1f,0x9a,0xa7,0x7e,0xef,0x7b,0xcb,0x45,0x44,0x9e, + 0x7e,0xd9,0xaf,0xec,0xb,0x46,0x32,0xcd,0xd8,0xb8,0x71,0x7c,0xe5,0x9f,0xde,0x7c, + 0xce,0xf1,0x4f,0x3d,0xb5,0x78,0xf3,0xd,0x37,0xee,0x10,0x11,0x39,0x70,0xe6,0x99, + 0x87,0x2,0x4c,0xaf,0xc0,0x96,0x1c,0x7f,0xde,0x73,0x1b,0x37,0xce,0xae,0x9e,0xf9, + 0xd1,0xca,0x15,0x3b,0xb6,0x2f,0x1d,0xdd,0xcb,0x79,0xb3,0x9e,0x4c,0xd7,0xa1,0x5, + 0x3e,0x18,0x40,0xc7,0x27,0x74,0x85,0xea,0x6a,0x56,0x99,0xfd,0xd8,0x79,0x69,0x77, + 0x41,0xa5,0x77,0x74,0x53,0xa8,0x63,0x91,0x9a,0x1e,0xf4,0x71,0xa6,0x75,0xe3,0x45, + 0x77,0xc6,0x75,0xaa,0x20,0x23,0xd6,0x64,0x68,0xcd,0x6b,0x34,0x1b,0xc8,0x64,0x3e, + 0x72,0x86,0xc3,0x72,0x44,0x9c,0x33,0xae,0xe0,0x97,0x6e,0x46,0xb0,0x74,0x6d,0x8d, + 0x17,0x6c,0x5e,0x6d,0x3b,0xb1,0x77,0xd8,0x7,0x85,0xed,0xba,0xd3,0xe2,0x82,0x15, + 0xaf,0x6f,0x5f,0xba,0x92,0xc3,0x18,0x86,0x36,0x52,0xb7,0xa4,0x35,0x48,0x6c,0xbc, + 0x6e,0x75,0xbc,0x3b,0x38,0xdd,0x73,0x26,0xfc,0xa6,0x67,0xad,0xfd,0xae,0xcb,0x32, + 0xa4,0xb3,0xbd,0x95,0x36,0xa0,0x89,0x95,0xba,0x66,0x6e,0xd,0x61,0xe,0x8,0x18, + 0xc6,0x30,0xbb,0xcb,0xce,0xf0,0xa6,0xa4,0xb6,0x73,0x64,0x9c,0x1b,0xc0,0xfc,0x2, + 0x1e,0xec,0x29,0xa3,0xf1,0xda,0xdb,0x30,0x7c,0x96,0x54,0x99,0xba,0x7f,0xc7,0x16, + 0x53,0x5f,0x3a,0xd0,0xd4,0x76,0x65,0x8c,0xb1,0x2f,0xd9,0x6b,0xbc,0x97,0xa6,0xad, + 0xa0,0x91,0xee,0x4a,0x2d,0xc9,0x9c,0xcb,0x9,0x97,0x5b,0x68,0xf7,0xb2,0x9,0x7d, + 0x9c,0x96,0xcd,0xd6,0x5b,0x61,0x74,0x50,0x77,0x3,0x8e,0x85,0x9b,0xb0,0x92,0x94, + 0xf9,0xa3,0xb8,0x3d,0x33,0x74,0x97,0x3a,0xbc,0x1,0x7,0x68,0x4d,0xd5,0xd4,0x50, + 0xe4,0x42,0xe3,0x41,0x14,0x3a,0x76,0xa0,0xb6,0xc7,0xc9,0xdc,0x20,0x20,0x23,0x42, + 0xac,0x4,0xf3,0x40,0xfa,0xa8,0xcb,0x2a,0x32,0xac,0x86,0xc9,0x86,0x12,0x2,0x13, + 0x6b,0xfb,0x21,0x3d,0x6f,0x66,0x84,0x4,0x41,0x84,0xc0,0x8c,0x28,0x5d,0x19,0xc, + 0x40,0x12,0x5f,0x13,0xf2,0x5e,0x19,0x93,0xe2,0x9a,0x85,0x60,0x95,0x5,0x87,0xa5, + 0x4f,0xf7,0xb1,0xcf,0x5c,0x72,0xe9,0xbe,0xe9,0x27,0x9f,0x5c,0xbc,0x7c,0xc7,0xc3, + 0x8b,0xf,0x9f,0x7c,0xd2,0xd1,0x1f,0x5f,0xf7,0xb6,0x27,0x2e,0xf9,0xd8,0x47,0xd7, + 0x5e,0xf2,0xf7,0x1f,0x3d,0xeb,0xd0,0xc9,0x27,0x1f,0xf9,0xc9,0x75,0x6f,0xdf,0x69, + 0x5a,0x64,0xd5,0xd6,0x2d,0xc7,0x8b,0x88,0xec,0xbe,0x78,0xd3,0x81,0x51,0x96,0xdd, + 0x65,0x4f,0xcb,0x1e,0x7b,0x6c,0xc9,0xd4,0x91,0x23,0x83,0xd7,0x5d,0xf7,0xd6,0x8b, + 0x44,0x44,0x76,0x5c,0xfe,0x86,0x5d,0xf,0x5d,0x73,0xed,0xae,0x87,0xae,0xb9,0xf6, + 0x17,0x8b,0x9f,0x7d,0x76,0xc1,0x5,0x77,0x7e,0xfa,0x8c,0xfd,0x67,0x9d,0x75,0x68, + 0xcb,0x95,0x57,0xed,0x6a,0xf,0xd9,0xa,0xbc,0x1e,0xe,0x47,0xd2,0x4c,0x6c,0x40, + 0xc,0xb9,0xfc,0xea,0x2b,0x36,0x1d,0x5d,0xbc,0xe4,0xd8,0xce,0xdf,0x78,0xf5,0xee, + 0x2d,0x57,0x5e,0xf1,0xb4,0x3f,0xd0,0xdf,0x70,0xf5,0x15,0xa1,0xa6,0xfd,0xb5,0xcf, + 0x7e,0x6e,0xf3,0xd6,0x37,0x5e,0xf1,0x8b,0xf3,0xef,0xbc,0xe3,0xf4,0x4b,0x6f,0xfd, + 0xbb,0x75,0xfb,0xd6,0xad,0x3b,0xb4,0xf9,0xfa,0x1b,0x76,0xfa,0x4c,0x74,0x74,0x2d, + 0x16,0x82,0x2,0x15,0x91,0xdd,0x17,0x5d,0x3c,0xbb,0xf1,0xb3,0xff,0xd2,0xfe,0x7c, + 0xcf,0x4b,0x2f,0x9a,0x6d,0x7e,0x57,0x25,0xc5,0x95,0x2,0x2d,0x62,0xfe,0x40,0xe2, + 0x99,0x64,0xf8,0x4b,0x11,0x7e,0x40,0x72,0x75,0x81,0x60,0xc,0xd2,0xba,0x1b,0x35, + 0xd9,0xad,0x32,0xd7,0xae,0xfa,0x1,0x15,0x6b,0xa1,0x5a,0xb1,0x1f,0xcd,0x7,0x17, + 0x93,0xd0,0x1f,0xd1,0x3,0x4a,0x2,0xf6,0x90,0x6c,0x87,0x1d,0xcc,0x9d,0xd9,0x8b, + 0xf,0x2e,0x22,0x13,0xaf,0xcb,0x2d,0xb,0x76,0x91,0x39,0x12,0x8f,0x92,0x96,0xa2, + 0x4a,0x80,0xad,0xe8,0xb0,0x6,0x28,0x4b,0xd0,0x17,0xaf,0x88,0x56,0x68,0x76,0x7a, + 0xf2,0xdf,0x69,0x2a,0x44,0x59,0xcd,0x7f,0x4c,0x9,0x7,0x85,0x39,0xc8,0x50,0x8c, + 0x38,0xb9,0xf9,0x7b,0x0,0x98,0x79,0xf4,0x5d,0xe8,0x6,0x96,0x58,0x4a,0x0,0x1d, + 0x12,0xa2,0x85,0x50,0x71,0xf9,0xf1,0x67,0x33,0x3c,0x14,0x33,0x10,0x6f,0xa3,0x58, + 0xd9,0xe8,0xc5,0x48,0xbf,0x74,0x3e,0xf0,0x61,0xf2,0xf0,0xb6,0x35,0x13,0xa9,0x9f, + 0xb0,0x9a,0xf,0xb5,0x60,0x33,0xe7,0xe,0x29,0x53,0xfe,0x76,0x36,0xf8,0x6c,0x9c, + 0x30,0x7b,0xc,0xf,0x10,0xef,0xd9,0x13,0xa9,0x60,0x2c,0x62,0xf3,0x3c,0x5c,0x13, + 0x9,0x6c,0xb1,0x77,0x33,0x49,0x5b,0xf6,0x64,0x9a,0xe9,0x76,0x34,0x67,0xdf,0xc6, + 0x24,0xf4,0x8c,0xbf,0x37,0x7d,0x4f,0x4d,0x64,0xa7,0x76,0x2f,0x46,0x7a,0xf1,0x34, + 0xcb,0x3c,0xaa,0xe4,0xc0,0x2a,0xcd,0x25,0xbc,0x1e,0xff,0xd9,0x96,0xdf,0x53,0x4d, + 0x18,0x8c,0x3c,0x3f,0xe2,0x84,0x99,0xb2,0x76,0xb6,0xe3,0x7b,0x31,0xa5,0x83,0xb3, + 0x33,0xe1,0x23,0x5c,0x46,0xd5,0x6e,0x7,0xd6,0x9,0x89,0x88,0xd3,0xa6,0x36,0x31, + 0x59,0x70,0x70,0x76,0xf0,0xea,0x77,0xdd,0x70,0xfe,0xd3,0x2f,0xbb,0x6c,0xef,0xe6, + 0x1b,0x6e,0x7c,0x42,0x15,0xbe,0x7b,0x7c,0x2f,0x17,0x7d,0xf2,0x1f,0x4e,0x3b,0xe5, + 0xfb,0xdf,0x5b,0xf5,0xdf,0xb7,0xde,0xfa,0xe0,0xf3,0xd3,0xcb,0x8f,0x55,0x83,0x3a, + 0xa2,0xa6,0x95,0xd7,0x4,0x8b,0x84,0x44,0x6a,0xa,0xd2,0x4c,0xe1,0x27,0xf2,0x2, + 0x5c,0xd6,0xdb,0xfe,0x9b,0xb1,0xb4,0xb9,0xa6,0xcf,0x4,0xf5,0xf5,0x64,0x96,0x26, + 0xa0,0x5e,0xe5,0xcd,0x19,0x82,0x9f,0x38,0x10,0x6b,0x6a,0xea,0x42,0x82,0x36,0x7, + 0xce,0x66,0xb3,0xb3,0x5f,0xb4,0xec,0x1d,0x1e,0x86,0xc5,0x42,0x86,0xf,0x5,0x95, + 0x17,0xf7,0x27,0xb1,0x37,0x85,0x47,0xcd,0x6a,0x93,0xd5,0x4b,0x26,0xfe,0xb8,0x5f, + 0xeb,0x38,0xdb,0x33,0x56,0x3e,0x57,0x2a,0x34,0x4,0xba,0x1,0xf6,0x7c,0x3f,0x6e, + 0x5a,0xb8,0x9,0x24,0xba,0x3,0x66,0x67,0x28,0x87,0x6c,0x15,0xb5,0x51,0x92,0x2d, + 0x54,0xc7,0xbd,0x26,0x44,0x8c,0xb5,0x2b,0x96,0x59,0x1b,0xf9,0x1d,0x93,0x7d,0xac, + 0x19,0xb6,0xcc,0xf3,0x59,0xf5,0x1e,0x4,0x92,0x94,0xf7,0x62,0x2d,0x81,0x5,0x19, + 0xb5,0xcf,0x13,0xa6,0x28,0x55,0x21,0x38,0xd5,0x9e,0x3f,0x31,0x9e,0xb1,0x8a,0x7e, + 0x79,0x50,0x15,0x63,0xcf,0x9a,0x40,0xb7,0x93,0xc6,0x4f,0x24,0xf7,0x69,0xb3,0x37, + 0x4c,0x52,0x6f,0x9a,0xa4,0x17,0x9e,0x32,0x5f,0xc2,0xc0,0xa6,0xef,0x9f,0xcf,0x6b, + 0x26,0x4c,0x9f,0xda,0x5a,0xa7,0x36,0xc6,0x92,0xec,0x93,0xa9,0x76,0x4,0x97,0xf6, + 0x93,0xba,0x3b,0x25,0x6,0x23,0x4c,0xb3,0xa0,0xf6,0x6f,0x91,0x89,0x3a,0x4a,0xd5, + 0x7,0xd2,0xef,0xf4,0x17,0xe7,0x4c,0xdc,0x4b,0xa7,0x1a,0x98,0xd7,0x7b,0x6f,0x5b, + 0x3,0x53,0x7,0xf8,0x55,0x1d,0xa9,0xa2,0xbb,0x98,0xe7,0x97,0x2f,0x3b,0xf6,0xd0, + 0x35,0xd7,0x3c,0xb1,0xee,0xcb,0x5f,0x5e,0x6d,0x3,0x28,0xfc,0xbb,0x71,0x5a,0xb5, + 0xe5,0xa1,0xe9,0x2d,0x57,0x5e,0xf5,0xe4,0xf3,0x2b,0x56,0x1e,0x6b,0xf,0xa3,0xd0, + 0xea,0xa2,0xc9,0xc5,0xad,0x61,0x4b,0x4b,0x38,0xae,0x3c,0x6b,0xd4,0x91,0x57,0xbc, + 0x67,0xb9,0x3f,0xa,0x75,0x1e,0xc,0xcf,0x94,0x41,0xe6,0x76,0xe,0x49,0xc4,0xba, + 0xac,0x92,0xde,0xb7,0xa0,0xd2,0xba,0xd4,0x68,0x97,0x68,0x48,0x90,0xf0,0xac,0x5c, + 0x68,0x51,0x69,0x4a,0x9,0xa8,0xb9,0x6f,0x2d,0xe4,0x2c,0x9d,0x75,0xdf,0x78,0x53, + 0xb1,0xa4,0xa1,0xe9,0x12,0xcf,0x71,0xcb,0xa2,0x99,0x71,0x48,0xb3,0x4f,0x99,0x3e, + 0xb,0xcc,0x57,0xac,0xbc,0x8,0xdc,0x64,0x7d,0xb,0x55,0xb9,0x41,0x36,0x23,0x9c, + 0x19,0xcb,0x66,0x84,0x8,0xad,0xd7,0x36,0x77,0x91,0xec,0xac,0x22,0xbc,0xde,0x80, + 0xb6,0x5a,0x38,0x24,0x56,0x83,0xf0,0x30,0xa8,0x56,0x97,0xd1,0x31,0xd5,0xb,0xab, + 0x47,0xeb,0xa1,0x9e,0xe7,0xcb,0xa,0xd6,0xd5,0x2c,0x2d,0x82,0xea,0x69,0xfc,0x4d, + 0x38,0xcc,0x1b,0xe,0x49,0xe3,0x7,0x8a,0xa1,0x5a,0x95,0x51,0x38,0x9b,0x7,0x42, + 0xa0,0x1a,0xd9,0x7,0xd9,0xa,0x64,0x27,0x6c,0x3e,0xf9,0x5b,0xab,0xa9,0xf2,0x18, + 0xb3,0xd4,0x34,0x92,0x9d,0x93,0x71,0xf,0x7,0x2,0xc0,0xd7,0x4c,0x19,0xa7,0x6, + 0x93,0x33,0x98,0x57,0xc9,0xf5,0x5b,0xaa,0x2b,0x48,0xd5,0x38,0x20,0x49,0x90,0x5a, + 0x4f,0xb0,0xc,0xb6,0x70,0x42,0xe6,0xef,0x24,0x7f,0x95,0xa4,0xe0,0x4,0x7,0x19, + 0x7b,0x96,0xd5,0x43,0x4c,0x78,0xb0,0x38,0x29,0x70,0xb7,0x4a,0xc0,0x65,0xc4,0x91, + 0x4e,0x8d,0xb0,0x63,0x51,0x65,0xd2,0x88,0xf9,0xf,0xfb,0x39,0x20,0x46,0xe9,0x19, + 0x1a,0x1f,0x1f,0xed,0xb9,0xb7,0x24,0x6c,0xc4,0x82,0x51,0xcb,0x28,0x54,0xed,0x80, + 0x51,0x15,0x95,0xc3,0x87,0x67,0x7a,0xd3,0xa0,0x49,0x24,0x4,0xa,0x43,0x54,0x32, + 0xe7,0x6a,0x74,0xd6,0x13,0xe1,0x31,0xf8,0xe7,0x97,0xfa,0x33,0x21,0x53,0xb3,0x9, + 0xd1,0x7d,0x82,0xa4,0xe4,0xc5,0x5f,0x17,0xd5,0xff,0xed,0x1b,0x67,0xcc,0xdc,0x6a, + 0xd0,0xc6,0x84,0xec,0xb3,0x4f,0x8a,0x94,0x6d,0xc4,0x2a,0xe4,0x80,0xee,0xcb,0x5e, + 0x35,0xa7,0xf5,0x6a,0x3d,0x59,0x35,0xa9,0x57,0x49,0x45,0x3f,0x11,0xf,0x57,0x1a, + 0xfd,0x56,0x36,0xaa,0x49,0xcf,0x93,0x41,0x93,0x93,0x1e,0x20,0x32,0x78,0x95,0xd5, + 0x32,0x6b,0xd3,0xae,0x12,0x89,0x23,0xac,0x55,0x9d,0x7b,0xa,0x16,0xa4,0x3d,0xbe, + 0xb0,0x93,0x90,0x12,0xf4,0x47,0xa8,0x11,0x82,0x6a,0xb5,0xbe,0x34,0x26,0xe4,0x99, + 0xf7,0x65,0xcf,0x74,0xba,0xb3,0x3a,0xb5,0xd6,0x3,0x90,0xbe,0x35,0x38,0x29,0x80, + 0x63,0x9b,0xb9,0xb1,0xb1,0x67,0x24,0x28,0xc9,0xb2,0x64,0xb5,0xc,0x8b,0xdd,0x5f, + 0xc5,0xd5,0x90,0xd6,0x93,0xe7,0xb3,0x3f,0xf9,0x3d,0x97,0xee,0xdb,0x52,0xd9,0xc3, + 0x2a,0xd9,0x34,0x5e,0x2b,0xb,0x48,0x7b,0x65,0x17,0x6b,0xeb,0xb1,0x92,0xc5,0xce, + 0x4b,0x10,0x9a,0x21,0x25,0x42,0x94,0x17,0x8d,0x3f,0x27,0x23,0xfb,0x68,0xdf,0xdc, + 0xd4,0x9e,0xbd,0x19,0xe7,0x42,0x75,0xe,0x10,0xd4,0x83,0x6b,0x66,0xd7,0xd1,0xd, + 0x9c,0x97,0x38,0xfe,0xe3,0xfb,0x19,0xa5,0xe2,0x9a,0xfd,0xb6,0xbb,0x1b,0x5,0xa6, + 0xa4,0x42,0x4d,0x1,0x23,0x51,0xed,0xa9,0x8d,0x84,0xd7,0x80,0x96,0xb9,0xf6,0x1c, + 0x64,0xc6,0x22,0x2b,0xb6,0xc9,0xa2,0x48,0x0,0xfe,0x9d,0x44,0x42,0x2a,0x15,0xef, + 0x3a,0xd7,0x3b,0xd4,0x8,0x33,0xa0,0x75,0xa0,0xa7,0x93,0xa9,0x7b,0x8f,0x4e,0x8a, + 0x27,0xdc,0x7b,0x9b,0xe6,0x63,0x13,0x72,0xfd,0x78,0xdd,0xc2,0x27,0x5e,0x75,0xe1, + 0x4a,0xf7,0xf9,0xb5,0xd7,0x63,0x31,0x18,0x6b,0x7b,0x58,0x9b,0x53,0xcd,0xa4,0xe, + 0x5a,0xd9,0xb6,0x9c,0x41,0xa8,0xd6,0x5f,0xe,0xc3,0x99,0x3e,0xcb,0x7a,0xb0,0x7f, + 0xaf,0x9c,0xd3,0x66,0x65,0xe4,0x39,0x84,0xfa,0x49,0x25,0x22,0xc6,0x6c,0xbd,0x59, + 0x1f,0x2a,0x35,0xc7,0x7,0x5e,0x90,0x4e,0xc1,0x13,0x7e,0x37,0x3c,0x2f,0xb6,0x99, + 0xb6,0xb5,0x71,0x92,0x35,0xa,0x2f,0xe7,0x86,0xfa,0x73,0x1c,0x7c,0xd0,0xd0,0x80, + 0x96,0x2c,0x53,0xae,0x1f,0x6b,0x24,0xc9,0x57,0x8,0xb4,0xfc,0xc3,0xab,0x6,0x44, + 0x16,0x96,0x55,0x5a,0x7b,0x7c,0x21,0x42,0x96,0x8d,0x6b,0xd9,0x1d,0xd2,0x4a,0xe0, + 0xa7,0xb4,0x95,0x40,0x46,0x6c,0x96,0x9,0x8,0x2c,0x58,0x56,0xe3,0xb0,0xac,0x6f, + 0x6d,0xc2,0xac,0x4d,0xfb,0x2,0xd,0xab,0xd4,0xe3,0x3c,0xe5,0xdf,0xa4,0xd6,0xdb, + 0xcc,0xff,0x6f,0xf5,0xc0,0xcc,0xcf,0x21,0x4c,0x20,0xd4,0x3d,0x17,0x23,0x49,0x8b, + 0xd6,0xca,0xb5,0xc0,0xf8,0xd6,0xca,0x78,0xa7,0xcc,0x57,0xf2,0x75,0x36,0x6c,0x6e, + 0x7a,0x0,0x32,0xb9,0x65,0xcd,0x81,0xa3,0x69,0x84,0x3e,0x53,0x62,0x1,0x67,0x99, + 0xb9,0x80,0xd7,0xac,0x72,0x8a,0xab,0x57,0xf0,0xca,0xfc,0x4,0xac,0xcf,0x1b,0xc0, + 0x1d,0xaa,0xe4,0x1c,0x13,0x49,0xee,0xa5,0x61,0x7d,0x10,0xde,0x44,0x20,0x2d,0x56, + 0x1e,0x88,0x75,0x8c,0x1d,0x78,0xb1,0xe6,0x62,0xaf,0x3f,0xc0,0x12,0xdd,0xd4,0x7d, + 0x29,0x32,0xf1,0x10,0xe6,0x45,0x1a,0xbf,0x3f,0x30,0x4d,0x73,0x3d,0x50,0x5c,0xa6, + 0x81,0x19,0x99,0x56,0x32,0x4e,0x9a,0x41,0x69,0xde,0x54,0xd2,0x21,0x82,0xaf,0x33, + 0xd7,0xfb,0x67,0x92,0xa8,0xe0,0xb8,0xf,0xb5,0x8c,0x46,0x2,0xb3,0x4a,0xe5,0x10, + 0xc3,0xc0,0xc8,0x2c,0x43,0x3c,0xb5,0x3,0xc0,0x20,0xf0,0x50,0xe3,0x35,0x51,0x8d, + 0xfb,0x15,0xd,0x80,0x55,0xc8,0x86,0xef,0xdf,0xab,0x31,0x4b,0x33,0x9c,0x23,0xca, + 0x89,0x50,0x6,0xd7,0x6b,0x84,0xd4,0xd1,0xc2,0x75,0x2c,0x7b,0x67,0x96,0xa9,0x4, + 0x9a,0xc7,0x0,0x17,0xc7,0x2c,0xcd,0x1d,0x85,0x67,0xe7,0xe,0x6e,0x2c,0xd5,0xf8, + 0x3,0xd2,0xa4,0x2,0xc9,0x5b,0x7e,0x16,0x49,0xd5,0xc6,0xc3,0xe1,0xee,0x1a,0x35, + 0x2b,0x25,0xa4,0xe7,0x6c,0xb5,0x20,0xc0,0xa4,0x4e,0x30,0xc2,0x4d,0x15,0xe6,0x30, + 0xce,0xb9,0xe6,0x10,0xaa,0x5a,0x8c,0x59,0x1c,0xaf,0x70,0xc8,0x5a,0xbd,0xf4,0xe1, + 0xef,0xc1,0x20,0xb0,0x9,0xd3,0x9d,0x1c,0xf8,0x2,0x8a,0x46,0x78,0x10,0x89,0x65, + 0x18,0xbd,0x2f,0x80,0x36,0x36,0xd7,0x35,0x47,0x96,0x8,0x63,0x63,0x3b,0x85,0xf6, + 0xec,0x71,0xe1,0x90,0xc0,0xfd,0x54,0xfa,0xcb,0x6,0x6a,0x39,0x22,0x54,0x36,0x37, + 0x2a,0x90,0x3e,0x15,0xef,0x81,0xc3,0x86,0x91,0xa,0x9d,0x6e,0x41,0x36,0x66,0xb0, + 0xfc,0x1c,0x6b,0x71,0x97,0x91,0x40,0xd1,0x1f,0x38,0x6,0x81,0x72,0x40,0x4d,0x8c, + 0x1f,0xda,0xc9,0xa2,0x10,0x2,0x2a,0x9c,0x23,0x35,0xaf,0x5,0x7f,0x91,0xcd,0x33, + 0x54,0x16,0x6c,0x48,0x7f,0x1d,0xdb,0xcf,0xd7,0x34,0xf6,0x10,0x40,0xfb,0x3d,0x5a, + 0xfb,0x18,0xf8,0xca,0xcf,0x6,0x73,0xe5,0x4,0x4c,0xa2,0xc,0xf6,0x8f,0x8e,0x97, + 0x6a,0xf9,0x20,0x63,0xf3,0x4e,0x6b,0xb5,0x7,0x17,0xc5,0x78,0x9a,0xbe,0xf4,0x38, + 0x76,0xb4,0x9b,0x3b,0x30,0x34,0x95,0xd2,0x6e,0x73,0xc6,0x6d,0x4a,0xf6,0x3e,0xff, + 0x19,0x46,0x22,0xf3,0xa4,0x52,0x20,0xc9,0x46,0x95,0x4d,0x68,0xab,0x44,0xfe,0x41, + 0x5f,0xd2,0xea,0xac,0x37,0x51,0x1e,0xa1,0x6a,0x1f,0x9c,0x53,0xd9,0x50,0x94,0x64, + 0x50,0x6a,0xa9,0x17,0x31,0xbd,0xce,0x8c,0x4c,0x1e,0x25,0x9b,0x82,0x54,0xfe,0x6e, + 0x79,0x3,0xc7,0xba,0x94,0x9,0x39,0xac,0xc8,0xbd,0xd6,0xca,0xc,0xea,0x16,0x99, + 0xef,0xeb,0x64,0x50,0x1f,0x66,0xdb,0x22,0xbc,0xb5,0xc4,0xb4,0x9e,0x19,0x85,0xac, + 0xd4,0xe2,0xc2,0x61,0x7,0x2b,0x65,0xe2,0x62,0x26,0x6,0xec,0x6c,0x3f,0xf,0xd4, + 0xaf,0x2f,0xcd,0x10,0x1d,0xcb,0x8e,0x95,0x5,0x1d,0x42,0x20,0x50,0x83,0x4d,0x44, + 0xb2,0x84,0x65,0x62,0x66,0x92,0x88,0xd8,0xac,0x9e,0x79,0xa5,0xb9,0xc9,0x36,0xd0, + 0xa,0xf2,0x85,0x99,0x22,0x51,0xf0,0x3,0xf3,0xe8,0xca,0x1a,0xad,0x64,0x38,0x6c, + 0xe3,0x17,0x8b,0xcf,0x57,0x95,0x23,0xf,0xa,0x48,0x4b,0x40,0x61,0x88,0x3f,0xa5, + 0x54,0xd0,0x15,0x6,0xcf,0x60,0xc6,0xa5,0x64,0xe3,0x47,0xf1,0x9a,0x2a,0x32,0x41, + 0xf6,0x80,0x14,0x90,0x90,0xa0,0x90,0xb9,0xa1,0x31,0x2b,0xc1,0xd8,0xaa,0x1,0xf3, + 0xb3,0x2,0x3f,0xab,0x55,0xe3,0x88,0x90,0x5c,0xb0,0x39,0x62,0xc6,0xdf,0x93,0xf6, + 0x39,0x44,0x6b,0xf1,0x10,0xb7,0x98,0xe1,0x9b,0xe5,0xb1,0xee,0xd,0x18,0x64,0x1e, + 0xe4,0x43,0xeb,0xb7,0x19,0xd6,0x9e,0xbd,0x0,0xf7,0x4,0x23,0x1,0x93,0x4e,0x1a, + 0xb,0x25,0xa8,0x18,0x20,0x43,0xe3,0xc7,0x56,0xd2,0x24,0xc,0xb0,0x4,0x28,0xd4, + 0x60,0xd4,0xa4,0x70,0xc3,0xaa,0x3c,0x92,0x12,0xad,0xd4,0x5c,0x60,0xc2,0x1a,0x4b, + 0xa7,0x48,0xf4,0x4f,0x59,0xaa,0x5a,0x99,0x80,0xc6,0x37,0x74,0x84,0x8c,0x91,0xd5, + 0x6b,0x15,0x2f,0x4c,0x1f,0x79,0x6b,0x5f,0x99,0x47,0x23,0xa4,0xc5,0xf4,0xcb,0x19, + 0xc4,0x53,0x85,0x87,0x21,0xc8,0x61,0x3e,0xe2,0xc,0x5a,0x4f,0x84,0xa,0xd2,0xca, + 0xc1,0xa0,0x69,0x16,0x35,0x2a,0x43,0x9,0x60,0x1e,0x24,0xa8,0x4a,0x32,0xab,0xbb, + 0x16,0x74,0x78,0xa8,0xcc,0x14,0x32,0x2,0x25,0x70,0xb3,0xc2,0xa6,0x2,0x73,0x44, + 0xad,0xe,0x93,0x30,0x38,0x30,0x5c,0x8b,0xc6,0xd,0xc3,0x2a,0x7,0x4c,0xad,0xf6, + 0x66,0xe0,0x8a,0x67,0x64,0x1,0x5a,0x25,0x23,0x67,0xfb,0x82,0x56,0x82,0x68,0x1a, + 0x8c,0xe3,0x24,0xb3,0x7c,0x78,0x22,0xb2,0x60,0x59,0xd,0xb1,0xf7,0x39,0x82,0xcc, + 0x2e,0xcd,0xce,0x8c,0x95,0x58,0xb4,0x7,0xb6,0xd2,0xa,0x29,0xad,0xa7,0xd4,0x82, + 0x5e,0xd6,0xa9,0x74,0x47,0xae,0x4f,0x35,0x97,0xf3,0xcc,0x7,0xfe,0x96,0xa1,0x67, + 0x81,0x3d,0xc6,0x7,0x27,0xac,0x35,0x27,0xec,0x15,0x52,0x21,0x35,0x59,0xcd,0x41, + 0x76,0x2,0x4c,0x6f,0x3d,0xfc,0x9d,0x9e,0x4d,0xc9,0x2a,0x9c,0x9c,0xda,0x3e,0xa9, + 0xb5,0x92,0x1,0x83,0x48,0x2d,0x92,0xd,0x13,0x89,0xc,0x4a,0x92,0xc8,0x97,0x49, + 0xe7,0x5,0xe3,0x4b,0x98,0x50,0xfd,0xe9,0x74,0x60,0x2b,0xef,0x1,0xf,0x1,0x1d, + 0x29,0x8b,0x68,0x25,0x98,0x67,0x67,0x93,0x2,0x21,0xd7,0xd0,0x25,0x8e,0x3d,0xf, + 0x25,0x9,0xb3,0x72,0xb2,0x6f,0x8,0xfe,0x59,0xbb,0x9a,0x92,0xb2,0x88,0x42,0x67, + 0x79,0x9a,0xb,0x46,0xea,0x9a,0xc2,0xf,0xe4,0xd0,0x53,0x7,0xcc,0x42,0x3f,0xe0, + 0xa,0x11,0xb9,0x56,0xb4,0xf9,0x52,0x34,0x67,0x1c,0x5a,0x4d,0x93,0xd7,0x38,0x72, + 0xa2,0xc4,0xb3,0xb0,0xa6,0x28,0x24,0x2c,0x48,0xb1,0x7a,0xf1,0xb7,0xf,0xea,0x44, + 0x48,0xdf,0xb4,0x92,0xed,0xa8,0x50,0x76,0xb5,0x32,0xb8,0xc9,0xb8,0x5b,0x8b,0xaf, + 0x1f,0x57,0x77,0x6,0xad,0x6c,0x8c,0x6,0xf5,0x25,0xf2,0xbd,0x9,0x1a,0x54,0x52, + 0xea,0x20,0x69,0x19,0x15,0x99,0xd0,0xdc,0x3f,0xcc,0x2,0xab,0x30,0xb7,0x48,0x49, + 0xc5,0xe0,0xf0,0xf0,0x8b,0xc4,0x14,0x88,0x25,0x5a,0x3f,0x50,0x8c,0xec,0x55,0x4a, + 0xe6,0xbd,0x5a,0xff,0x82,0xad,0x7d,0x66,0x82,0x80,0x7b,0x6a,0x85,0x56,0xe3,0x42, + 0x48,0x65,0xdd,0x8,0x41,0x81,0x6a,0x48,0xc,0x6,0x3a,0xc6,0xef,0xcf,0x48,0xb6, + 0x57,0xed,0x3b,0x56,0x67,0x0,0xe2,0xb3,0x33,0xe3,0xc1,0x3f,0x56,0x29,0x6a,0xf3, + 0x4e,0xa2,0xa7,0x7a,0x2d,0xf6,0x4d,0x87,0x48,0x4a,0x36,0x60,0xc,0xac,0x52,0x9e, + 0xaa,0x32,0xfe,0x11,0x9,0xc1,0xec,0xdf,0x7a,0x90,0x54,0xf4,0xb2,0xd6,0x9e,0x25, + 0xc9,0x10,0x1d,0xc9,0xd9,0x72,0x4a,0x10,0x18,0xac,0x6f,0x19,0xd9,0x54,0xb6,0x9e, + 0xa0,0x5,0x30,0x21,0x22,0x50,0x83,0x56,0x80,0xc9,0xad,0x2f,0x60,0xd7,0x8,0xe7, + 0xfb,0x44,0xd1,0x3f,0x53,0x23,0x65,0x2e,0x7a,0x4d,0x4a,0x20,0x7d,0x86,0x38,0xc1, + 0x77,0x69,0x25,0xfb,0xb5,0x4a,0x40,0x96,0x94,0x2c,0xad,0x52,0x6a,0x23,0xeb,0x18, + 0xf7,0x52,0x85,0x2e,0x94,0xc4,0x37,0xe8,0xeb,0xe1,0x83,0xb1,0x30,0x72,0x4e,0xc2, + 0xbe,0x50,0xb2,0x40,0xc5,0x24,0x76,0xae,0x70,0x68,0x4c,0x85,0x10,0x4d,0xc8,0x81, + 0x67,0x48,0x30,0x33,0x2,0x33,0x1a,0x1c,0xe,0xec,0x10,0xb2,0xca,0x46,0xa9,0x7c, + 0xf3,0x34,0x6c,0xd9,0x50,0x9a,0xb8,0x50,0xfb,0x22,0x52,0xf6,0xe2,0x91,0x33,0xf, + 0xa2,0xa2,0xf0,0x83,0xe5,0xfa,0x9b,0x91,0x80,0x44,0x99,0x64,0xe1,0x4,0x48,0x4a, + 0x35,0x2e,0x54,0xf,0x53,0x25,0xf,0x67,0xad,0x43,0x9a,0xac,0x26,0xa5,0x52,0x3f, + 0x70,0x82,0x51,0x3,0xec,0xd6,0x6a,0xb9,0x44,0xc2,0x6a,0x50,0x46,0xcc,0x82,0xd9, + 0xa1,0x16,0xc4,0x48,0xfc,0x38,0x59,0x6e,0x93,0x42,0xd6,0xb8,0x91,0x1a,0xbc,0xd6, + 0x6a,0xbd,0x90,0x51,0x86,0xd,0x8a,0xa4,0xaa,0xda,0x43,0x62,0xea,0x83,0xf3,0x10, + 0xfd,0x52,0x40,0x7e,0x42,0xad,0x91,0x1c,0xb8,0x4a,0x90,0x80,0x90,0xb1,0x10,0xc8, + 0xd6,0x34,0x13,0x76,0xfa,0xd8,0xc5,0xc,0x7e,0x45,0x64,0xc0,0xa4,0xa2,0x6a,0x56, + 0x43,0xe0,0x14,0xca,0x22,0x3d,0x70,0x70,0x40,0x66,0x34,0xa8,0xc0,0x75,0x63,0xa7, + 0x39,0x38,0x60,0x6a,0x62,0xaa,0x95,0x75,0x80,0xdc,0xa,0x9f,0x41,0x92,0xb2,0x59, + 0x22,0xc8,0x32,0x92,0xa1,0xf2,0x12,0x1a,0x8d,0xb3,0x2b,0x5c,0x13,0xba,0x7,0x69, + 0x9e,0x27,0x94,0xbd,0xa6,0x52,0xd7,0x49,0x60,0x87,0x97,0x56,0xea,0xce,0xa,0x8, + 0x9f,0x55,0x92,0x2a,0x21,0x9,0x9e,0x91,0xd2,0x27,0xfa,0x9e,0x23,0x2a,0x46,0xca, + 0x27,0x7d,0x68,0x1,0x25,0x2e,0x4a,0xe6,0x6a,0x60,0x9,0x51,0x49,0x22,0xca,0xc6, + 0x70,0xbe,0x5a,0x19,0x29,0xb0,0xa9,0xb5,0xf0,0x56,0xb8,0xc,0xd2,0x73,0xfe,0xa6, + 0x64,0xd1,0xa3,0x93,0xdd,0xb5,0x94,0x2e,0x52,0xb2,0xa,0x5c,0xc8,0x6a,0x9f,0x3a, + 0xa1,0xb6,0xc1,0xa2,0x1b,0x16,0xe5,0x13,0x8,0x5f,0x84,0x1f,0x6c,0x35,0xc6,0xb2, + 0x49,0x7d,0x2,0xb1,0x93,0x96,0xb2,0xa8,0xc9,0x43,0x43,0x26,0xb1,0x55,0x36,0xd9, + 0xfa,0xa8,0x4b,0x76,0xa,0x90,0xc,0x39,0x85,0x7a,0x33,0x92,0xb1,0x34,0xf7,0x42, + 0xa,0x21,0x15,0x69,0x25,0xc0,0x13,0x96,0xd1,0x63,0xad,0x1d,0x7b,0x51,0xb5,0xbe, + 0x28,0x12,0xaa,0x60,0xb9,0xe,0x8c,0xbe,0x9d,0x8c,0x6c,0xe3,0x17,0x54,0x6d,0xa1, + 0x5a,0x25,0xa8,0xa0,0x35,0x7f,0x2,0x6b,0x99,0xe6,0xd,0x4c,0x7b,0x82,0x18,0x81, + 0xe7,0x4b,0xb3,0x37,0xe3,0x90,0x59,0x5f,0xcb,0x94,0x92,0xa8,0x41,0x35,0xcf,0x91, + 0xd0,0xbb,0xb,0xbd,0xbd,0x1e,0xda,0x35,0xa2,0xc1,0x6b,0x95,0xec,0x9c,0x21,0x0, + 0xe9,0xc0,0x57,0xa8,0xff,0xd5,0x5a,0x8a,0x2c,0x67,0xe0,0xaa,0xbc,0xed,0xb1,0x97, + 0xfd,0xec,0xf6,0x1b,0x25,0x50,0x3b,0xdb,0x74,0x53,0x70,0xe,0x44,0x36,0x25,0x75, + 0x75,0xc,0xdc,0x95,0x4,0x7d,0x7d,0xe5,0x12,0xe4,0x53,0xa8,0xf6,0x1c,0x64,0xc8, + 0x1d,0xb2,0x18,0x88,0xf4,0xc4,0x10,0x7c,0x5e,0x48,0x46,0x9b,0x18,0xd7,0xc1,0x2a, + 0x49,0x14,0x6,0xf6,0x6,0x87,0x93,0x6a,0x5,0x9,0x34,0x92,0x8d,0x6a,0xe4,0xb2, + 0xd4,0x92,0x16,0x11,0x7e,0xfd,0x29,0xf6,0x55,0x8e,0xf0,0x6a,0xd,0xc9,0xd7,0x1c, + 0xa4,0x33,0x56,0x25,0x6b,0xff,0xc3,0xe,0xa,0xed,0x2b,0xd9,0x54,0xf6,0x21,0xda, + 0x85,0x21,0x7c,0x4f,0x65,0xb5,0xed,0x89,0xa2,0x5c,0xda,0x8f,0x12,0x19,0xd9,0x8f, + 0x42,0x59,0x32,0x6,0x46,0xff,0xf,0x29,0xcc,0x82,0x9,0xae,0x64,0xb9,0x0,0x0, + 0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/right.png + 0x0,0x0,0x0,0x90, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x15,0x8,0x2,0x0,0x0,0x0,0xf4,0x25,0x38,0x99, + 0x0,0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4, + 0x1,0x95,0x2b,0xe,0x1b,0x0,0x0,0x0,0x42,0x49,0x44,0x41,0x54,0x78,0x9c,0x63, + 0xb4,0x76,0x74,0x95,0x93,0x93,0x7f,0x7c,0xf7,0x6,0x3,0xc,0xc8,0x2a,0x6b,0x2c, + 0x5f,0x38,0x87,0x89,0x1,0x15,0xfc,0x67,0xe5,0x86,0x30,0xd0,0x25,0x18,0x7f,0x7f, + 0xc5,0x2e,0x1,0x7,0x44,0x1b,0x85,0x53,0x7,0x15,0x25,0x48,0x77,0x2e,0x4e,0x89, + 0x1,0xf5,0x7,0xe9,0x12,0x38,0x7d,0xe,0xf7,0x7,0x0,0xa4,0x3a,0x10,0x39,0xce, + 0x4b,0x7a,0x37,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/topBorder.png + 0x0,0x0,0x0,0x90, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x15,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0x16,0x5f,0xb4,0xd3, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x25,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0x8c,0x8c,0x4f, + 0xf9,0xcf,0x40,0x65,0xc0,0x68,0x63,0x63,0x43,0x75,0x43,0x99,0xa8,0xec,0x48,0xb0, + 0x71,0xa3,0x86,0x52,0x3f,0x54,0x19,0x69,0x91,0xa4,0x0,0x41,0xac,0x5,0xf7,0xea, + 0x8d,0x19,0x2b,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/up_arrow.png + 0x0,0x0,0x0,0x7d, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x2,0x0,0x0,0x0,0xb4,0xb4,0x2,0x1d, + 0x0,0x0,0x0,0x44,0x49,0x44,0x41,0x54,0x78,0x9c,0xd5,0xcb,0xbb,0xd,0x0,0x20, + 0xc,0x43,0x41,0x47,0x5e,0x2c,0xa3,0x67,0x33,0x53,0xa4,0x41,0x84,0x5f,0x9,0x2e, + 0xad,0x7b,0xc0,0x2b,0xe3,0xf4,0x95,0x64,0x66,0x11,0x71,0xd6,0x92,0x0,0xb8,0x7b, + 0xd,0x46,0x9d,0x34,0x57,0x3,0xae,0xe8,0x34,0xe0,0x86,0xd6,0x80,0x7b,0x3a,0x4, + 0x3c,0xd2,0x3e,0xb0,0x1b,0xfa,0xfd,0x1a,0x8,0x5a,0x2a,0x14,0x67,0x84,0x29,0xfd, + 0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/hpsdr4.png + 0x0,0x0,0x61,0x2e, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x1,0x90,0x0,0x0,0x1,0x90,0x8,0x6,0x0,0x0,0x0,0x80,0xbf,0x36,0xcc, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x6,0x62,0x4b,0x47,0x44,0x0,0xff,0x0,0xff,0x0,0xff,0xa0,0xbd,0xa7,0x93,0x0, + 0x0,0x0,0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xd,0xd7,0x0,0x0,0xd,0xd7,0x1, + 0x42,0x28,0x9b,0x78,0x0,0x0,0x0,0x7,0x74,0x49,0x4d,0x45,0x7,0xdb,0x5,0x18, + 0x3,0x18,0x1e,0x93,0x32,0xad,0x2f,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x78, + 0xda,0xec,0x7d,0x77,0x9c,0x1d,0x57,0x75,0xff,0xb9,0x33,0xf3,0xca,0xee,0xdb,0xde, + 0x8b,0xb4,0xea,0xc5,0xaa,0x96,0x64,0xb9,0xdb,0x42,0xae,0x32,0x72,0x17,0xc6,0x5, + 0x17,0xf8,0x19,0x8,0x49,0x80,0x4,0x92,0x1f,0x49,0x48,0x20,0x84,0x10,0x20,0x10, + 0x8,0xc1,0x60,0xe0,0x7,0xc6,0xe0,0x8a,0x71,0xc3,0x5d,0xb8,0xc8,0x45,0xee,0xb6, + 0x9a,0x55,0x2c,0x69,0x77,0xb5,0xbd,0xb7,0xd7,0xdb,0xcc,0xdc,0xfb,0xfb,0x63,0x65, + 0x47,0x92,0xf7,0xcd,0xbd,0xf3,0x66,0x76,0xf6,0xbd,0x79,0xe7,0xfb,0xf9,0xec,0x27, + 0x41,0x9e,0x77,0xe7,0xce,0x39,0xe7,0x9e,0x76,0xcf,0x3d,0x17,0x0,0x81,0x40,0x20, + 0x10,0x8,0x4,0x2,0x81,0x40,0x20,0x10,0x8,0x4,0x2,0x81,0x40,0x20,0x10,0x8, + 0x4,0xc2,0x7d,0x20,0x48,0x2,0x4,0x2,0x91,0xa3,0xa8,0xb0,0x79,0x2c,0xbb,0xf4, + 0x5d,0x19,0x0,0x48,0x36,0x8e,0x25,0xdb,0x34,0x96,0x2,0x0,0x1a,0x0,0x24,0x1, + 0xa0,0xb,0x0,0xfa,0x1,0x80,0xb9,0xc5,0x80,0x78,0x8f,0x32,0x31,0x80,0x2,0x66, + 0xa,0xa5,0x47,0x5,0xc3,0xe,0x4,0x0,0xc0,0x63,0xe3,0x58,0x5e,0x9b,0xc6,0xf2, + 0x1f,0xfd,0xb3,0x6b,0xac,0x22,0x1b,0x65,0xb6,0xd8,0xc6,0xb1,0xec,0x92,0x7d,0xf9, + 0xa8,0x5c,0xd8,0x35,0x56,0x99,0x8d,0xfa,0xa4,0x1c,0xed,0x5e,0xce,0x20,0x9,0x0, + 0xef,0x1,0xc0,0x2b,0x0,0xb0,0x1d,0x0,0x5e,0x6,0x80,0x54,0xae,0x1b,0x10,0x5, + 0x0,0xd6,0x2,0xc0,0xd9,0x0,0x70,0x1a,0x0,0xcc,0x3,0x80,0xb9,0x36,0xa,0x3c, + 0x2,0x81,0x40,0x20,0xcc,0x23,0x8,0x0,0xf,0x1,0xc0,0xed,0x0,0xf0,0x7e,0xae, + 0x19,0x90,0x55,0x0,0x70,0x13,0x0,0x5c,0xb,0x0,0xb5,0xc8,0x2b,0x4,0x2,0x81, + 0xc8,0x49,0x50,0x0,0x78,0x4,0x0,0xbe,0x7,0x0,0x7,0x66,0xda,0x80,0x9c,0xf, + 0x0,0x7f,0x7,0x0,0x1b,0x91,0x2f,0x8,0x4,0x2,0x91,0x37,0xd0,0x0,0xe0,0x17, + 0x0,0xf0,0x6d,0x0,0x88,0x3a,0x6d,0x40,0xe6,0x1,0xc0,0x8f,0x1,0x60,0x13,0xf2, + 0x1,0x81,0x40,0x20,0xf2,0x16,0xed,0x30,0x99,0x3d,0xda,0x65,0xf6,0x87,0xd9,0xee, + 0xfe,0xff,0x5,0x0,0xfc,0x11,0x0,0x4e,0x42,0xda,0x23,0x10,0x8,0x44,0x5e,0xa3, + 0xa,0x0,0x6e,0x4,0x80,0x6e,0x0,0xd8,0x3b,0x9d,0x6,0x24,0x0,0x0,0xbf,0x7, + 0x80,0xaf,0x80,0x7d,0xd5,0x3c,0x8,0x4,0x2,0x81,0x98,0x59,0x28,0x0,0x70,0x39, + 0x4c,0x56,0x69,0xbd,0x3e,0x1d,0x6,0xa4,0x1a,0x0,0x9e,0x80,0xc9,0x3d,0xf,0x4, + 0x2,0x81,0x40,0xb8,0xb,0x4,0x0,0xce,0x33,0x63,0x44,0x44,0xd,0x48,0x25,0x0, + 0x3c,0x7,0x0,0x27,0x23,0x8d,0x11,0x8,0x4,0xc2,0xd5,0xd8,0x8,0x93,0x7,0x11, + 0xdf,0x13,0xb1,0x38,0x3c,0x14,0x3,0xc0,0x33,0x0,0x70,0x2a,0xd2,0x15,0x81,0x40, + 0xe4,0x3b,0x24,0xaf,0xf,0x80,0x58,0x2f,0x40,0x95,0x3c,0x3e,0x66,0xcb,0x38,0x5e, + 0xaf,0x2d,0xf3,0x1,0x0,0x60,0x6a,0x1a,0xb4,0x58,0x94,0x30,0x4d,0xb5,0x3a,0x54, + 0x2,0x0,0x36,0x0,0x67,0x4f,0x44,0x64,0xd6,0xbf,0x5,0x80,0xeb,0x73,0x4e,0x8, + 0x7c,0x7e,0x9b,0x84,0xc9,0xcf,0xec,0x19,0xc7,0x6b,0x93,0x50,0x7a,0x19,0x91,0xac, + 0x1f,0x62,0x27,0x1e,0x2f,0x10,0x49,0xb6,0x61,0x1c,0xf,0x48,0x76,0x8c,0xa3,0xc8, + 0x8c,0xc8,0x36,0x1c,0xa8,0x97,0x14,0x20,0x8a,0xf5,0x71,0x88,0xac,0x0,0xf1,0x28, + 0x96,0x79,0x4f,0x24,0x5,0x88,0x62,0x7d,0x3b,0x90,0x48,0x4,0x88,0xd7,0xfa,0xc1, + 0x7e,0x42,0x8,0x48,0x1e,0x8e,0x4c,0x33,0x81,0xf6,0x16,0x12,0x1,0xd9,0xeb,0xb3, + 0x61,0x65,0x10,0x90,0x7c,0x36,0xad,0x31,0x9f,0xf,0x10,0x62,0xd0,0x42,0x41,0x92, + 0xe8,0xef,0x92,0x62,0xed,0x7,0xa4,0x44,0x7f,0xb7,0x4,0x2c,0x2b,0x16,0x1c,0x6, + 0x80,0x33,0x0,0x20,0x9e,0xad,0x1,0xb9,0x19,0x0,0x7e,0x95,0xdd,0x2,0x95,0xc1, + 0xdf,0x34,0x87,0x16,0xcd,0x9e,0x4f,0x7d,0xb5,0xd,0xcc,0x53,0x56,0xc5,0xe4,0xa2, + 0x22,0x66,0x97,0xa5,0x45,0x20,0x10,0x8,0x84,0x80,0x31,0x9,0x7,0x21,0xb8,0xe3, + 0x55,0x25,0x72,0x78,0x5f,0x36,0x9e,0xe0,0x7f,0x3,0xc0,0xd7,0xb3,0x31,0x20,0xf5, + 0x30,0x99,0x3,0x33,0xd5,0x27,0x47,0xf2,0x78,0xa1,0x6c,0xc5,0x3a,0xbd,0x6c,0xe5, + 0x7a,0x5d,0x2e,0x2a,0x66,0xc8,0xbe,0x8c,0x6e,0x20,0xd2,0x6,0x81,0x40,0x38,0x86, + 0x44,0x7f,0xb7,0x34,0xfa,0xe2,0xd3,0x1e,0x2d,0x1a,0x32,0xe3,0xc5,0x6b,0x30,0xb9, + 0x7d,0xf1,0xbe,0x59,0x3,0x72,0x7,0x0,0xdc,0x60,0x66,0x82,0xc5,0x2d,0xb,0x68, + 0xf5,0x39,0x17,0xab,0x4a,0x49,0x29,0x2a,0x47,0x4,0xe2,0xf8,0xa5,0x86,0x6b,0x2, + 0x31,0xe3,0xa0,0xc9,0x24,0x19,0x7a,0xf6,0x61,0x6f,0x72,0xa0,0xc7,0x4c,0x9e,0xfc, + 0x41,0x98,0xcc,0x46,0x9,0x1b,0x90,0x93,0x61,0xb2,0x8c,0x4b,0xd8,0x52,0x55,0x9e, + 0xba,0x41,0xad,0x58,0x73,0x86,0x86,0x2c,0x42,0x20,0x10,0x88,0xf,0x90,0x7b,0x99, + 0x6,0xa6,0xeb,0x30,0xf8,0xd4,0x3,0xbe,0xe4,0x40,0x8f,0x68,0x4a,0x4b,0x7,0x80, + 0x35,0x0,0xd0,0x7a,0xe2,0x7f,0xc8,0x34,0xc0,0xf,0x0,0x60,0xb9,0xe8,0x84,0xaa, + 0xcf,0xbe,0x58,0x2d,0x5f,0xb5,0x5e,0x43,0xa6,0x22,0x10,0x8,0x44,0x8e,0xc7,0xc2, + 0x92,0x4,0x81,0x39,0x8b,0x68,0xac,0xfd,0xa0,0x42,0xd3,0x29,0x91,0x20,0x41,0x2, + 0x0,0x15,0x0,0x9e,0x17,0x89,0x40,0x9a,0x1,0xe0,0x20,0x8,0xde,0x41,0x51,0xb1, + 0xee,0x6c,0xb5,0xf2,0x94,0xb3,0x54,0x64,0xb,0x22,0x77,0x57,0xc,0xa6,0x8f,0x10, + 0x88,0x13,0x91,0x1a,0xe8,0x91,0xfb,0x1f,0xbf,0xcf,0x2f,0xe8,0x4f,0xf,0x3,0xc0, + 0xc2,0xa3,0x86,0xe4,0x43,0x4c,0x65,0x24,0x6e,0x10,0x35,0x1e,0x45,0x4d,0x73,0xf4, + 0xca,0x53,0xce,0x4a,0x63,0x65,0x15,0x2,0x81,0xc8,0xa1,0x4,0x3,0x3a,0xc,0x2, + 0xf0,0x35,0xcc,0xd2,0x4a,0x17,0xaf,0x50,0x23,0x87,0xf6,0x8a,0xd4,0xa1,0xd7,0xc1, + 0xe4,0x1d,0x4f,0x2f,0x1e,0xfb,0x8f,0x53,0xa5,0xb0,0xfe,0x1b,0x26,0x2b,0xb0,0x8c, + 0x9d,0x3a,0x59,0x86,0xfa,0x8f,0x5f,0x93,0x12,0xae,0xb4,0x42,0xa6,0x22,0x10,0x8, + 0x44,0x4e,0xc1,0x53,0x59,0xcb,0xc2,0x7,0x76,0x79,0x4,0xa3,0x90,0xfe,0x13,0xd, + 0x88,0x32,0x85,0x95,0x59,0x29,0x32,0x52,0xe9,0xe2,0x15,0xaa,0xa7,0xbc,0x52,0xc7, + 0xed,0x4,0x84,0xb1,0xa7,0x81,0xe9,0x23,0x4,0x22,0x67,0xd,0x48,0x45,0xa5,0x5e, + 0x34,0x6b,0x9e,0x96,0xe8,0x6e,0x17,0xc9,0x3a,0x9d,0x73,0xe2,0x3f,0x28,0x53,0x3c, + 0x20,0x94,0x8f,0x2a,0x5d,0xbe,0x2e,0x8d,0xca,0x1,0x81,0x40,0x1c,0x7,0xcc,0x34, + 0xe4,0x1d,0x8a,0xe7,0x2d,0x51,0x5,0xd,0xc8,0xb2,0xa3,0xf6,0x81,0x65,0x32,0x20, + 0xab,0xc5,0xc2,0x9e,0x6a,0xea,0xad,0xae,0xc5,0xe8,0x3,0x81,0x40,0x20,0xf2,0x1c, + 0x45,0xcd,0x73,0x74,0xc1,0x47,0xcb,0x0,0xa0,0x11,0x26,0x53,0x59,0x53,0x1a,0x90, + 0xc5,0x42,0x16,0xab,0x79,0x2e,0x9e,0xf7,0xc8,0x69,0x60,0x64,0x88,0x40,0x20,0xc4, + 0xe0,0x29,0x2d,0xd7,0x25,0xaf,0x8f,0x9,0x96,0xf4,0x36,0x1b,0x19,0x90,0x16,0x91, + 0x17,0x2a,0x55,0x75,0x3a,0x2a,0x29,0x4,0x22,0x97,0x80,0xcb,0x11,0x91,0x3d,0xe4, + 0x40,0x9,0xa5,0xe9,0x94,0xc8,0xc1,0xc2,0xf2,0xe3,0x6c,0xc1,0x9,0xff,0xb1,0x54, + 0xc8,0x62,0x95,0x97,0xeb,0x28,0xb0,0x8,0x4,0x2,0xe1,0xe,0x8f,0x41,0xf2,0x78, + 0x45,0xc7,0xb,0x18,0x19,0x90,0x80,0xd0,0xcb,0xbc,0x3e,0xb4,0x1e,0xe8,0x6,0x22, + 0x10,0x8,0x97,0x80,0x10,0xe1,0xd6,0x58,0x92,0x91,0x1,0x91,0x5,0x5f,0xc6,0x50, + 0x59,0x22,0x10,0x98,0xc6,0x45,0xb8,0xc6,0x82,0x8,0x3f,0x69,0x64,0x40,0x84,0x16, + 0x4,0x23,0x84,0xe1,0xe2,0x41,0x20,0x10,0x5,0x9,0xe6,0x4a,0xe7,0x59,0xf4,0x9b, + 0x24,0xcb,0x6,0x24,0x27,0xcb,0x77,0x19,0x46,0x44,0x8,0x4,0x2,0x91,0x5d,0x4, + 0x22,0x9c,0xc2,0xb2,0x1e,0x81,0x0,0x65,0xa8,0xb0,0x11,0x33,0xeb,0x2f,0xe0,0x21, + 0x56,0x4,0x62,0x46,0x4c,0x8d,0x65,0x3,0xc2,0x70,0x1,0x23,0x10,0x8,0x47,0xb5, + 0x16,0x9e,0x5a,0x9e,0x6e,0x9f,0xcc,0xe,0x3,0x42,0xc5,0x5e,0xc5,0x90,0xb1,0x8, + 0x4,0x2,0xe1,0x1a,0xb,0xed,0xe0,0x26,0x3a,0x10,0xc6,0xd0,0x70,0x14,0xac,0xa4, + 0x21,0xdf,0x11,0x88,0x42,0xe,0x6,0x2d,0x1b,0x10,0x9d,0xa1,0x22,0x41,0x20,0xa, + 0x2,0xe8,0x28,0x22,0x6c,0x36,0x20,0x84,0x30,0x86,0x82,0x85,0x40,0x20,0x10,0xee, + 0x80,0x24,0x11,0x7,0xcb,0x78,0xb1,0x0,0xcb,0x61,0x27,0x10,0xa3,0x3d,0x4,0x2, + 0xe1,0x58,0x60,0x31,0xbd,0x11,0x8,0x65,0xc0,0x50,0xa9,0x21,0x10,0xd3,0xbd,0xa6, + 0x31,0xca,0x47,0xe4,0xb6,0xa5,0xc9,0xf2,0x20,0x21,0x45,0xe1,0x36,0x80,0x16,0x4e, + 0x29,0x7a,0x42,0x3b,0x2e,0xd4,0x93,0xbc,0x32,0x3,0x69,0xfa,0x43,0x37,0xe2,0x91, + 0x99,0x24,0x49,0xe,0xbc,0x87,0x30,0x22,0x4b,0x28,0x3,0x8,0x84,0x5d,0x98,0x59, + 0xa7,0xdc,0xc9,0x32,0x5e,0x64,0xaa,0x11,0x82,0x3b,0x86,0xca,0x23,0x87,0xc7,0x4a, + 0x71,0x45,0xd8,0x60,0xa8,0x14,0x99,0x8a,0x1f,0x92,0xb5,0xf2,0x1e,0x89,0x12,0x89, + 0xcc,0xc8,0x37,0x36,0x6c,0x5e,0x38,0xe0,0x29,0xf7,0xe3,0x1d,0x3b,0x88,0x19,0x5c, + 0x68,0xe,0xa6,0xb0,0x8,0xa6,0xb0,0x8c,0x6d,0xe,0x52,0xc6,0x3e,0x5a,0x6a,0xba, + 0x33,0x61,0x4e,0x5a,0x97,0x66,0xec,0x1b,0x29,0xc3,0x88,0x1e,0x91,0x37,0xa6,0xc6, + 0xb2,0x1,0x1,0x60,0xc,0x5,0x1e,0x43,0x34,0x84,0x4d,0xa0,0x94,0x20,0x11,0x66, + 0x7a,0xc5,0x16,0xb8,0x43,0x4c,0x9c,0xad,0xc2,0x22,0xc8,0x54,0x8c,0x41,0x10,0x76, + 0x49,0x8b,0xc4,0x18,0x9e,0xab,0x42,0x14,0x4a,0x4,0xc2,0x18,0x41,0x81,0x37,0xb6, + 0xaf,0xe8,0x51,0x22,0x4c,0xc8,0x8b,0xe,0x84,0xa1,0xd3,0x81,0x28,0x10,0x3,0x2, + 0x8c,0x31,0x14,0x78,0x63,0xfa,0x20,0x11,0x10,0x26,0x42,0xed,0x42,0x55,0x45,0xb8, + 0x4e,0x72,0x86,0x17,0x92,0x73,0x55,0x58,0x8c,0x21,0xf3,0x11,0x8,0x5b,0xfd,0xd, + 0x5c,0x4f,0x88,0x5c,0x9,0x2b,0xa6,0x3d,0x2,0x41,0x59,0x47,0xea,0x20,0xec,0x14, + 0x18,0x86,0xf7,0xeb,0x20,0xf2,0xd1,0xd6,0x64,0x5f,0x85,0x85,0x2,0x8f,0x16,0x4, + 0x61,0x93,0xbc,0x10,0xa7,0x55,0x0,0x4a,0x28,0xe2,0x4,0x99,0x70,0xb4,0xa,0xb, + 0x85,0xd0,0xe,0xb,0x52,0x7a,0x52,0xf5,0x4,0x91,0xe5,0xec,0xe9,0xc8,0x28,0xd0, + 0x34,0xb3,0xfd,0xfc,0x2,0xd3,0x29,0xa1,0xba,0xfd,0xe7,0x22,0x98,0xca,0x24,0x36, + 0xd,0x25,0xab,0x6c,0x1a,0xce,0x70,0x30,0x9d,0x11,0xa6,0x83,0xa5,0x71,0x69,0x5a, + 0x93,0x68,0x5a,0x97,0x45,0xfc,0x31,0x5c,0x4f,0x88,0x3c,0x71,0x69,0xd,0x23,0x10, + 0xc1,0x95,0x81,0xb2,0x6e,0x7,0xbb,0x2a,0x4f,0x6b,0x1e,0x95,0x7d,0xb2,0x8e,0x4, + 0x73,0x27,0x26,0xde,0x19,0xa8,0xe,0xee,0x1c,0xac,0xe5,0xdb,0xf,0x86,0x71,0x2b, + 0x62,0x86,0x23,0x10,0x7b,0x5a,0x99,0x8,0x5f,0x28,0x85,0x2,0x6f,0xb,0xcf,0x90, + 0x86,0x98,0x16,0xc0,0x3d,0x10,0x44,0x4e,0x68,0xa3,0x6c,0x90,0xfd,0x95,0xb6,0x28, + 0xf0,0x36,0x4,0x8c,0x4,0x15,0x7,0x7a,0x75,0x78,0xee,0xd4,0xcd,0xaa,0x80,0xe4, + 0xc9,0x79,0x39,0x92,0xdd,0x93,0xd9,0x45,0x20,0x14,0x99,0xca,0x71,0x28,0x5,0x23, + 0x39,0x89,0xe5,0x8d,0x80,0x21,0xa6,0x6d,0x51,0x32,0x96,0x47,0x8a,0x6,0xe1,0x56, + 0x61,0x75,0x2e,0x85,0xc5,0x8,0x43,0xc5,0x67,0x8b,0xea,0xa0,0x0,0x20,0x21,0xb5, + 0xa6,0xdd,0x63,0x98,0x19,0x17,0x9f,0x88,0x2e,0xca,0xc9,0xb,0x3e,0x71,0x3d,0x21, + 0xf2,0x4e,0xb7,0x65,0x7b,0x12,0x1d,0x5,0x9e,0x13,0x82,0x8,0x5b,0x7d,0xa4,0xa3, + 0x7b,0x57,0x9a,0xa0,0x93,0xc5,0x28,0xd2,0x6a,0x26,0xe9,0x8f,0x0,0x33,0x9b,0xe8, + 0x36,0x94,0xf1,0x52,0x64,0xaa,0x4d,0x12,0xce,0x90,0x1e,0x2e,0x86,0xe8,0x5,0x62, + 0xc,0xd7,0x5,0x62,0xa6,0xed,0x87,0x24,0xfe,0xa8,0x55,0x3,0xc2,0x8,0x43,0xc5, + 0xc7,0x8b,0xd0,0x10,0x48,0xc,0xe1,0xaa,0x46,0xca,0x50,0x68,0x10,0x79,0x63,0x6b, + 0x2c,0x47,0x20,0x93,0x55,0xbc,0x28,0xf0,0x62,0x34,0x36,0x78,0x8c,0x51,0xa4,0xa3, + 0x9b,0xc5,0x40,0x90,0xb5,0xd4,0x45,0xdd,0x9b,0xf1,0xa2,0x39,0x77,0x3b,0x3b,0x36, + 0x5d,0x69,0x8b,0x37,0x12,0xda,0xe0,0x74,0x13,0x46,0x90,0x8e,0xae,0x76,0x23,0x64, + 0xe1,0xee,0xd6,0x28,0x7,0x88,0x99,0x15,0x56,0x7,0xaf,0xb4,0x5,0xc6,0xf0,0xbe, + 0xb,0x3b,0x30,0x9d,0x5,0x58,0x78,0x63,0x64,0xe,0xf0,0x97,0x9,0xde,0xaf,0x83, + 0x57,0xda,0x22,0xf2,0xc8,0x2f,0xb2,0x6c,0x40,0x8,0x5e,0x69,0x6b,0x97,0x96,0x77, + 0x23,0x1d,0xf5,0x84,0x26,0xeb,0x29,0xed,0xb8,0x1e,0x50,0xb2,0x57,0xa6,0x60,0xe3, + 0xbe,0x99,0x24,0x4b,0x8c,0x78,0x25,0x9a,0xeb,0xec,0x15,0x34,0x20,0xd6,0x1d,0x32, + 0x8c,0x60,0x10,0x33,0xe0,0xf6,0x66,0x19,0x81,0xa0,0xc0,0x72,0x34,0x82,0xe8,0x73, + 0xc,0x98,0xe4,0x3a,0x3a,0x6,0x77,0xc,0xd4,0x86,0xf7,0xf,0xd7,0xe7,0xdd,0xca, + 0xf0,0x4e,0x47,0x5f,0x32,0xbe,0x8d,0x1b,0x7f,0xa3,0xb7,0x39,0xf8,0x4e,0x7f,0xa3, + 0xc0,0xd2,0x65,0xc4,0x63,0xef,0x1c,0x25,0xcf,0xf4,0xf7,0x62,0xab,0x39,0xb7,0xa5, + 0xd7,0x5b,0x59,0x9c,0x42,0xc5,0x90,0xc3,0x19,0x6,0xc9,0xc9,0x5e,0x58,0xd8,0x4c, + 0x91,0x6b,0x5f,0x85,0x38,0x21,0xb9,0x33,0x92,0xcb,0xd7,0xa3,0x2d,0x42,0x9d,0x73, + 0xa7,0xe3,0xbd,0x29,0x4d,0xa1,0x2e,0x56,0xaf,0x34,0xa5,0x49,0x98,0xb1,0xc8,0x79, + 0x8b,0x94,0xd5,0x83,0x59,0x97,0xf1,0xa2,0x40,0x38,0xca,0x34,0xfc,0x30,0x44,0x9e, + 0xbb,0xcb,0x98,0xb1,0x70,0x8b,0xdf,0x6b,0x64,0x40,0x84,0x9b,0x29,0xa2,0x40,0x58, + 0x67,0x5,0x23,0x92,0x3b,0xcf,0x20,0x63,0x84,0x8a,0x38,0x3e,0x22,0x75,0x95,0x43, + 0x51,0xe0,0x5d,0xb4,0xed,0xb8,0x91,0x10,0x99,0x6a,0xcb,0x9c,0x5d,0x1a,0xc5,0x61, + 0x6c,0x8a,0x38,0x41,0xab,0x30,0xbc,0xba,0x20,0xe7,0x95,0x91,0x73,0x6,0x84,0x51, + 0x86,0x77,0x59,0xd8,0x11,0xc,0xe2,0xf7,0x23,0xa,0x46,0x22,0x30,0x63,0x91,0xdb, + 0xe,0x38,0x71,0xf2,0x42,0x29,0x14,0x8,0x7b,0x34,0x28,0xd2,0x10,0x81,0x30,0x11, + 0xda,0xe2,0x7a,0x99,0x79,0xa5,0x65,0x47,0x19,0x2f,0x43,0xa6,0xe2,0x82,0x30,0xf8, + 0x2e,0xbc,0xa5,0x17,0x71,0x82,0xbe,0x40,0x3d,0x91,0xe3,0x21,0x88,0x93,0x27,0xd1, + 0x29,0xa,0x84,0x21,0x79,0xa8,0x59,0x36,0xe4,0x95,0xa0,0xf1,0xf9,0xce,0xf0,0x8e, + 0x13,0xc4,0x9,0x91,0x36,0x36,0x5f,0x75,0x4b,0x4,0x62,0x43,0x15,0xd6,0x64,0xff, + 0x69,0x14,0x8,0xab,0xc,0x73,0x29,0xd,0x45,0xab,0x6e,0x4a,0x4f,0xaa,0x1d,0xc8, + 0xd6,0x90,0x32,0xca,0x8,0x53,0x75,0x1b,0x2d,0x15,0x21,0xcc,0xe6,0x73,0x20,0x6a, + 0x2c,0xe5,0x53,0xc7,0x53,0x1,0xde,0x73,0x4a,0xa9,0x37,0x29,0x17,0x2b,0x69,0xa1, + 0x6f,0xd6,0xa8,0xad,0xd6,0x99,0xa6,0xa9,0x92,0x35,0x9f,0x55,0x5d,0xa6,0x69,0x5d, + 0x11,0x60,0x16,0xe4,0xfd,0x35,0xa6,0x8,0x1b,0x23,0x10,0xc6,0x18,0xa,0x84,0x1d, + 0xc6,0x9c,0x16,0xf4,0xf7,0x57,0x9f,0x35,0xbb,0x97,0xc8,0xee,0xdd,0x72,0x8f,0xb5, + 0x87,0xca,0x87,0x9f,0xef,0x58,0xc2,0x35,0xa4,0x4b,0x6a,0x86,0x2a,0xd6,0xd5,0xf, + 0xe5,0xdb,0xf7,0x85,0xf6,0xc,0xd5,0x8e,0xbf,0xd9,0x37,0xcf,0xc5,0xf1,0x76,0xe1, + 0x40,0xdc,0x2d,0x71,0x67,0x19,0x6f,0x6e,0xe9,0x4f,0xfe,0x7a,0x21,0xd9,0x74,0xf0, + 0xce,0x97,0xf6,0x31,0xa2,0xdd,0x88,0xc1,0xdd,0x5d,0x9d,0x9,0xc1,0xd6,0x40,0x93, + 0xdf,0x27,0x61,0xb7,0xe1,0x5c,0x97,0x55,0xf1,0x96,0x4a,0x76,0x44,0x20,0x80,0xbd, + 0xb0,0x2c,0x7b,0xe0,0xcc,0xbd,0x34,0x14,0x16,0x45,0x97,0xcb,0x90,0xe8,0x95,0xb6, + 0x99,0x52,0x7e,0xb9,0x7e,0x4e,0x48,0x98,0x7f,0x3a,0x76,0x1b,0xce,0x79,0x59,0x75, + 0xb2,0x17,0x16,0xb6,0x32,0xb1,0x41,0x81,0x4a,0xee,0xa5,0xa1,0x70,0x41,0xa0,0xcb, + 0x65,0x48,0xb8,0x41,0x9d,0xcb,0xd7,0x13,0x6a,0xa,0x41,0x29,0x98,0x51,0x87,0xca, + 0xb9,0x32,0x5e,0x46,0xb,0xef,0x3e,0x10,0x73,0xcc,0x65,0xf9,0x20,0x30,0x33,0x2b, + 0x89,0xc4,0xbd,0xdf,0x6f,0x7e,0x3d,0xe5,0x27,0x2d,0x98,0xe8,0xf7,0x31,0xc2,0x18, + 0x66,0x2c,0x72,0x3e,0x4,0x71,0x2e,0x2,0x61,0x80,0x2,0x61,0xbc,0x60,0x44,0xa2, + 0x38,0xf7,0x12,0x80,0xa,0x49,0x63,0xae,0x13,0xc0,0xfa,0xfc,0x84,0x53,0x3c,0x2c, + 0x4f,0xfd,0x74,0x53,0x42,0x8c,0xfa,0xc2,0x15,0xf6,0xc3,0x96,0x4d,0x74,0x86,0x2, + 0x61,0xf,0xc7,0x5c,0x9a,0xc2,0xe2,0x7f,0xd6,0xd1,0x1a,0x2,0xdc,0x3,0x1,0xc8, + 0xdb,0x3b,0xd1,0x25,0x57,0xb1,0xa,0x1b,0x10,0x39,0x68,0x40,0x90,0xa9,0x36,0xf0, + 0x82,0xb9,0x55,0x68,0xc5,0x3e,0x4a,0x62,0x6e,0x5f,0xb4,0x44,0x74,0x8f,0x87,0xb1, + 0xfc,0x94,0x75,0x22,0xbe,0xc7,0x83,0xa,0xda,0x9d,0xc8,0x32,0x85,0x45,0xd1,0x62, + 0x3b,0x17,0x32,0xe6,0xa1,0x5,0xa1,0x24,0xeb,0xef,0x67,0xee,0x91,0x2b,0x2,0x92, + 0xf0,0xf5,0x8,0x79,0xfa,0xdd,0x4c,0xf4,0xf3,0xdc,0xc4,0x57,0x77,0x6,0xcb,0x4e, + 0x96,0xf1,0x2,0x61,0x28,0x10,0x36,0x4,0x83,0x6e,0xa5,0xa1,0xd0,0x1e,0x10,0xa0, + 0xc,0x7d,0x28,0x6,0x79,0xea,0x4d,0x88,0x4e,0xdb,0x28,0x10,0x43,0x47,0x34,0xcf, + 0xa2,0x49,0x3b,0x9a,0x29,0x2,0x43,0xc6,0x3b,0xcb,0xb4,0x3c,0xd3,0x88,0xac,0xb0, + 0xbf,0xff,0xc3,0xa5,0x46,0xc4,0x9b,0x93,0x12,0xf7,0x46,0x20,0x68,0x28,0x5c,0xa6, + 0xb5,0x2c,0x1b,0x10,0x91,0x14,0x45,0x41,0xbb,0x94,0x42,0x29,0x1c,0x96,0x43,0x6a, + 0xc0,0xf1,0xb9,0x10,0x52,0x0,0x51,0x2c,0x11,0xbd,0xe1,0x33,0x5f,0xa3,0x51,0x49, + 0xb8,0x6a,0x13,0xa3,0xcd,0x9c,0x17,0x56,0x47,0xaf,0xb4,0x45,0x81,0xb0,0x18,0xdb, + 0x93,0xa3,0x8d,0x3c,0xdc,0x19,0x80,0x88,0xe4,0xb0,0xdc,0x2f,0x3e,0x44,0x3c,0xc5, + 0x33,0x53,0xe,0x99,0x35,0x26,0x10,0x8a,0x55,0x9b,0x68,0x40,0xb2,0x16,0x28,0x14, + 0x8,0x4b,0xa4,0x71,0xf1,0xa2,0x12,0xf9,0xaa,0xc9,0x12,0x57,0x77,0x57,0x61,0x11, + 0x42,0x4d,0x10,0xc,0x4f,0xa2,0x23,0xa6,0x97,0xd,0xf6,0x64,0x3d,0x6c,0x3b,0x7, + 0x82,0xb0,0x81,0x3c,0xac,0x50,0x73,0xc3,0x84,0x30,0xb7,0x7f,0x3b,0x15,0xfc,0x3e, + 0x4a,0xf3,0x55,0xe,0x4,0x7b,0x7d,0x4d,0xc6,0x58,0xa8,0x34,0x72,0x19,0x92,0x83, + 0xe7,0x40,0x58,0x21,0x2b,0x3e,0xbb,0xec,0x87,0x9b,0x15,0x28,0x4a,0xc6,0xd1,0x45, + 0x29,0x78,0xd4,0x6e,0xb2,0xce,0xd5,0xdd,0x9b,0xe8,0x80,0xbd,0xf3,0x5c,0xc2,0x4b, + 0x5b,0xae,0xb4,0x65,0x28,0x10,0x76,0xf0,0xcb,0x9d,0x34,0xa4,0x42,0xfd,0xec,0xc1, + 0xf5,0x32,0x24,0x11,0xa1,0xbb,0x29,0x27,0x6b,0x1a,0xf3,0x33,0x8a,0x44,0x8f,0x42, + 0xc0,0x51,0x74,0xdb,0x17,0xd9,0x60,0x40,0x5c,0x72,0xc,0x6e,0xba,0x98,0x5b,0xe8, + 0xed,0xcc,0x5,0xf6,0x56,0x89,0x9b,0xbf,0xdf,0x2c,0x7f,0x59,0x9e,0xd2,0x42,0xb4, + 0x83,0x30,0xc3,0x2b,0x6d,0xf3,0xc0,0x2c,0xe0,0x95,0xb6,0x79,0x15,0xd,0x8a,0x9f, + 0xfc,0x74,0x67,0x30,0x3c,0x3,0xe9,0x3b,0xc2,0x1c,0x8e,0x78,0x44,0x37,0xd1,0x27, + 0xbb,0xb9,0xbb,0xb7,0x99,0x22,0x83,0x3c,0xfd,0x3e,0x54,0x59,0xd3,0x12,0x81,0x50, + 0x36,0xd9,0xa0,0x19,0xa9,0x9e,0xd1,0xe3,0xca,0x4d,0x85,0xe6,0xd8,0xf7,0xb,0xa5, + 0xb0,0x50,0xa9,0x98,0x5f,0xbc,0xf8,0x81,0xb9,0x90,0x61,0x70,0x23,0x24,0x29,0x4f, + 0x9a,0x29,0x22,0x53,0xb,0x20,0x8a,0x13,0x31,0xa0,0x92,0xeb,0xd3,0x1a,0x44,0x92, + 0x44,0x23,0x7a,0x92,0x8f,0xb4,0x20,0x66,0xf6,0xb0,0x70,0xdd,0xbb,0x72,0x71,0x67, + 0x67,0x40,0x28,0xa6,0xb0,0xac,0x87,0x20,0xee,0xa5,0x9f,0xd0,0x41,0x42,0xe2,0xfe, + 0x42,0xc,0x22,0x51,0xd1,0x2b,0x6d,0x21,0x2f,0x69,0x21,0x61,0xd1,0x8d,0x6b,0x2, + 0x10,0xe7,0xdb,0xb9,0xa3,0x40,0x58,0xb7,0xe3,0x85,0x4b,0x43,0x2,0x5,0xd0,0xd, + 0x47,0xf8,0x3e,0x10,0x97,0xbb,0x53,0x8c,0x4c,0x6e,0xa4,0x23,0x72,0x9a,0x4d,0xe2, + 0xb6,0xc6,0xaa,0x1,0x99,0x3c,0x8,0x82,0x2,0x61,0x81,0x15,0x93,0x55,0xac,0xa4, + 0x70,0x9b,0x29,0x4a,0xc0,0xdc,0x2e,0x43,0x84,0x88,0xb6,0x73,0x7,0x92,0x97,0xb4, + 0x60,0x4,0xf,0x1e,0xbb,0x47,0x58,0x4d,0xb9,0xbe,0x99,0xc,0x88,0xa0,0x2f,0x44, + 0x91,0xe0,0x96,0x97,0xcb,0x34,0x2b,0xc,0x32,0x83,0xd1,0x8d,0x50,0x99,0x37,0x61, + 0x33,0x3a,0x47,0x67,0xc2,0x2c,0x96,0x17,0xfc,0x9a,0x7e,0xaf,0x15,0x5c,0xcf,0xeb, + 0x42,0x89,0x96,0xed,0x39,0x7,0xc2,0x50,0x20,0xac,0x2b,0x17,0x17,0xd3,0x90,0x99, + 0x14,0xc3,0x2,0x37,0x20,0x36,0x8a,0x1,0x73,0x36,0x92,0x11,0xde,0x3,0x61,0x98, + 0xb1,0xc8,0xf5,0x15,0xeb,0x60,0x2b,0x13,0xe6,0xb8,0xa0,0xe6,0x19,0x37,0x58,0x2e, + 0x2e,0xf6,0x1c,0xfb,0x7c,0x52,0x0,0x4a,0x85,0x88,0x6e,0xa2,0x93,0xfc,0xa4,0x5, + 0xde,0xea,0x90,0x3,0x22,0xc6,0x6c,0xe2,0xa4,0xfb,0xee,0x44,0xcf,0xef,0xf0,0x42, + 0xc0,0xe8,0xbb,0x35,0x2,0x11,0x49,0x61,0x11,0xe6,0xfe,0x14,0x96,0x6c,0xe2,0x3e, + 0x90,0x7c,0xa4,0x85,0xe0,0x9d,0xef,0xc,0x0,0x33,0x16,0x2e,0x55,0x6e,0x16,0x6e, + 0x24,0x44,0x81,0x30,0xa,0x2d,0xd0,0x7b,0xe3,0x7c,0xbd,0xab,0x3e,0x3f,0x53,0xf4, + 0x20,0x99,0xd8,0x64,0x26,0x6e,0xbe,0x50,0xa,0xdc,0x5c,0xb6,0xee,0xe,0x11,0x96, + 0x1c,0xbd,0xd2,0x96,0xa1,0x40,0x58,0xb6,0xe3,0xee,0xa5,0xa1,0xe8,0x26,0x3a,0xb8, + 0xfd,0x20,0xa1,0x60,0x4a,0x98,0xe6,0xab,0x39,0xa5,0xc2,0x2,0xe1,0x3a,0xde,0xba, + 0xed,0x32,0x38,0xe2,0x64,0xa,0x2b,0x47,0x9b,0x29,0xe6,0xe,0x53,0x49,0x61,0xa, + 0xe1,0xb1,0xfe,0x85,0xc0,0x53,0x4,0xaf,0xb4,0xfd,0x90,0x5e,0x79,0x49,0xb,0xe1, + 0x73,0x2e,0x4,0x8,0xde,0x60,0xea,0x1e,0xa9,0x36,0x30,0x20,0xee,0x16,0xf8,0xdc, + 0x52,0xa0,0x6e,0xfe,0x7c,0x81,0x3d,0x10,0x62,0x87,0x28,0xe7,0x34,0xa1,0x89,0xe8, + 0x37,0x32,0x46,0x20,0x3f,0xef,0x86,0x11,0xad,0x58,0x67,0x80,0xf7,0x7,0xb9,0x83, + 0x97,0x76,0x5d,0x28,0x85,0x2,0xe1,0x68,0xd8,0xe8,0x3e,0x3,0x5a,0x8,0x4a,0x45, + 0xc2,0x34,0xef,0x51,0x85,0x41,0x6c,0x1a,0x7,0xe9,0x39,0x7d,0xc2,0x6a,0x8b,0x1, + 0x11,0x4,0x45,0xa6,0xda,0xb3,0x1c,0xdc,0x4a,0x3b,0x22,0x24,0xb0,0x85,0x20,0x3b, + 0x4,0x18,0x57,0x81,0x4e,0xde,0x4d,0x99,0x77,0xb4,0x90,0xc4,0x53,0xde,0xc,0xf5, + 0x84,0x3b,0xd7,0x76,0x96,0xcd,0x14,0xd1,0x70,0x18,0xeb,0x3,0x46,0xa,0x40,0x8c, + 0x98,0x95,0x8,0x84,0x60,0x5a,0xe3,0x78,0x72,0xe5,0x23,0x2d,0x88,0x99,0xaa,0x4d, + 0xe4,0x75,0x8e,0x7b,0x3,0xe,0x6e,0xa2,0xe3,0xe2,0xe7,0xae,0x17,0x21,0x86,0xb9, + 0x36,0x85,0xc5,0x4f,0xfe,0x93,0x2,0xe9,0xe6,0x4c,0x8,0x61,0x7c,0x87,0x22,0x2f, + 0xaa,0xb0,0xd8,0x54,0x8a,0x40,0x90,0xa,0xc,0xf0,0x8c,0x59,0x8e,0xdb,0xf,0x27, + 0x5b,0x99,0x50,0x13,0xcf,0x22,0x32,0x70,0x81,0xb8,0x98,0x86,0x42,0x7b,0x20,0x5, + 0x22,0x43,0x84,0xff,0x99,0x2c,0x4f,0x69,0x21,0x7a,0x9,0x51,0x21,0x44,0xe4,0xf9, + 0x2f,0xa7,0x8e,0x5e,0x69,0x8b,0x2,0x61,0x39,0x4,0xc9,0x62,0xd4,0x3c,0xb9,0xc1, + 0x4f,0x2c,0x85,0x27,0x31,0x56,0x8,0x37,0x12,0x8a,0x44,0x99,0x93,0x17,0x7c,0xe6, + 0x1d,0x2d,0x18,0xd3,0x45,0x5b,0xb5,0x14,0x6,0xaf,0xf3,0x3a,0x69,0xc0,0x9c,0xec, + 0x85,0xc5,0x0,0x5,0xc2,0xb2,0x7d,0x75,0xf1,0xa2,0x12,0x6c,0xe5,0x52,0x18,0x8e, + 0x1d,0xf7,0x3b,0x29,0x8f,0x14,0x39,0x9b,0xee,0x23,0x78,0x23,0x61,0x61,0xad,0x59, + 0x7b,0xc,0x8,0x0,0x30,0x14,0x8,0x8b,0xdc,0x20,0x2e,0x5e,0x54,0x62,0x77,0xa2, + 0x17,0x88,0xc,0x11,0x7e,0xa3,0x53,0x4a,0xf2,0xf2,0x4a,0x5b,0x97,0xf5,0xa3,0xc9, + 0xa9,0x10,0x7e,0x26,0x5e,0xea,0x9c,0x1,0x61,0x5,0xd8,0xc8,0xc9,0x14,0x53,0x5, + 0x8f,0xd3,0x30,0x56,0xd8,0xad,0x4c,0xa,0x22,0x85,0xc5,0xc4,0xc4,0x25,0x1f,0x69, + 0xc1,0xcc,0x5c,0x40,0x87,0x19,0x8b,0xdc,0xf6,0x78,0x25,0xd1,0x47,0x6d,0xe9,0x85, + 0x85,0x2,0x81,0xb0,0xe8,0xbc,0xd2,0x1c,0x9f,0x1f,0xb1,0xa9,0x4d,0xb6,0xc4,0x18, + 0xe8,0xdc,0x88,0x2d,0x2f,0xab,0xd2,0x4c,0xdc,0x77,0x42,0x30,0x63,0xe1,0xe,0x5e, + 0xda,0x14,0x81,0x30,0x14,0x8,0x23,0xfa,0x88,0xed,0x1,0xb8,0x95,0x86,0xa2,0x9b, + 0xe8,0x5,0x21,0x43,0x58,0xee,0xe,0x79,0xd3,0x79,0xba,0x90,0x9d,0x62,0x6,0x2e, + 0xad,0xc2,0xca,0x4b,0xa6,0xb2,0x2,0x17,0x58,0xc1,0x56,0x26,0x85,0xb1,0x60,0x99, + 0x80,0x18,0x90,0x7c,0xa4,0x85,0x24,0x7e,0x73,0x1a,0xc3,0x8c,0x45,0xce,0x33,0x33, + 0x2b,0x6f,0x20,0xcb,0x73,0x20,0x14,0x53,0x58,0xc6,0x1a,0xc3,0x99,0x66,0x82,0xb9, + 0x1b,0x81,0xf1,0x2f,0x38,0xcb,0x74,0xff,0x80,0xdb,0xa2,0x12,0xd1,0xef,0x21,0xee, + 0xbd,0xf,0x84,0xba,0x91,0xaf,0xee,0xb3,0x20,0xe,0xdf,0x48,0x88,0x2,0x61,0xe4, + 0x71,0x89,0xd9,0x19,0xd7,0xd2,0x90,0x9,0xde,0x48,0x58,0x10,0x29,0x2c,0x21,0x49, + 0x70,0xb5,0x71,0xb4,0x23,0x5a,0x47,0xe4,0x84,0xd2,0x2,0xdb,0x6e,0x24,0x44,0xc6, + 0x5b,0xd6,0x1a,0x85,0x7c,0x10,0x5d,0xa8,0xbc,0xd5,0x1d,0x92,0x20,0x74,0x90,0x30, + 0x2f,0x69,0x41,0x74,0x13,0xe,0x5,0xea,0x8b,0xfc,0xd7,0x59,0x36,0x19,0x10,0x4c, + 0x5e,0xd9,0xe1,0x81,0xe7,0xe0,0x8a,0xb2,0xaf,0x41,0x26,0x11,0x78,0xa0,0x70,0xba, + 0xf1,0x8a,0xf9,0x12,0x79,0x58,0xc6,0x2b,0x61,0x37,0x5e,0xb7,0x88,0xa9,0x78,0x59, + 0xa4,0x5d,0x65,0xbc,0x28,0x10,0xd6,0x2c,0x2c,0x71,0x2d,0xd,0x85,0xaa,0xb0,0xa, + 0xe6,0x10,0x1a,0x11,0x14,0x86,0x19,0xf1,0x17,0x2c,0xc9,0x1f,0x93,0x98,0xb0,0xbe, + 0x60,0xe8,0x76,0xe6,0xbf,0xa3,0x63,0x57,0x4,0x72,0xd4,0x7e,0xa0,0x40,0x58,0xd2, + 0x7,0x93,0x65,0x48,0x85,0x4b,0x22,0x56,0x18,0xdf,0x2f,0x89,0x55,0x61,0xe5,0x27, + 0x2d,0x88,0xe0,0x9d,0xef,0xa8,0x11,0x72,0xc3,0xb3,0x33,0xe0,0x17,0x23,0x8e,0xee, + 0x81,0x60,0xf,0x3,0xcb,0xa0,0x66,0x19,0x97,0x47,0x82,0x2a,0x54,0x85,0xc6,0x5c, + 0xf9,0xed,0xd9,0x89,0x2,0xc9,0x4b,0x5a,0x98,0x3a,0x89,0x8e,0xbc,0xce,0x6d,0x47, + 0xc7,0x9e,0x3d,0x10,0x2a,0x2c,0x38,0x28,0x10,0x16,0xd,0xac,0xe4,0x4e,0x1a,0x52, + 0x61,0xe7,0xa2,0x40,0x9a,0x29,0x12,0xf1,0x3b,0x76,0xf2,0x4e,0xe9,0x98,0x98,0x33, + 0xc1,0x8c,0x45,0x8e,0xeb,0x2c,0x87,0xab,0xb0,0x50,0x20,0x2c,0xa9,0x46,0xe2,0xd6, + 0x45,0x45,0x84,0x9f,0x63,0x85,0x20,0x43,0x84,0x88,0x56,0x61,0x21,0xd0,0x91,0x98, + 0x59,0x6f,0xc0,0x31,0x3,0x42,0xdd,0x92,0xc2,0x9a,0x36,0xa6,0xa,0xf5,0x12,0x74, + 0xe7,0x39,0x8,0x33,0x11,0x48,0x61,0x9c,0x25,0x62,0x42,0xf,0xe4,0x21,0x2d,0x24, + 0x71,0xa5,0x83,0xe7,0xc6,0x72,0xdf,0xf1,0x63,0xc2,0x6c,0xb7,0x1c,0x81,0x30,0x86, + 0x2,0x61,0xa8,0x10,0xa,0xd7,0xa3,0x14,0x76,0x2e,0x66,0x40,0x7e,0xc8,0xcc,0xa4, + 0xc,0x85,0x22,0x10,0xe2,0xea,0x3d,0x10,0x6,0x4,0x53,0xde,0xb9,0xee,0xe,0x38, + 0x7b,0x12,0x1d,0x5,0xc2,0x92,0xca,0x0,0x0,0x89,0xb9,0x92,0x86,0x82,0x67,0xcb, + 0x24,0x2,0xac,0x20,0x64,0x48,0x28,0x85,0x95,0xa7,0x35,0xcd,0x92,0x7b,0x56,0x23, + 0x82,0x39,0x7e,0x27,0x3a,0x32,0x55,0x8c,0xc6,0x5,0x45,0x7,0x22,0x2c,0x88,0xa4, + 0x40,0xda,0x19,0x88,0x78,0x76,0x8c,0xe4,0x25,0x2d,0x88,0x44,0x4d,0xac,0x7,0x54, + 0xe4,0x2e,0x54,0x6e,0xd9,0x76,0xe3,0x45,0x81,0xe0,0x2b,0x4,0x9e,0x5e,0x71,0xe7, + 0x21,0x42,0x4a,0xc4,0x53,0x58,0x5,0x10,0x81,0x8,0x6e,0xa2,0xe7,0x67,0x99,0xab, + 0xe8,0x9c,0x19,0xc3,0xaa,0xcd,0xdc,0x77,0x6,0x9c,0x3d,0x48,0x88,0x2,0x61,0x43, + 0x60,0xe1,0xca,0x33,0x20,0xa2,0xe1,0x29,0xc3,0x3b,0xd1,0x8f,0x35,0x33,0x79,0xf9, + 0x6d,0x54,0x58,0x24,0x18,0x56,0x6d,0xba,0x24,0x73,0x60,0x47,0x2f,0xac,0xc9,0x63, + 0x20,0x28,0x10,0xd6,0xec,0x7,0x73,0x23,0xd,0x85,0xed,0x87,0x44,0x58,0x61,0xc8, + 0x90,0x24,0x76,0x12,0x3d,0xf,0x69,0xc1,0x48,0x76,0xa7,0x97,0x11,0xb9,0xe9,0xe9, + 0x88,0xa,0xb4,0xf5,0x8,0x4,0x5,0x42,0xc0,0xa3,0x64,0xb9,0x32,0x15,0x47,0x27, + 0x42,0xc5,0xcb,0x1,0xb,0xa3,0x8c,0x57,0x28,0x55,0xc9,0x48,0x9e,0xd2,0x2,0x79, + 0xed,0x1e,0x95,0x65,0x4b,0x4,0x22,0x9e,0x7d,0x40,0x81,0xb0,0xb4,0xae,0x88,0x5b, + 0x17,0x95,0xe8,0x39,0x10,0x22,0xa1,0xfc,0x1c,0xe3,0xca,0xdb,0x37,0x96,0x83,0x91, + 0x8c,0x89,0x32,0x5e,0xbc,0x80,0xce,0x35,0xce,0x80,0x4d,0x17,0x4a,0xa1,0x40,0xe4, + 0xd7,0x62,0x77,0xcc,0x80,0x98,0xd8,0x3,0x61,0x85,0x70,0x12,0x5d,0x64,0xa3,0x20, + 0x5f,0x15,0x2c,0xea,0x80,0x1c,0x90,0x30,0x36,0x93,0xe3,0x64,0xd9,0xb,0xb,0xdb, + 0x6b,0xf2,0x2,0x76,0xb1,0x90,0xd1,0x95,0x8d,0x14,0x45,0x35,0x2b,0x75,0xe5,0xf7, + 0x67,0x43,0x11,0x6,0x24,0x2f,0x69,0x21,0x99,0x89,0x22,0x31,0x63,0xe1,0x16,0x8b, + 0x65,0x4f,0x4,0x82,0x2,0x81,0x98,0x52,0x19,0x8a,0xa5,0x63,0x5c,0x77,0x1d,0x48, + 0xc6,0x8,0x82,0x8,0x6c,0xa2,0x3,0xc9,0xc7,0x8,0x44,0x12,0x9d,0x33,0x3,0xcc, + 0x58,0xe4,0x7e,0xa8,0x2c,0x1a,0x15,0xd8,0x51,0xc6,0x8b,0x39,0x4d,0x5b,0x3c,0x53, + 0x57,0xa6,0xb0,0x84,0xaf,0x39,0xa5,0x85,0x91,0xc2,0x2,0xd1,0x83,0x84,0xf9,0xee, + 0x8c,0x16,0x98,0xbe,0x75,0x99,0x3,0xed,0xf0,0x85,0x52,0x4,0x99,0xca,0xf1,0x28, + 0x5,0x22,0x38,0xe2,0xc2,0x4d,0x74,0x26,0x7a,0xcd,0x29,0x48,0xae,0xfc,0xfe,0xa9, + 0xbd,0x2d,0xfe,0x7a,0xca,0x4b,0x5a,0xc8,0xe2,0x7,0x8f,0x9,0x16,0xdd,0xe4,0xbc, + 0xa7,0x23,0x1a,0x78,0x5a,0x37,0x20,0x28,0x10,0x88,0xcc,0x21,0x88,0x73,0xce,0x45, + 0x3e,0x9c,0x9d,0x10,0xdd,0x27,0x20,0x2e,0xde,0x44,0x67,0x80,0xd7,0x3f,0xe4,0xbe, + 0xfd,0x70,0x30,0x85,0x5,0x28,0x10,0xd6,0x19,0xc6,0xdc,0x79,0x1f,0x86,0x68,0x77, + 0x24,0x9,0x68,0x41,0xc8,0x90,0x68,0x6a,0x40,0x67,0x4,0xe4,0x7c,0x73,0xca,0x66, + 0xa8,0x9b,0x22,0x76,0xc1,0x98,0x6,0x9a,0xda,0xd3,0xca,0x44,0xb0,0xa,0x6b,0x8a, + 0x9c,0x2d,0x32,0xf5,0x38,0x62,0x88,0x58,0x60,0x77,0xb6,0x32,0x11,0x96,0xc3,0x2, + 0xe9,0x8f,0xc4,0x5c,0xdb,0x1e,0x88,0x8,0x6e,0xbc,0x32,0x8a,0xfa,0x21,0xf,0x1c, + 0x9d,0xac,0x9e,0xcc,0xb2,0x95,0x9,0xa,0x4,0x9f,0x40,0x6e,0xff,0xc4,0xa9,0x15, + 0x23,0x15,0xaf,0xf0,0x66,0xac,0x20,0xce,0x11,0x88,0xad,0x13,0x8d,0x32,0x90,0xe5, + 0xfc,0xa2,0x7,0x5,0xca,0x44,0x9f,0x64,0x78,0x66,0xc4,0x2d,0x5a,0xcb,0x8e,0x4d, + 0x74,0x14,0x8,0xeb,0xf6,0x9c,0xb9,0x54,0x81,0xa,0xee,0x81,0x48,0x85,0xd2,0x4c, + 0x51,0xbc,0x33,0x5a,0x8e,0x7,0xd5,0x6c,0x2a,0x2f,0x42,0xec,0xb7,0x12,0x3a,0x9c, + 0x39,0x6f,0x3e,0x88,0xd3,0x27,0xd1,0x51,0x20,0x1c,0x64,0x5a,0xfe,0x40,0x17,0xd5, + 0x83,0x52,0x61,0xb4,0x73,0x17,0x6d,0x59,0xab,0xe7,0xa3,0x3c,0x48,0xb8,0x86,0xdd, + 0x2,0x9,0x1c,0x6d,0xa6,0x88,0xb0,0xae,0x5a,0x98,0x85,0x9f,0xe6,0x30,0x9f,0x74, + 0xd1,0x6f,0x28,0x8c,0x4d,0x74,0xe1,0x85,0x49,0xf3,0xae,0x30,0x85,0x8,0xcf,0x97, + 0x62,0xd1,0x4d,0x1e,0x30,0xd3,0xb9,0x8,0x84,0x31,0x14,0x8,0x7b,0x6c,0x88,0xeb, + 0x68,0x48,0x41,0xf4,0x24,0x7a,0xc1,0x44,0xb0,0xa2,0xb7,0x7c,0x12,0x1b,0x16,0xb7, + 0xd3,0xc6,0x51,0x7c,0xc7,0xb,0xcb,0xfe,0xdd,0x21,0xa7,0x36,0xa5,0xb0,0x8,0xa, + 0x44,0x46,0xe3,0x2a,0xb8,0x7,0xe0,0xd6,0x6e,0xbc,0x26,0x4,0xb6,0x20,0x64,0x48, + 0xf0,0x1b,0x49,0x3e,0xd2,0x3,0x6f,0x75,0x98,0x26,0xbf,0xd2,0x71,0x39,0x20,0x36, + 0x45,0x20,0x66,0xae,0xb4,0x45,0xc6,0x4e,0x69,0x3f,0x44,0xcf,0x62,0xb2,0x19,0x11, + 0x94,0xe9,0x37,0xa0,0xc2,0xe7,0x91,0x18,0x29,0x84,0x76,0x38,0x82,0x51,0x26,0xd5, + 0x28,0x51,0xf2,0x8c,0x1e,0x92,0xe0,0x26,0x3a,0x65,0x0,0x4,0x5b,0x1f,0xb9,0x46, + 0xa2,0x2d,0x47,0x20,0xc,0x5,0xc2,0xba,0x7,0xee,0xd6,0xfb,0x30,0x84,0x6f,0x24, + 0xcc,0x7,0xf9,0xb1,0x21,0x22,0x10,0x6f,0x52,0x7,0x79,0xd7,0xa0,0xd4,0xcd,0xdf, + 0x56,0x78,0x70,0x32,0x85,0xc5,0x50,0x20,0x32,0xd3,0x86,0x88,0x33,0xac,0x70,0x69, + 0x48,0x40,0x2a,0x88,0x76,0xee,0x92,0x68,0x8f,0xa1,0x7c,0xbc,0x21,0x41,0x12,0x9c, + 0x34,0xcd,0x93,0x66,0x91,0xac,0x80,0x8b,0x88,0x88,0x2c,0xec,0xfa,0x59,0x37,0x20, + 0x4e,0x36,0x53,0xcc,0x33,0xa6,0x12,0xe1,0x52,0x4c,0xe6,0x4e,0x81,0xa5,0x82,0xb2, + 0x41,0x18,0x2b,0x90,0x5,0x2b,0xd8,0xdd,0x41,0xca,0x3f,0x79,0x60,0xb2,0xf8,0xfe, + 0xe,0xc3,0xa,0x4f,0xd7,0xf8,0x7e,0x36,0x18,0x10,0x40,0x81,0xc8,0x68,0xef,0x4, + 0x8d,0xab,0x4b,0xbd,0x6f,0xe1,0xaf,0xca,0x90,0xc2,0x23,0xae,0x93,0x2b,0xc1,0x2a, + 0x2c,0xd,0x80,0x78,0xf3,0xec,0xdb,0x4d,0xa4,0x21,0x9,0xea,0x8b,0xdc,0x8e,0x26, + 0x9d,0x4e,0x61,0xa1,0x40,0x64,0x58,0x52,0xac,0xa0,0x69,0xc8,0x98,0xd8,0x49,0x74, + 0x22,0x4d,0x5e,0xa3,0x84,0xb,0xf3,0x43,0xc2,0xe5,0xdf,0xa9,0x3c,0x22,0x5c,0xa2, + 0xcc,0xff,0x7c,0xd4,0x27,0x33,0xcc,0x4b,0x7b,0x2e,0x94,0x32,0x51,0x42,0x83,0xc, + 0x9f,0x7a,0xad,0x10,0xe1,0xfb,0x30,0xdc,0x48,0x43,0x2a,0x7e,0x21,0x0,0x2d,0xc, + 0x19,0x12,0x93,0x7,0x46,0xf3,0x4f,0x89,0x32,0x49,0x3c,0x8a,0x46,0x7d,0xe1,0x1e, + 0x81,0xb6,0x21,0x2,0x41,0x18,0x99,0x72,0x41,0xbd,0x92,0x7b,0xb4,0xb6,0xa3,0xb2, + 0x4e,0xb8,0x9b,0x22,0x63,0x85,0x71,0xab,0xa5,0x98,0x67,0x47,0x19,0xcd,0xbf,0x5b, + 0x3e,0xcd,0x44,0xdb,0x58,0xb5,0x99,0xe3,0xbc,0x74,0xb4,0x17,0x16,0x45,0x81,0xc8, + 0x48,0x1a,0x9d,0xd9,0xbf,0x0,0xf3,0xd7,0x43,0xc9,0x1c,0x80,0x15,0x48,0x5,0x9a, + 0xa8,0xa3,0x40,0x67,0xe2,0x96,0x78,0x8b,0x3c,0x20,0x62,0x65,0x58,0x93,0x67,0x6b, + 0xb1,0x6a,0x33,0xa7,0xc5,0x54,0x72,0xf4,0x4e,0x74,0x40,0x81,0x30,0xa4,0x8d,0x10, + 0x1b,0xdc,0x59,0xc6,0x2b,0x9a,0xc0,0x23,0xa4,0x20,0xca,0x78,0xc5,0xcf,0xfb,0xb8, + 0xba,0x34,0x1e,0x8f,0xac,0xe7,0x7a,0xe4,0xc8,0x1c,0x6c,0xa6,0x28,0x5e,0x69,0x84, + 0x30,0xe2,0xa2,0x2b,0xa3,0x11,0x4c,0x61,0x9d,0xe8,0xe4,0x8b,0x11,0x44,0xcb,0x3f, + 0x19,0x10,0x6e,0xa6,0xc8,0x30,0x63,0x91,0xf3,0x90,0x1c,0x6f,0xe7,0x8e,0x2,0x31, + 0xb5,0x2,0xb5,0xe8,0x9,0xe4,0xfd,0xf7,0x8b,0xa6,0x62,0xa4,0x82,0x90,0x1f,0x62, + 0x22,0xaa,0xc8,0xbb,0x6,0x93,0x26,0x4e,0xa2,0x13,0xec,0x9d,0xe7,0x92,0xdc,0x81, + 0x3d,0x29,0x2c,0x82,0x2,0x91,0xd1,0xe3,0x14,0xae,0xc2,0x2a,0x68,0x1a,0x4a,0x8c, + 0x16,0xc8,0xf7,0xb,0xee,0x81,0x60,0x54,0x8f,0x7a,0x61,0x66,0xc3,0x49,0x67,0x23, + 0x10,0x64,0xac,0xd5,0x10,0x84,0xb9,0xb3,0x9d,0xbb,0x89,0x3b,0xd1,0xb,0xe0,0x4a, + 0x0,0x22,0xb9,0xf7,0xce,0xc,0x89,0x48,0x74,0xe6,0xd6,0x19,0x62,0x86,0x22,0x65, + 0x9b,0xc,0x8,0xa,0x84,0x35,0xfb,0xe1,0x56,0xe7,0x5b,0xb8,0x9d,0xfd,0xc,0x11, + 0xc0,0xf1,0x5b,0xff,0x24,0xc1,0x32,0x5e,0xc8,0xbf,0x1b,0x9,0xa9,0x89,0xe7,0xf0, + 0x6,0xd3,0x5c,0xb7,0x20,0x59,0xf1,0x27,0xfb,0xb,0xa5,0x50,0x20,0x32,0x2c,0x16, + 0xb1,0x3,0xc5,0x84,0x11,0x77,0x5e,0xe9,0x2a,0xbc,0x87,0x4e,0x68,0x61,0xc8,0x90, + 0xa0,0xa3,0xa5,0xe7,0xe1,0x49,0x74,0x39,0x1f,0x9c,0x48,0xa,0x8,0x11,0x85,0x44, + 0x1c,0x6c,0xa6,0x68,0xb9,0x2c,0xcf,0xcd,0x4c,0x15,0xbd,0xd2,0x15,0x98,0x4b,0xe9, + 0x20,0xde,0xca,0xa4,0x10,0x16,0xb7,0xa9,0x48,0x2b,0xdf,0xe8,0x21,0xee,0x2d,0xa0, + 0x22,0x77,0xe7,0xfa,0xb6,0xb0,0x7,0x82,0x2,0x91,0x79,0xb1,0x14,0x72,0x4,0x46, + 0x85,0xab,0xb0,0x28,0xc3,0x4d,0xf4,0xf,0xc9,0xa6,0x53,0x92,0x6f,0xf4,0x60,0x4c, + 0xfc,0x20,0x21,0xc5,0x8c,0x45,0xae,0x47,0x20,0xe,0xee,0x81,0x50,0x46,0x50,0x20, + 0x32,0x2c,0x16,0x2a,0x89,0x9e,0xa5,0x71,0xa5,0x2,0x65,0xe2,0xcd,0x88,0xf1,0x4e, + 0xf4,0x13,0x56,0xb0,0x4b,0x83,0x4d,0x98,0xbc,0xff,0x1,0xf7,0x4c,0x73,0xdb,0x7e, + 0x38,0xd8,0x4c,0x91,0x2,0xa0,0x40,0x64,0xd6,0xa0,0xc2,0x16,0xdf,0x95,0x34,0x64, + 0xba,0x60,0x2f,0x30,0xa0,0x5,0x21,0x43,0x92,0x68,0xa5,0x92,0x9e,0x7f,0x6b,0x4a, + 0xa6,0x98,0x86,0x28,0x40,0x5b,0x63,0x3d,0x2,0x1,0x8a,0x35,0xeb,0x86,0xe6,0x55, + 0x40,0xaf,0x38,0xd5,0xdd,0xc1,0xe9,0xb3,0x16,0xc2,0x11,0x8,0x30,0x20,0xb8,0x89, + 0x7e,0xdc,0x92,0xca,0x33,0x7a,0x98,0x3a,0xc7,0x83,0xe7,0xc6,0x72,0x9d,0x9b,0x4e, + 0x97,0xf1,0xa2,0x40,0x64,0x6f,0x3e,0x8e,0x2a,0x16,0x57,0xd2,0x50,0xd0,0xb9,0x28, + 0x14,0xf9,0x91,0x9c,0x2a,0x4c,0xf9,0x50,0xac,0x9c,0xa3,0xab,0x68,0xa,0x96,0x1, + 0x76,0xae,0xc8,0x7d,0x6f,0xc0,0xd1,0x2b,0x6d,0x51,0x20,0xac,0x2e,0xaa,0xc9,0x6d, + 0x90,0x82,0x2d,0xe3,0x95,0x80,0xd0,0x42,0x90,0x21,0x89,0x9,0xb6,0x73,0xd7,0xf3, + 0xb1,0x5f,0x14,0xc1,0x8c,0x45,0x6e,0x28,0x7f,0x66,0xc3,0x18,0xe,0x76,0xe3,0xc5, + 0x66,0x8a,0x46,0x1e,0xa0,0xf8,0x95,0xb6,0x2e,0xf4,0xc2,0xa9,0x68,0x2f,0x2c,0x2, + 0xb4,0x20,0xa2,0x10,0xd1,0x93,0xe8,0xc,0x48,0xde,0xd1,0x43,0xb8,0x55,0x3d,0x66, + 0x2c,0xdc,0x64,0xae,0x6c,0x30,0x20,0x28,0x10,0x96,0x23,0x10,0xd7,0x9a,0x60,0xd1, + 0x56,0x60,0xee,0x6a,0xa6,0x48,0x32,0x46,0xf,0x82,0x9e,0x1d,0x33,0x1a,0x23,0xcf, + 0xd,0x8,0x21,0x8c,0x60,0xc6,0x22,0xc7,0x83,0x18,0x7b,0xf6,0x40,0x44,0x85,0x9d, + 0xa0,0x40,0x64,0x74,0xc1,0x45,0x23,0x15,0x77,0x2e,0x2a,0xd1,0x8,0x8c,0xe8,0x5, + 0xa2,0x54,0x88,0x6b,0x9b,0x29,0xa,0xf7,0x4f,0x62,0x6e,0x74,0x97,0x5c,0xe6,0x40, + 0x8b,0xf7,0x35,0xb3,0x25,0x85,0x85,0xcc,0xb5,0xbe,0xfa,0xdc,0x79,0xa1,0x14,0x15, + 0xfd,0x7c,0xb9,0x30,0x2e,0x94,0x92,0xc0,0xc4,0xc2,0xcc,0xb7,0x14,0x16,0x5e,0x96, + 0x55,0x88,0xc1,0x8a,0xd,0x6,0x4,0x50,0x20,0x1c,0x5b,0x7c,0xf9,0x2d,0x60,0x6, + 0xe2,0x63,0xdb,0xf7,0xd3,0x9c,0x4e,0xa7,0xa,0x1e,0x2c,0xa5,0xb9,0xfe,0x1d,0x53, + 0xd1,0x1d,0x84,0x1b,0x45,0x52,0x4c,0x79,0xe7,0xf8,0xaa,0x75,0xf6,0x4a,0x5b,0x82, + 0x2,0x61,0xc9,0x1,0x7,0x0,0xc6,0xdc,0x48,0x43,0x2a,0x5a,0x60,0x21,0xc9,0x94, + 0xe2,0x26,0xfa,0x31,0x4b,0xa,0xb,0x53,0x4c,0x2c,0x1d,0xd4,0x3d,0xb6,0xdb,0xf, + 0x53,0x6b,0x91,0x7c,0x60,0x2b,0xec,0xbb,0xf,0x4,0x99,0x7a,0xd4,0xb1,0x26,0x85, + 0x7d,0xab,0xa3,0x78,0x11,0x33,0xc5,0x2b,0x6d,0x8f,0x73,0xd3,0x49,0xbe,0xd1,0x43, + 0x96,0x4c,0xf9,0x4b,0xa8,0x1f,0xdc,0x95,0x65,0xc8,0xde,0x80,0x30,0x60,0x28,0x10, + 0x19,0x53,0x11,0xba,0x78,0x19,0xaf,0x1b,0x3d,0x17,0x2a,0x58,0x98,0x23,0x43,0x41, + 0xdc,0xc8,0x38,0xb9,0xd7,0x23,0x64,0x40,0xf2,0xee,0xda,0x57,0x46,0x64,0xbc,0xc1, + 0xd4,0x35,0x82,0x2a,0x99,0x8d,0x40,0x60,0x2a,0x3,0x42,0x51,0x20,0xac,0x2a,0xc, + 0xf1,0x83,0x84,0xee,0xa4,0x21,0x29,0x28,0x3,0x2a,0xe2,0x7a,0x8b,0x2e,0xa9,0x3c, + 0xf9,0x1c,0x76,0x8c,0xb7,0x24,0x18,0x81,0x50,0x74,0x38,0x73,0x3f,0x73,0x60,0xa6, + 0xaf,0x59,0x46,0x3,0x22,0x7e,0x90,0x10,0x5,0x22,0xc3,0x5a,0x11,0xbe,0x23,0xc1, + 0xa5,0x27,0xd1,0x45,0x5b,0x99,0xd0,0x2,0x49,0x61,0x89,0x9e,0x3,0x41,0x25,0x8b, + 0x98,0x41,0x98,0xbb,0xce,0xcc,0xaa,0x1,0x41,0xd8,0xc5,0x89,0xac,0xfd,0x85,0xdc, + 0xf5,0x64,0x4,0x45,0x50,0xa6,0x85,0x20,0x6f,0x44,0xb4,0x17,0x16,0xfd,0xdf,0xbc, + 0x72,0xfe,0xd8,0x46,0x53,0x51,0x24,0xea,0x96,0x9c,0xe6,0xa5,0x64,0x26,0x2,0x91, + 0xec,0x30,0x20,0x28,0x10,0xd6,0x58,0xc6,0xdc,0x48,0x43,0xe1,0x6a,0x22,0xa9,0x30, + 0xbc,0x6d,0xf1,0xab,0xf8,0x38,0x74,0xcb,0xc5,0xfb,0x53,0x8,0x13,0xef,0x9d,0x47, + 0x30,0xba,0xca,0x6d,0xbf,0x97,0x38,0x98,0xc2,0x62,0xc,0x5,0x22,0x23,0x4,0xaf, + 0xb4,0x95,0x80,0xb9,0x94,0x86,0x62,0x57,0xda,0x12,0x89,0x16,0x84,0xc,0x9,0x2e, + 0x4c,0x46,0x29,0xc9,0x3b,0x7a,0x48,0x12,0xea,0x80,0x69,0xb3,0xcd,0x4e,0xef,0x11, + 0x12,0x5b,0x36,0xd1,0x51,0x20,0xac,0x32,0x95,0x49,0xa2,0xad,0x2b,0x18,0x61,0x85, + 0x7b,0x12,0x5d,0x22,0x8c,0x92,0x42,0xb8,0xd5,0x52,0x74,0x5f,0x83,0x4a,0x40,0xf2, + 0xee,0x4a,0x5b,0xe1,0x83,0xe8,0x84,0xe0,0xd,0xa6,0x39,0xae,0xdc,0xa6,0xdd,0x80, + 0x48,0x0,0x50,0x32,0x99,0xfb,0xa2,0x7e,0x4f,0xbc,0x3d,0xd8,0x28,0xf2,0x26,0xb9, + 0xc8,0x93,0x30,0xfb,0x2d,0x72,0xb1,0x27,0x45,0x24,0x73,0x2,0x27,0x17,0x29,0x69, + 0xa2,0x48,0xfa,0x8c,0x33,0x42,0xb4,0xa7,0x91,0x5b,0xbd,0x37,0xe1,0x5e,0x58,0x72, + 0x1e,0xb4,0x9b,0xb1,0x21,0x22,0x10,0x8c,0x40,0xf4,0x64,0x3a,0x90,0x1c,0x8c,0x54, + 0xe4,0x1a,0x9,0x94,0x12,0x6f,0xd2,0x6,0xa7,0x42,0xd6,0xa2,0x29,0xff,0x74,0xce, + 0x53,0xf6,0xcb,0x2a,0xf1,0xc8,0x1a,0x5a,0x82,0x6c,0xed,0x7,0x99,0xee,0x32,0x5e, + 0x2f,0x1,0x38,0xc3,0xb,0x0,0x40,0x55,0xa8,0x1a,0x7e,0xbe,0xf3,0xb,0x79,0x4f, + 0x34,0x9,0x54,0x20,0x92,0x66,0xee,0x37,0x4c,0x7,0x59,0x56,0xd,0xc,0x88,0xe0, + 0x2e,0x3a,0x2b,0xe8,0x14,0x16,0x10,0x5a,0x18,0x29,0x2c,0xc1,0x85,0x19,0x6b,0xf, + 0x5e,0x10,0x6b,0xf,0x5e,0xe0,0x46,0x12,0xa4,0x46,0xe2,0x2b,0x7b,0xee,0x3b,0xb0, + 0x12,0xd5,0x34,0x0,0x10,0x42,0x89,0x44,0x52,0x39,0xe8,0xf9,0x11,0x80,0xf3,0x7c, + 0xc7,0xff,0xdb,0x5b,0x69,0x80,0x18,0xb3,0x29,0x2,0x71,0xa1,0xb3,0x4c,0xc1,0x3, + 0x40,0x3d,0xa6,0x7e,0xa3,0x3,0x80,0x6a,0x83,0xa3,0xc3,0x80,0x51,0xe6,0xc6,0xfb, + 0x40,0x44,0x3f,0x5f,0x72,0xe5,0xf7,0x4f,0xe9,0x7f,0x23,0x10,0xff,0xeb,0x37,0x4a, + 0x4c,0x67,0x45,0xb9,0x39,0x39,0x8f,0xa8,0x2f,0x98,0xb1,0xa,0xcb,0xb2,0x63,0x89, + 0x28,0x74,0x72,0x52,0x9b,0x9a,0x29,0x32,0xb7,0x9c,0xd4,0x47,0x3,0x32,0x59,0x86, + 0x85,0x64,0x70,0xa1,0xf6,0xc2,0x4d,0xf4,0x99,0xe3,0x1,0x73,0x8b,0x92,0xcc,0x4a, + 0x82,0x64,0x89,0xba,0xf2,0xfb,0x3f,0xea,0xab,0xe1,0x9a,0x42,0xe3,0xe1,0x5a,0xa0, + 0x1,0x99,0xb9,0x35,0xe5,0xce,0x2a,0x2c,0xc1,0x96,0x1c,0x84,0x41,0x81,0x54,0x61, + 0x49,0x18,0x81,0x20,0x30,0x2,0x41,0x2f,0xa2,0xa0,0x82,0xa3,0xec,0x15,0xbb,0x60, + 0x2b,0x13,0x89,0xb0,0xc2,0xd8,0x44,0x97,0x19,0x1a,0x10,0x44,0xc1,0x18,0x10,0x14, + 0x76,0xe7,0x40,0xb,0xba,0xa,0x4b,0xc6,0x66,0x8a,0x8,0x4,0x46,0x20,0x88,0xac, + 0x35,0xb,0xb8,0xb1,0x1b,0xaf,0x70,0x2f,0x2c,0x89,0x42,0x21,0xb4,0x73,0x97,0x64, + 0x74,0xca,0x70,0x13,0x1d,0xd,0x8,0x62,0x9a,0x35,0xad,0x5b,0x3a,0xb1,0xa,0x1e, + 0x24,0x24,0x52,0x61,0x5c,0x28,0x25,0x89,0xb7,0x67,0x2e,0x4,0x7d,0x83,0x70,0x8b, + 0x58,0x9b,0x37,0x20,0x2a,0x0,0x74,0x6a,0x47,0x57,0xbf,0x56,0x34,0x6b,0xc5,0x9b, + 0x42,0xfa,0x44,0xa5,0xa6,0x6b,0x9e,0xa9,0x46,0xfd,0xc2,0xe5,0xa0,0x1f,0xbe,0x7, + 0x7c,0x0,0xcc,0x54,0x2b,0x5c,0x4a,0x99,0x17,0x74,0xa6,0x98,0x9a,0x1c,0x63,0xa, + 0xd3,0x99,0xc7,0x32,0x7,0xbc,0x72,0xdc,0x8d,0xa,0x94,0x31,0x61,0x6d,0x51,0x10, + 0xce,0x8a,0x52,0x5d,0x34,0x11,0x58,0x50,0xf1,0xcc,0xf1,0x82,0xc7,0x14,0xaa,0x59, + 0x97,0x21,0xcb,0xbc,0xd2,0x99,0x2,0xd4,0xda,0x3c,0x92,0x43,0x91,0xf5,0xc0,0x8c, + 0xd7,0x9d,0xe4,0x95,0xc7,0xbd,0x55,0xc5,0xad,0x19,0xd7,0xa1,0x4e,0x3d,0xc0,0xa8, + 0x92,0x3,0xf4,0xf0,0x2,0x5,0x79,0xa6,0xe7,0x41,0x35,0xe6,0xe3,0xd1,0x74,0x3a, + 0xa0,0xc7,0xc7,0x9a,0x4e,0xf8,0x17,0x3b,0x23,0x90,0x34,0x3,0x38,0xa4,0x4d,0xda, + 0xf,0x25,0xd9,0x70,0xc9,0x15,0x4f,0xa3,0x21,0x46,0x64,0xeb,0x6e,0x12,0x49,0xa2, + 0xa4,0x0,0x2e,0x95,0xf2,0xd7,0x96,0x84,0xfc,0xe7,0x97,0xbc,0xe8,0xd6,0xef,0xeb, + 0xfc,0xcd,0xce,0xb5,0x8c,0x19,0xdf,0x61,0xa0,0x94,0x78,0xfa,0x1a,0x2f,0x5f,0xf4, + 0x30,0x26,0x1d,0x72,0xdb,0x61,0xec,0xf8,0xf5,0x7f,0x7e,0x5b,0x70,0xfd,0x5a,0xbe, + 0x50,0xa,0x99,0x8a,0xc8,0x40,0x4f,0xc1,0x8c,0x4d,0xa1,0x5c,0x28,0xe5,0x7e,0x86, + 0x8b,0xe9,0x1b,0xe4,0x75,0x1e,0xb8,0x7e,0x84,0x9,0xa6,0xa0,0xad,0x5f,0x69,0x8b, + 0x2,0x81,0x98,0x5a,0x36,0x4,0xcf,0x81,0x48,0xa,0x9d,0xb1,0x45,0x82,0xb0,0x93, + 0xa0,0x8c,0x6f,0x44,0x18,0xd2,0xdd,0xa5,0x59,0x86,0x6c,0x37,0xd1,0x9,0xa,0x4, + 0x22,0xa3,0x73,0x21,0x0,0x49,0x6,0x8a,0x32,0x54,0x30,0x6,0x64,0xc6,0x77,0xd1, + 0x9,0xca,0x9a,0x5d,0xe1,0xa4,0x1d,0x6,0x84,0x21,0x53,0x11,0x96,0x94,0x5,0x91, + 0x14,0x8a,0xfc,0x2f,0x14,0x9d,0x43,0x18,0xf2,0xda,0x2d,0xce,0xc0,0xa4,0xff,0x67, + 0x39,0x2,0x41,0x81,0x40,0xf0,0xbc,0x13,0x63,0x11,0xa4,0x14,0x8,0xde,0x68,0x57, + 0x30,0x36,0x6,0x6f,0x30,0x75,0xe5,0x1a,0xcf,0xfe,0x1c,0x8,0xa,0x4,0x62,0x2a, + 0x50,0xc1,0x2a,0x2c,0x59,0x66,0x78,0xec,0xc8,0x15,0xaa,0x44,0x80,0x89,0xc,0x53, + 0xde,0xf9,0xc0,0x4a,0xf1,0x9d,0x6d,0x6b,0x6,0x84,0x31,0xdc,0x3,0x41,0x58,0xb, + 0x40,0x40,0x2,0x8a,0x7,0xcc,0x10,0x8,0x77,0x45,0x20,0xa2,0xd7,0x1,0xe1,0xca, + 0xcf,0xab,0xa8,0x80,0x3a,0x66,0xec,0x29,0x13,0x39,0x0,0xca,0x98,0x93,0x73,0x42, + 0x4c,0x2b,0xc4,0xea,0x78,0x91,0xdf,0x6e,0xe1,0xa5,0xf5,0x8,0xc4,0x69,0xa5,0x84, + 0x70,0x59,0x8,0x82,0x7b,0x1f,0xd3,0xcb,0x0,0x67,0xe9,0xcb,0x7d,0x17,0x63,0xcc, + 0xe9,0x39,0x21,0xb2,0x93,0x1c,0xc7,0xc,0x8,0x41,0x81,0x40,0x64,0x1f,0x9d,0x32, + 0x86,0xf2,0xe3,0x26,0x7f,0x81,0x9,0x3c,0x83,0x98,0x3e,0x16,0xd8,0xe4,0xcc,0x13, + 0x61,0xfd,0x6f,0xb9,0xa,0xb,0xe1,0x14,0x53,0xf3,0x2f,0x8,0x26,0x22,0xc4,0x29, + 0x58,0xfa,0xb8,0x91,0xe3,0x22,0xaa,0x9,0xf9,0xed,0xca,0x2c,0x43,0x76,0x6,0x84, + 0x31,0x14,0x8,0x44,0xd6,0x6,0x84,0x10,0xf7,0x3a,0x2a,0x94,0x15,0x5c,0x71,0x9, + 0x43,0xba,0x14,0x16,0x2f,0xc1,0x8e,0x3d,0x10,0x14,0x8,0x44,0x46,0xe7,0x42,0xe0, + 0x29,0x94,0x1f,0xb7,0xf8,0xa2,0x2,0x6c,0x74,0x75,0x43,0x7b,0x57,0x7d,0x9c,0x73, + 0x7b,0x20,0xc8,0x54,0x44,0x6,0x9,0x24,0x62,0x8f,0x21,0x8f,0xdc,0x63,0x41,0x18, + 0xae,0x49,0x77,0xf0,0xd2,0xf4,0x83,0x16,0xae,0xb4,0x45,0x81,0x40,0x4c,0x69,0x1a, + 0x4,0xaa,0xb0,0x6c,0x4e,0x61,0x51,0x8c,0x66,0x72,0x5c,0x28,0x8,0xf2,0x8,0x23, + 0x90,0x29,0xec,0x7,0xa,0x5,0x62,0xa,0x65,0x21,0xe2,0xb5,0xa2,0x42,0x29,0x34, + 0xaf,0xd5,0xfe,0x37,0x63,0x37,0xc,0xbb,0x59,0xe9,0x60,0x15,0x96,0x4e,0x1,0x64, + 0x19,0x99,0x8a,0x38,0xd1,0xb1,0x10,0xd1,0x28,0x14,0xe5,0xa4,0x90,0xbc,0x56,0x46, + 0x90,0xdf,0x18,0x81,0x1c,0xc5,0x42,0x5,0x40,0x82,0xa1,0xad,0xed,0x97,0xdb,0x7e, + 0x20,0x4c,0x2,0xd,0x64,0xa2,0x4e,0x17,0x75,0x24,0x9f,0x12,0x9f,0xb6,0xb1,0x65, + 0x49,0x23,0x8a,0x94,0x9e,0xd6,0xb9,0x4b,0xd3,0x93,0x36,0x94,0x65,0x59,0x23,0x9e, + 0x6c,0xe7,0x7e,0x7c,0x24,0x41,0x29,0x2b,0x12,0x10,0x3f,0x86,0xad,0x70,0x5c,0xa3, + 0x73,0xf8,0x7c,0x64,0x4,0xef,0x3,0x99,0x8a,0x2c,0x69,0xaa,0x68,0x9,0xcd,0x6b, + 0xc7,0x58,0x5a,0x42,0xf7,0x32,0x35,0x6d,0xed,0x5a,0x60,0x56,0x2c,0x3,0xa8,0x4, + 0x20,0x21,0x7c,0xb0,0x27,0xb,0x3,0x32,0x5b,0x1,0x50,0x20,0xde,0x17,0xbd,0x10, + 0x45,0x0,0x61,0x87,0xd1,0x41,0xe4,0x95,0xbd,0x30,0xcd,0x3b,0x2d,0x96,0x9e,0xdb, + 0xf5,0xfb,0xbd,0xff,0x68,0xfe,0x55,0x54,0x1,0x6,0xb6,0x28,0x58,0xa6,0x33,0x1f, + 0x30,0x26,0xdb,0x22,0xbc,0xba,0x80,0x93,0x94,0x97,0x38,0xed,0xe8,0xff,0x7d,0x3e, + 0xc9,0x31,0x5,0x19,0xd,0x8,0x2,0xe1,0x8c,0xd7,0x8a,0x37,0x5a,0xba,0x86,0x99, + 0xdc,0x7,0x28,0xf3,0xeb,0x9,0xb5,0x5,0x49,0xe5,0x1e,0xf,0x30,0x93,0x1,0xc1, + 0xd2,0x2a,0xc4,0xf4,0x4b,0x1f,0x1,0xbc,0x4c,0xca,0x3d,0xbc,0x44,0x4f,0xa0,0x80, + 0x91,0x45,0xa,0xb,0xfb,0xda,0x20,0xac,0x67,0x1,0x90,0x6,0xa6,0x83,0x36,0xa4, + 0x19,0xc2,0xc1,0x0,0x23,0xbb,0x14,0x16,0xa,0x29,0xc2,0x11,0x6d,0x88,0xa,0x11, + 0x9d,0x1,0x44,0xde,0x2,0x9b,0x29,0x22,0x66,0x54,0xe9,0x50,0x8a,0x29,0x2c,0xd7, + 0x78,0x3,0x48,0x82,0x82,0xc,0x51,0xb2,0x35,0x20,0x98,0xc2,0x42,0x58,0xf6,0x5f, + 0xf2,0x4b,0xe9,0x60,0xe3,0x50,0x4,0xc2,0x2e,0x3,0x82,0x40,0x58,0x96,0x3f,0x86, + 0x4a,0x19,0x3,0x10,0x44,0xce,0xdb,0x7,0xd3,0x6,0x4,0xab,0xb0,0x10,0x4e,0x28, + 0x1d,0x6c,0x65,0xe2,0x26,0x67,0x0,0x81,0x11,0x88,0xb8,0x3b,0xf1,0x72,0xa,0x80, + 0x40,0xc3,0xa5,0x37,0x7f,0x53,0x9,0x94,0x26,0xac,0xce,0x44,0x8b,0x25,0x8b,0x18, + 0xfd,0xdf,0x4d,0x19,0xcb,0xaa,0x29,0xa9,0xf9,0xa8,0xe,0xb2,0x6d,0xe3,0xa9,0x9a, + 0x97,0xa5,0xa9,0xc7,0xae,0xf1,0xa8,0xae,0x2b,0x4c,0xb7,0xe7,0x70,0xd4,0xe4,0x78, + 0x4c,0x2,0x95,0xf9,0xed,0x93,0xd,0x5d,0xd2,0x53,0xd3,0x7b,0x50,0x4a,0xf6,0xc9, + 0x51,0xae,0x84,0xe2,0x8d,0x85,0x79,0x1,0xc9,0x27,0x8d,0x9d,0xa0,0x37,0x18,0x51, + 0x48,0xc2,0x96,0xc1,0x9,0xd1,0x88,0x4c,0x52,0xb6,0xc,0x25,0x93,0x14,0x0,0xd1, + 0x6d,0xf9,0x66,0xf,0x89,0xd9,0x43,0x3c,0x49,0x27,0x8a,0x3d,0xdf,0x27,0x49,0x52, + 0xa,0x24,0x49,0xb3,0x32,0x46,0xa2,0x77,0xf7,0x85,0x4c,0xd7,0x2,0x2,0x71,0x75, + 0x2d,0x14,0x1f,0x0,0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x84,0x15,0x3,0xa2,0x31, + 0x0,0x0,0x25,0xe0,0x89,0x7b,0x2b,0xfd,0x96,0x5b,0x83,0x78,0x2b,0xfd,0x31,0x5c, + 0x86,0x8,0x44,0x7e,0xa2,0xe5,0xc6,0x55,0x3f,0xb0,0x37,0x38,0xc5,0x88,0x66,0xa6, + 0xd0,0xf9,0xbb,0x27,0x4e,0x63,0x7a,0xd2,0x27,0x62,0xaf,0x2c,0x18,0x90,0xf,0x5c, + 0x5f,0x8a,0xcc,0x46,0x20,0x10,0x88,0xc2,0x83,0x1d,0x9b,0xe8,0x3a,0x92,0xd1,0xad, + 0xd2,0x81,0x25,0xb6,0x8,0x44,0x21,0xc2,0xc1,0xfb,0x40,0x50,0xd1,0x20,0x10,0x2e, + 0xf1,0x18,0xf0,0x50,0x27,0xc2,0x71,0x3,0x42,0x51,0xf0,0x10,0x8,0x4,0x22,0x1f, + 0x31,0x75,0x15,0xa4,0x65,0x3,0xf2,0xc1,0x20,0xfc,0xd3,0x82,0x58,0xf0,0xeb,0x14, + 0x53,0x11,0x8,0x4,0x22,0xa7,0x62,0x56,0xeb,0x6,0x44,0x47,0x85,0x87,0x40,0x58, + 0xf4,0x17,0x70,0xfd,0x20,0x72,0xc8,0x2c,0x10,0xd1,0xb0,0x40,0xe2,0x19,0x10,0x81, + 0x0,0x44,0xc7,0x5,0x80,0x40,0x20,0x10,0xa2,0xc8,0xfd,0xaa,0x55,0xdb,0x52,0x58, + 0x42,0x26,0x4,0x99,0x8a,0x40,0x20,0x10,0x85,0x17,0xab,0x58,0x37,0x20,0x14,0x95, + 0x2f,0x22,0xaf,0xa3,0x75,0x94,0x5d,0x4,0x62,0x1a,0x22,0x10,0xc1,0xd0,0x82,0xe2, + 0x22,0x44,0x20,0x10,0x79,0xe2,0x31,0x60,0x6b,0x1c,0xa7,0xc,0x88,0xd8,0x20,0x8c, + 0x11,0x64,0x2a,0x2,0x81,0x40,0x14,0x9e,0x39,0xb6,0x6e,0x40,0x28,0x1a,0x0,0x84, + 0x49,0x50,0x8c,0x58,0x11,0x8,0x8c,0x40,0x0,0x80,0x52,0xca,0x50,0x21,0x20,0x10, + 0x8,0x43,0x4d,0x83,0x4e,0x66,0x1e,0x41,0x72,0xae,0x8c,0x77,0x72,0xf,0x4,0x85, + 0x3,0x81,0x40,0x20,0xdc,0x61,0xed,0xcd,0x3f,0x99,0xb5,0x1,0x61,0xc0,0xf0,0x6e, + 0xdb,0xbc,0x9,0x4c,0x31,0x52,0x44,0x20,0x10,0x7c,0xa5,0x6e,0x87,0x1,0x11,0xb, + 0x63,0x74,0x8a,0x8a,0x9,0x81,0xc8,0x45,0x47,0x12,0x33,0x3,0x88,0x2c,0x20,0x49, + 0xc0,0x4,0x73,0x58,0x76,0x1c,0x24,0x44,0x41,0x45,0x20,0x10,0x88,0x5c,0x81,0x6e, + 0xf1,0x58,0x5,0xb5,0x69,0x13,0x5d,0x34,0xde,0xc1,0x14,0x96,0x3,0x4c,0x45,0x20, + 0x10,0x8,0x87,0xe0,0x60,0x15,0x96,0x4e,0x51,0x39,0x22,0x10,0x1f,0x59,0x18,0xd8, + 0x9d,0x1,0x91,0x9f,0x90,0xc0,0xc9,0x14,0x16,0x21,0xc,0x17,0xb,0x2,0x81,0x28, + 0x64,0x10,0x77,0x35,0x94,0x75,0xf0,0x24,0xba,0xae,0x13,0x64,0x2e,0x2,0x81,0x40, + 0xa0,0x1,0xc9,0x62,0x10,0x1d,0x15,0x34,0x22,0xc7,0xc4,0x1f,0x23,0x62,0x4,0xc2, + 0x82,0xcb,0xed,0x60,0x19,0x2f,0x76,0xe3,0x45,0x20,0x10,0x33,0xa9,0xee,0xb0,0xa, + 0x34,0x8f,0x23,0x10,0x36,0xf5,0xb9,0x45,0x64,0x2a,0x2,0x81,0x40,0xb8,0xdb,0x76, + 0x5b,0x37,0x20,0x68,0x2c,0x10,0x0,0x0,0x58,0x89,0x87,0x40,0xb8,0x25,0xa4,0x73, + 0xb2,0x17,0x96,0x8e,0xca,0x3,0x81,0x28,0x48,0x9f,0x1,0x1d,0x47,0x97,0xc2,0xc1, + 0x14,0x16,0x45,0x41,0x42,0x20,0x10,0x88,0x42,0xf4,0x21,0x6c,0x88,0x40,0x10,0x33, + 0x9,0x5d,0xc2,0xe8,0xf,0x81,0x40,0xe4,0x5e,0x4,0x22,0x94,0x7,0xd3,0x75,0x95, + 0xa0,0x12,0x43,0x20,0x1c,0x2,0x46,0xfb,0x88,0x3c,0x31,0x20,0xe2,0x37,0x12,0xa2, + 0x50,0x23,0x10,0x8,0xc4,0x34,0x42,0xcb,0xc5,0x49,0x61,0xa,0xcb,0x85,0x4c,0x45, + 0x20,0x10,0x88,0x3c,0x89,0x40,0x80,0xa2,0x22,0x45,0x14,0x4,0xb0,0x5c,0x1d,0x51, + 0x20,0x82,0xee,0x64,0x19,0x2f,0x2e,0x2c,0x4,0x2,0xe1,0x42,0xd0,0x42,0xdd,0xdb, + 0x65,0x4e,0x9e,0x44,0x9f,0x81,0xfb,0x40,0x28,0x6e,0xda,0x23,0x10,0x8,0xc4,0x34, + 0x85,0x20,0xa6,0x1f,0xb4,0xd0,0xb,0x8b,0xa2,0x42,0x47,0x4c,0xb3,0x3c,0x63,0x84, + 0x8b,0x40,0x38,0x19,0x82,0x38,0x17,0x81,0xe0,0x2,0x47,0x20,0x10,0x76,0xfb,0xc, + 0xe8,0x94,0x16,0x88,0x1,0xa1,0x14,0x99,0x8d,0x40,0x20,0x10,0x68,0x40,0xb2,0x18, + 0x84,0xe1,0x9d,0xe8,0xae,0x86,0x84,0xad,0xfa,0x11,0x88,0x42,0x8b,0xff,0x44,0xb5, + 0x83,0x75,0x3,0x2,0x14,0x95,0xc,0x2,0xe1,0x12,0xe8,0x14,0x2f,0x87,0x43,0x38, + 0x18,0x81,0x50,0x8a,0x42,0x87,0x40,0x20,0x10,0x79,0x19,0x6b,0x90,0x29,0x9d,0x7f, + 0x47,0xaf,0xb4,0xc5,0x14,0x96,0x33,0x4c,0x45,0x20,0x10,0x88,0xbc,0x89,0x40,0xc4, + 0xf2,0x60,0x3a,0x2a,0x3c,0x4,0xc2,0x9a,0xc7,0x80,0x45,0x28,0x88,0x1c,0x82,0xe4, + 0x74,0x2b,0x13,0x5c,0x0,0x8,0x4,0x2,0x61,0xd2,0x6f,0xc8,0xd1,0xe3,0xf,0xd4, + 0x41,0x3,0xc2,0x4c,0x1c,0x5b,0x44,0xa6,0x22,0x10,0x8,0x84,0x6b,0x22,0x10,0x1b, + 0xaa,0xb0,0xf0,0x46,0x42,0x44,0x5e,0x2f,0x16,0x8c,0x9e,0x11,0x88,0xac,0x74,0x3f, + 0x27,0x2,0x11,0x84,0x8e,0x8b,0x10,0x81,0x40,0xe4,0x5,0x88,0x8e,0xce,0xae,0x40, + 0x50,0xe0,0x60,0x19,0x2f,0xb3,0x27,0x85,0x85,0x8c,0x45,0x20,0x10,0x88,0x5c,0x88, + 0xca,0xcd,0xdf,0x5,0x65,0xa1,0x99,0x22,0x10,0x54,0xfe,0x8,0xf3,0x42,0x8a,0x32, + 0x83,0x40,0xe4,0x28,0x1c,0x6e,0xa6,0x88,0xca,0x0,0x81,0x40,0x18,0x69,0x1a,0x4c, + 0x73,0xa3,0x1,0x99,0x1a,0x3a,0xa,0x7,0x2,0x51,0x80,0xa0,0x6a,0x5a,0x8e,0x75, + 0x1c,0xac,0x4b,0xd,0xe,0x34,0xa5,0x22,0xc1,0x46,0x96,0x4e,0x97,0x28,0x81,0xd2, + 0x21,0x4f,0x79,0xd5,0x60,0xd1,0xac,0x59,0x3,0xc5,0xcd,0xf3,0x83,0x48,0xa5,0xbc, + 0x34,0xf7,0xe,0x47,0x20,0x88,0xbc,0x82,0xa6,0xbb,0xeb,0xe0,0x67,0xe7,0x6f,0xfe, + 0xf3,0x29,0x60,0x34,0x90,0x31,0x40,0xf6,0xf9,0xf7,0xb7,0xdc,0xfc,0x95,0xbf,0xb6, + 0xe3,0x5d,0x3d,0xf7,0xdc,0xf6,0x7d,0x3d,0x11,0x3d,0x3d,0xd3,0x7f,0x57,0x2,0xa5, + 0xdb,0x67,0xdd,0xf0,0xc5,0x6f,0x58,0x99,0x2f,0x7f,0xd9,0x12,0x95,0x10,0x29,0xc, + 0xb2,0x1c,0x26,0x92,0x32,0xa1,0x94,0x94,0x1c,0xf0,0xd5,0x36,0xef,0xae,0x58,0x75, + 0xda,0x3e,0xb9,0xbc,0x32,0x39,0x5d,0x74,0x8e,0x77,0x1c,0xae,0x9,0xee,0xdc,0xbe, + 0x45,0x8b,0x45,0x97,0x30,0x2d,0xdd,0xc4,0x74,0xad,0xe,0x8e,0x29,0xe5,0x3c,0x16, + 0x13,0xbb,0x0,0x80,0x90,0x24,0x51,0x3c,0x43,0x92,0xe2,0x1d,0xf0,0x56,0xd7,0xbd, + 0x52,0x7b,0xfe,0xa5,0xcf,0x4a,0xde,0x80,0x2d,0xf7,0x5f,0x77,0xdd,0xf1,0x83,0x47, + 0x19,0xd5,0x2b,0x4d,0x86,0x41,0x31,0x22,0x49,0x61,0x22,0xcb,0x93,0x7f,0x1e,0xdf, + 0x90,0xb7,0xb2,0x66,0x4f,0x60,0xc1,0x8a,0x3d,0x81,0x5,0x4b,0x87,0xa7,0x53,0x46, + 0xb3,0x9a,0xaf,0x81,0xed,0x26,0x92,0x14,0x6,0x59,0x9,0x12,0x49,0xe,0x49,0x3e, + 0x7f,0x97,0xb7,0xb6,0xe1,0x9d,0xaa,0x93,0x4f,0xdb,0xa9,0x54,0x35,0xc6,0x6c,0x30, + 0x20,0xe,0x36,0x53,0xa4,0xee,0x53,0x48,0x88,0xfc,0x41,0xec,0xc8,0xa1,0x5a,0x9e, + 0x32,0x96,0x7c,0x45,0x9d,0xb6,0x79,0xdd,0xe9,0xe4,0x3c,0xc3,0x77,0xf9,0x8d,0xdf, + 0x25,0x32,0x5f,0x7e,0x82,0x81,0x79,0x18,0xd3,0xab,0x81,0xea,0xd5,0xc,0xd2,0xf3, + 0xd2,0xa9,0xf8,0xda,0xf4,0xd8,0xf0,0x8d,0x91,0x43,0xbb,0x93,0xbe,0xda,0xa6,0xbb, + 0xea,0x2f,0xd9,0xf2,0xc7,0x63,0x15,0xb5,0xd5,0xc,0x41,0xf4,0xf0,0xde,0x86,0x89, + 0x1d,0x6f,0xdc,0xa0,0x45,0x82,0x1f,0x7,0xc6,0x3c,0x26,0xe6,0xe9,0x67,0x6a,0x7a, + 0x8e,0xae,0xa6,0xe7,0x24,0x7a,0xa3,0xa7,0xf7,0xdc,0xf3,0xf3,0x5b,0xfc,0xd,0xcd, + 0xf7,0xd7,0x6e,0xd8,0xfc,0x94,0x5c,0x5a,0x96,0xce,0xda,0x90,0xf5,0xf7,0x96,0x65, + 0xa5,0x8c,0x19,0xd,0x30,0x9d,0x6,0x98,0xae,0x35,0x2,0x0,0x40,0x22,0xe,0x5a, + 0x78,0xe2,0xd2,0x78,0x57,0x2b,0x8c,0xbe,0xac,0xc,0xc8,0xa5,0xe5,0xaf,0x55,0xae, + 0x3d,0xeb,0x8f,0x25,0x8b,0x4e,0x1a,0xb2,0xd5,0xf0,0x66,0x3b,0x5f,0x3,0x31,0x63, + 0x94,0x56,0x0,0x4d,0x57,0x30,0x0,0xa0,0xa9,0xc4,0x6a,0x2d,0x3c,0x71,0x79,0xbc, + 0xfd,0x7d,0x5d,0x9,0x94,0xbc,0x5e,0xbe,0xf2,0x94,0x3b,0xca,0x56,0x9f,0xd6,0x61, + 0x45,0xc0,0x1c,0x8c,0x40,0x28,0xa6,0xb0,0x10,0x33,0x86,0x64,0x5f,0xfb,0x1c,0xde, + 0x33,0x72,0x71,0xa0,0xd3,0xe,0x19,0xd5,0x82,0x13,0xfe,0xa3,0x5e,0x77,0x46,0x28, + 0x25,0xe5,0x86,0xef,0x12,0x99,0xaf,0x85,0x75,0xef,0x4f,0xd,0xf7,0x7d,0xbe,0xe7, + 0xbe,0x5f,0x6e,0x2a,0x5d,0xb2,0xf2,0xc7,0xd5,0x67,0x5d,0xb0,0xcb,0xca,0x70,0x91, + 0xfd,0xbb,0x67,0x5,0xf7,0xbc,0x79,0xa3,0x16,0x9,0x5d,0x4,0x0,0xb2,0xe5,0xe9, + 0xe9,0x7a,0x7d,0xa2,0xaf,0xfb,0x6f,0x7b,0xfe,0xf0,0xff,0x6e,0xf6,0xd6,0x35,0xde, + 0xdf,0x78,0xd9,0xf5,0xf,0x92,0x2c,0xf6,0x4f,0x13,0x1d,0x7,0xe7,0xd9,0x4e,0x3a, + 0x5d,0x6b,0xd4,0x82,0x63,0x9f,0x18,0xd9,0xf6,0xf8,0x55,0x13,0x6f,0xbf,0xfc,0x7c, + 0xf9,0xca,0xb5,0xf7,0x95,0xad,0x3a,0xd5,0x16,0xc7,0x63,0x3a,0xe6,0x9b,0x49,0xd4, + 0xb5,0x58,0xf4,0x9c,0xb1,0x37,0x5f,0x3a,0x2b,0xb4,0x7f,0xd7,0xb3,0xd,0x17,0x5c, + 0xf5,0x3f,0x9e,0xea,0xac,0x22,0x12,0xe7,0x7a,0x61,0x51,0x36,0x75,0x8,0x8b,0x38, + 0x1,0x58,0xa9,0x36,0x2d,0x48,0x4f,0x8c,0x71,0x15,0xb2,0xb7,0xb4,0xaa,0xd3,0xe, + 0xfa,0x87,0xf,0xed,0x9b,0x3,0x9c,0xce,0xb,0xfe,0xba,0xa6,0xe,0xa3,0x77,0x89, + 0xcc,0xd7,0xb2,0x32,0x54,0xd3,0x2d,0xe1,0x7d,0x3b,0x7e,0x12,0xef,0x68,0x7d,0xbe, + 0xfa,0xec,0x8b,0x7e,0x56,0x3c,0x7b,0xd1,0xb8,0xd9,0x31,0xc6,0xdf,0x79,0x71,0x79, + 0xe8,0xbd,0xb7,0xfe,0x7,0x18,0xf3,0xda,0x3e,0x3f,0xaa,0x57,0xa5,0x6,0x7b,0xff, + 0xba,0xff,0xa1,0x3b,0x6b,0x9a,0xb7,0x7c,0xee,0xe7,0x66,0x7f,0xaf,0x8e,0x8d,0xce, + 0x9d,0x56,0x25,0x1c,0xd,0x5d,0x3c,0xf6,0xc6,0x8b,0x17,0x46,0xdb,0x5b,0x7f,0xd1, + 0x74,0xf9,0x4d,0xf,0x58,0x1d,0x70,0x9a,0xe7,0x3b,0x65,0x84,0xa2,0x45,0x42,0x9b, + 0xfa,0x9e,0xbc,0x6f,0x49,0xcd,0x59,0x97,0x7c,0xad,0x64,0xe1,0x32,0x73,0x11,0x15, + 0x31,0xbf,0x7,0x22,0x65,0x6d,0x85,0xa8,0x3e,0xa9,0x1c,0xf1,0xcf,0xf8,0xf,0x31, + 0x3d,0x76,0x39,0x11,0xe5,0x2e,0x4e,0x7f,0xf3,0x3c,0x5b,0x3c,0x49,0x75,0x6c,0x88, + 0xf7,0x2e,0x5a,0xb2,0x60,0x45,0xf7,0x71,0x2b,0x4c,0xa2,0xec,0xd8,0x3f,0x91,0xf9, + 0xda,0x5,0x2d,0x16,0xbe,0x60,0xe4,0xc5,0xc7,0x7f,0xc8,0xf4,0xa4,0x74,0xe2,0x3c, + 0x8c,0xfe,0xa2,0xad,0xbb,0x1a,0xc2,0x7b,0xdf,0xfe,0xee,0x74,0x18,0x8f,0xe3,0x8d, + 0xe9,0xe8,0xb5,0x83,0x4f,0xdd,0x73,0xb5,0x99,0xb9,0x11,0x89,0x32,0x35,0x1e,0x99, + 0xe3,0x84,0x12,0x4e,0xd,0xf7,0xfe,0x75,0xcf,0xfd,0x3f,0xff,0xa6,0x1e,0x1e,0xf5, + 0x99,0x9d,0xe3,0xc,0xcc,0x77,0x2a,0x47,0x62,0xde,0xe8,0x2b,0x4f,0xfe,0x22,0x31, + 0xd4,0x5d,0x62,0x66,0xbe,0xe,0xa7,0xb0,0xb0,0x44,0xf,0x31,0x73,0xa0,0xc9,0xc4, + 0x3c,0x8e,0x37,0x95,0x28,0x5d,0xbc,0x74,0x50,0xf4,0x58,0x93,0xa1,0x42,0x8e,0x86, + 0xc,0x15,0x1,0x91,0x95,0x7e,0xa5,0xac,0x24,0x65,0xf4,0x2e,0xee,0x7c,0xed,0xa6, + 0x4f,0x3a,0xbd,0x68,0xe0,0xa9,0x3f,0x5c,0xdf,0x7c,0xe5,0xcd,0xf7,0x88,0x19,0xc9, + 0xfe,0xc0,0xe8,0xeb,0xdb,0x7e,0xc8,0x28,0xad,0x74,0x62,0x7e,0x89,0x81,0x9e,0x2f, + 0xf,0x3e,0xf7,0xd8,0x48,0xc3,0x85,0x57,0xbc,0x62,0x1b,0xcf,0x6d,0x36,0xc2,0xbd, + 0x7f,0xba,0xab,0x79,0xf6,0x96,0xcf,0x7c,0x51,0x2e,0x2d,0xe7,0xee,0xdb,0x4c,0x95, + 0x92,0x63,0xa9,0xc4,0xdc,0x99,0x5a,0x1f,0x8c,0xea,0x35,0x63,0xaf,0x3c,0xf3,0x99, + 0xc0,0xf5,0x7f,0xf1,0x3f,0x4e,0xa7,0xb0,0x4c,0xf,0x92,0xab,0x20,0x78,0x4e,0xc5, + 0xb5,0x60,0x9a,0x6a,0xa8,0xd4,0x25,0x8f,0xb7,0xd3,0x2e,0xfe,0xeb,0xc9,0xb8,0xa1, + 0x22,0x90,0xbc,0x7e,0xee,0xbb,0x78,0xf3,0x9d,0xe,0xa4,0x46,0x6,0x3f,0x13,0x39, + 0xb8,0xeb,0xc5,0xb2,0x65,0xeb,0x7a,0xd,0x15,0xb3,0x9a,0x96,0xfb,0x9f,0x7a,0xe8, + 0x3b,0x4c,0x4d,0x9b,0x99,0x23,0x25,0xb2,0x32,0x44,0x14,0xcf,0x20,0xa3,0x7a,0x29, + 0xd3,0xd4,0x59,0xc0,0x98,0xdf,0x8c,0xa7,0x1f,0xef,0x3c,0xf4,0xcd,0xc8,0xa1,0x3d, + 0x37,0x95,0x9d,0xb4,0xa6,0x5f,0xd0,0xb3,0x76,0x54,0x21,0xd3,0x74,0xea,0xa4,0xbe, + 0x27,0xff,0xf0,0xd5,0x39,0x9f,0xfa,0xcb,0xef,0x65,0x69,0xc4,0xe7,0xcd,0xe4,0x1a, + 0x51,0x43,0xe3,0x57,0x87,0x76,0xbf,0xf1,0x58,0xf9,0xc9,0x67,0x8,0x46,0xe2,0x92, + 0xb3,0x57,0xda,0xa2,0x82,0x46,0xcc,0x4,0xa2,0x9d,0x87,0xaa,0x19,0xa5,0xa5,0x86, + 0x12,0xee,0xf3,0x75,0x82,0x6e,0x4f,0x84,0x4c,0xd3,0xc6,0x8a,0x4b,0xf6,0xfb,0x3b, + 0x8c,0xde,0x15,0xed,0x3a,0xc8,0x9d,0x2f,0x10,0x92,0x20,0x44,0x8a,0x1a,0xa8,0x4f, + 0x2f,0xa3,0xb4,0xdc,0x9c,0x95,0x65,0xde,0xb1,0xb7,0xb6,0xff,0x43,0xd9,0xa2,0xd5, + 0x5f,0x32,0x3a,0xf4,0xdb,0xff,0xf8,0xfd,0x9f,0xd4,0x93,0x89,0x53,0xf8,0x1e,0x19, + 0x51,0x95,0xb2,0xf2,0x27,0x2a,0x96,0xac,0x7d,0xa8,0x74,0xd9,0xea,0x5e,0xc9,0xe3, + 0xd5,0x8f,0xfb,0xce,0x8e,0x3,0xb5,0xc1,0xdd,0x6f,0x6f,0x4e,0x8d,0xd,0xdf,0x8, + 0x8c,0x15,0x9,0xcc,0xcf,0x17,0xde,0xbf,0xeb,0xa2,0xb2,0xc5,0xab,0xef,0xe4,0x3d, + 0x1a,0xef,0xeb,0x2e,0x63,0x54,0xaf,0x32,0x9e,0x9e,0x14,0x5,0x49,0xa,0x9d,0xf8, + 0xcf,0x8c,0xea,0xb5,0xa6,0xaa,0xc8,0x8e,0x8d,0x44,0x22,0xc1,0xcd,0xfd,0x8f,0xdf, + 0xbb,0xbf,0x69,0xf3,0xf5,0x8f,0x99,0xf9,0x9d,0xc8,0x7c,0xf9,0x3c,0xb7,0xc8,0x7f, + 0x0,0x79,0x62,0xf7,0xdb,0x5f,0x2a,0x5f,0x79,0xda,0x57,0xc5,0x22,0x2,0x27,0x53, + 0x58,0x14,0xc0,0xae,0x5,0x8a,0x40,0x98,0x4a,0x7f,0x74,0xb4,0x71,0x3d,0x51,0xd9, + 0x5f,0xd2,0x61,0xc7,0xbb,0xf4,0x48,0xc8,0xfb,0x61,0xf9,0x67,0x6,0x28,0xa5,0x65, + 0x86,0xef,0x4a,0x74,0x75,0x70,0x3d,0x51,0x5f,0x4d,0xe3,0x9d,0xb3,0xae,0xbc,0xe9, + 0x5e,0xa3,0x67,0xd2,0x23,0xbd,0x25,0x91,0x8e,0xb6,0x59,0x89,0x81,0x9e,0xb5,0xe9, + 0x91,0xc1,0x5b,0x18,0xa3,0x25,0xdc,0x65,0x9a,0x4a,0xac,0x19,0x78,0xf6,0xa1,0x4d, + 0x8d,0x9b,0x3e,0xf9,0x4c,0xc6,0x71,0x83,0x23,0x9b,0xb9,0x2e,0xa7,0xd7,0x77,0xa0, + 0xe6,0xcc,0x8b,0xfe,0xb9,0x74,0xd1,0xb2,0x8c,0xe7,0x26,0x4a,0xe6,0x2d,0x1b,0x29, + 0x99,0xb7,0xec,0x77,0xd1,0xae,0xf6,0xc7,0xc7,0xb6,0x6f,0xfd,0x7b,0x2d,0x11,0xdd, + 0xc0,0x1b,0x37,0x1d,0x1a,0xbf,0x0,0x0,0xf8,0x6,0xa4,0xfb,0x30,0x97,0xe7,0xde, + 0x9a,0x86,0xdf,0xcf,0xbe,0xfa,0x96,0x7b,0x3f,0x1a,0xfd,0x69,0x52,0xf8,0xe0,0xce, + 0x59,0xf1,0x81,0x9e,0x79,0x5a,0x38,0x34,0x4f,0x4f,0xc4,0xe6,0x6b,0xf1,0xd8,0x6, + 0x51,0xa3,0x92,0x18,0xe8,0xf9,0x4a,0xb4,0xed,0xc0,0xeb,0xa5,0x8b,0x57,0x8,0x9f, + 0x19,0x11,0x99,0xaf,0xaf,0xa6,0xfe,0xce,0xd9,0x57,0x7f,0xe6,0x1e,0xd1,0x31,0xd3, + 0xa3,0x43,0x81,0x70,0xdb,0xc1,0xd9,0x89,0xbe,0xf6,0xb3,0x52,0x63,0xc3,0xd7,0x3, + 0x63,0xc5,0x2,0xd1,0xf3,0x69,0xc3,0xdb,0x9e,0x38,0xa3,0xfe,0x82,0x2b,0x5e,0xb7, + 0x33,0xb9,0x63,0x64,0x40,0x84,0xc2,0x18,0xc6,0x74,0x9,0x53,0x47,0x88,0x19,0x9, + 0xcd,0x83,0x63,0x7c,0x65,0x52,0x56,0xd1,0x61,0x87,0x1c,0x6,0xdb,0xf6,0xb5,0x0, + 0x18,0x57,0x1c,0x7a,0xab,0x1a,0xc,0xdf,0x65,0xd7,0x7c,0x7d,0xf5,0x2d,0x11,0x5f, + 0x7d,0xcb,0xfb,0x0,0xf0,0x7e,0xb4,0xfb,0xc8,0x53,0xa3,0xaf,0x3c,0xf3,0x37,0x5a, + 0x2c,0x7c,0x31,0x6f,0xec,0xd4,0xe8,0xd0,0xc7,0x88,0x24,0x3d,0x3d,0xd5,0x7f,0x1b, + 0x7d,0x73,0xdb,0x52,0xa6,0xaa,0x86,0xf3,0x23,0x92,0x14,0xac,0x3d,0xeb,0xa2,0xaf, + 0x8b,0x2a,0xd0,0xd2,0x79,0x8b,0xc6,0x8a,0x6b,0xea,0xbf,0xd9,0xf5,0xd0,0x6f,0x7e, + 0x4a,0xd3,0xa9,0xd5,0xc6,0x69,0x29,0x75,0xee,0xd8,0xae,0xd7,0x16,0xd6,0xac,0x3b, + 0xa7,0xd5,0x50,0x79,0x8e,0x8f,0x70,0x8d,0xb0,0xb7,0xbc,0xf2,0xc8,0x94,0xf3,0x57, + 0x14,0x5a,0xbe,0xe2,0xd4,0xee,0xf2,0x15,0xa7,0x76,0x3,0xc0,0xcb,0x0,0x0,0xc1, + 0x5d,0xaf,0xcd,0x1b,0xdf,0xfd,0xd6,0x3f,0xd3,0x74,0x6a,0x99,0x80,0xb2,0xf3,0x4c, + 0xec,0x7c,0xed,0xba,0xd2,0xc5,0x2b,0x7e,0x2a,0xac,0xec,0x45,0xe6,0x5b,0x56,0xd9, + 0x65,0x46,0x16,0xbd,0x35,0xf5,0xb1,0x9a,0x9a,0xfa,0x83,0x0,0x1b,0xe,0x46,0xbb, + 0x8f,0x3c,0x3c,0xfa,0xd2,0x53,0x5f,0xd3,0x12,0xd1,0x8f,0x71,0xd,0xe0,0x70,0xff, + 0x39,0x0,0x20,0x60,0x40,0x9c,0xac,0xc2,0x3a,0x6a,0x28,0xa6,0xfa,0x43,0x15,0x57, + 0x60,0xd0,0x75,0xe6,0xe4,0x9f,0x1a,0x8f,0x71,0x17,0x67,0x51,0xfd,0xec,0xe,0x3b, + 0xde,0x95,0x1e,0xec,0xe7,0x29,0x7f,0x5a,0xb1,0x68,0x79,0x87,0xd3,0xf3,0x2d,0x69, + 0x9e,0x33,0xd1,0xb2,0xe5,0xc6,0xef,0x10,0x8f,0xb7,0x8d,0xef,0x85,0x26,0xd6,0xb2, + 0x64,0x42,0x9a,0x6a,0x9c,0xd4,0x60,0xef,0x4a,0x81,0xb9,0xdd,0x5e,0xba,0xe0,0xa4, + 0x21,0x33,0xf3,0x93,0x8b,0x3,0xe9,0xfa,0x8d,0x97,0xff,0x23,0x91,0xe4,0x11,0xae, + 0xb7,0xde,0xf6,0xfe,0x45,0xbc,0xf1,0xb4,0x68,0x84,0x6b,0x84,0x8b,0x1a,0xc4,0x69, + 0x58,0xb1,0xea,0xf4,0x23,0xf3,0x3e,0xf5,0xd7,0x9f,0xf3,0xd5,0x36,0xdc,0xe,0x84, + 0x70,0x37,0xc9,0xd3,0xe1,0x89,0x2b,0xe2,0xdd,0x47,0x4a,0x45,0xc7,0x17,0x99,0xaf, + 0xbf,0xb6,0xa1,0x33,0x5b,0xb9,0x2c,0x69,0x9e,0x33,0xd1,0x7c,0xc9,0x27,0xbf,0x4d, + 0x64,0x4f,0xb7,0x40,0x14,0xda,0x22,0x34,0xae,0xd3,0x55,0x58,0x93,0x2f,0x9d,0x6, + 0x7d,0x14,0xe,0x79,0x23,0x47,0xe,0x35,0xa5,0xc3,0x63,0x35,0x5a,0x3c,0x56,0xab, + 0xa7,0xe2,0xd5,0xb2,0xe2,0xd,0x7b,0x2a,0x6b,0xba,0x8a,0x67,0x2f,0xe8,0xa,0xcc, + 0x9e,0x97,0x13,0xbd,0x76,0xb4,0xd0,0x84,0x2f,0xd8,0xb6,0xbf,0x45,0x9f,0x18,0x6b, + 0xd4,0x92,0xd1,0x7a,0x0,0xa2,0xfb,0x6a,0x1a,0xe,0x56,0xae,0x58,0xdf,0x2a,0x97, + 0x94,0xaa,0xd3,0xf9,0xee,0x68,0xf7,0x91,0xca,0x44,0x5f,0x47,0xb3,0x16,0x8b,0xd4, + 0xd2,0x58,0xac,0x8e,0x82,0xee,0x95,0xbd,0xbe,0x9,0xd9,0x5b,0x14,0xf4,0xd7,0x37, + 0x76,0x97,0xaf,0x58,0xdf,0x3d,0xd3,0xf4,0x89,0xf,0xf7,0x94,0xc6,0x8e,0xb4,0xb6, + 0xa8,0xc1,0xf1,0x16,0x3d,0x15,0xaf,0x52,0x2,0x65,0xfd,0x45,0xd5,0xd,0x5d,0xa5, + 0x8b,0x96,0xf7,0x58,0xa1,0xf,0xe5,0x55,0xb7,0x10,0x92,0x2a,0x5d,0xb2,0x7c,0xc0, + 0x16,0x1e,0xc7,0x23,0x86,0xca,0x9f,0xc8,0xf2,0x80,0x52,0x5e,0x99,0x9a,0x89,0xf9, + 0x4a,0xde,0x12,0xad,0x7c,0xf9,0xda,0xef,0x4,0x77,0xbf,0x79,0x7,0x18,0x1d,0xf8, + 0x63,0xac,0x78,0x6c,0xf7,0x1b,0x8b,0x6b,0xd6,0x6f,0x78,0xff,0x23,0x6b,0x2d,0x95, + 0xac,0xe3,0xbd,0x27,0x30,0x67,0xfe,0x9e,0xe3,0x68,0x22,0xc9,0x42,0xeb,0xde,0x37, + 0x67,0xe1,0x84,0xb7,0xa2,0xfa,0xd1,0xd4,0xf8,0xf0,0xe7,0xa7,0x9a,0x15,0xf1,0x78, + 0x5b,0x95,0x40,0xe9,0x5b,0xbe,0xe6,0xb9,0xaf,0xf0,0xc6,0xe4,0x75,0x2,0x0,0x42, + 0x12,0xc5,0x4b,0x57,0xd,0x88,0xce,0x6d,0x92,0x80,0xb2,0xde,0x78,0xd5,0x67,0xee, + 0x1a,0x7b,0xed,0xd9,0x5d,0x91,0xfd,0x3b,0xfe,0x1f,0x18,0x15,0x6,0x31,0x56,0x34, + 0xf6,0xd6,0x8b,0x5b,0xbc,0x9f,0xb8,0xf5,0xb7,0x42,0x32,0xca,0x9f,0xaf,0x5a,0xbc, + 0x6c,0x5d,0x8f,0xa9,0xf9,0x9e,0x38,0x44,0x4d,0x7d,0xbc,0x7c,0xd9,0xda,0x6f,0x5, + 0xf7,0xbe,0x65,0x38,0x27,0xa6,0xa9,0x2d,0x82,0xef,0x71,0xf6,0x24,0xba,0x95,0x8f, + 0xff,0xa8,0xd1,0x8,0x7a,0xc7,0xdf,0xdc,0x76,0x66,0x72,0xa4,0xef,0x7c,0x3d,0x1e, + 0x3b,0x7b,0xca,0x4d,0xb8,0x81,0x6e,0x8,0x1d,0xd8,0x9,0x20,0x49,0x61,0x49,0xf1, + 0x74,0x49,0x1e,0x5f,0x57,0xd1,0xbc,0xc5,0x7f,0xaa,0x3e,0xf3,0xc2,0x7d,0x59,0x2b, + 0x88,0xf1,0x91,0xa2,0xde,0x87,0x7e,0xf3,0xa2,0xd1,0x33,0x35,0xe7,0x5f,0x76,0x59, + 0xc9,0x82,0x15,0x1f,0x7a,0x52,0x91,0xf7,0xf7,0x34,0x84,0xf7,0xbe,0xf5,0x9,0x35, + 0x34,0x71,0x5,0xb0,0xe3,0x37,0x47,0x13,0x83,0xbd,0x10,0xdc,0xb7,0x43,0x23,0x1e, + 0xcf,0x11,0x6f,0x79,0xd5,0xb,0xd,0x97,0xdf,0x78,0x37,0x51,0x3c,0xd4,0xe,0x1a, + 0xc5,0xbb,0xdb,0x2b,0x42,0xbb,0x5f,0x3f,0x5f,0x1d,0x1f,0xb9,0x88,0xa6,0x53,0xab, + 0x32,0x9,0x7c,0xa4,0xe3,0x20,0x8c,0xbe,0xf3,0x4a,0xbf,0x12,0x28,0x7b,0xad,0xfc, + 0xd4,0x73,0x7e,0x5f,0x32,0x7f,0xf9,0x68,0x36,0xef,0x63,0x6a,0x4a,0xee,0xba,0xf3, + 0xc7,0xdb,0x33,0xa6,0x70,0x8,0x49,0xce,0xfd,0xdc,0x3f,0x1e,0x1f,0x42,0x53,0x9d, + 0x8c,0x3c,0xff,0xc8,0xc6,0x78,0x5f,0xd7,0xad,0x4c,0x55,0x17,0x1c,0x97,0x4a,0x19, + 0x19,0x84,0x58,0xe7,0x61,0x18,0xdd,0xf1,0xa,0x95,0xfd,0x45,0xbb,0xca,0xd7,0x9e, + 0xf9,0xfd,0xb2,0x15,0xa7,0xf6,0x98,0x9e,0x97,0xc6,0x49,0xb9,0x28,0x9e,0x2e,0xdd, + 0xe3,0xd3,0x6d,0x91,0xcb,0x4,0xaf,0x2,0xcb,0xd7,0xc1,0x5b,0x7,0xd3,0x39,0xdf, + 0x8a,0x53,0x37,0x1e,0xc,0xed,0xdf,0xd9,0xc6,0xd4,0xf4,0x12,0xc3,0xb4,0x5f,0x38, + 0x54,0x3d,0xd5,0x3c,0x75,0x35,0x55,0xc3,0x33,0x6e,0x81,0x15,0xeb,0xbb,0xb3,0x5d, + 0xeb,0x25,0xcb,0xd7,0x3d,0x93,0xda,0xfe,0xcc,0xe7,0x0,0x80,0x10,0x49,0x1e,0x96, + 0x8b,0x2,0xef,0x78,0xab,0x6a,0xdf,0x2a,0x59,0xbe,0xee,0xed,0xe2,0x96,0x5,0xc2, + 0x8e,0x20,0xaf,0xa2,0x89,0x28,0x9e,0x2e,0xc8,0x72,0x8e,0xd5,0x67,0x5d,0xb4,0x37, + 0xd1,0x79,0x78,0xab,0x16,0x8b,0x5c,0x62,0x18,0x85,0x44,0x82,0x1f,0x3,0x80,0xdf, + 0xda,0x33,0x5f,0xa5,0xd7,0xe,0xbd,0x50,0x71,0xc6,0x79,0x7,0x82,0xfb,0xdf,0x9, + 0x3,0xa5,0x65,0x19,0xe5,0x8f,0xd2,0x6a,0x75,0x64,0x30,0xe0,0xa9,0x6d,0xe0,0x9c, + 0x4e,0x17,0xae,0xc2,0xca,0x9d,0x32,0x5e,0x1a,0x9,0x79,0x86,0x9e,0x7d,0xe4,0x53, + 0xa9,0xf1,0xa1,0x9b,0x45,0x36,0x85,0x26,0x7f,0x44,0xcb,0x68,0x3a,0xb5,0x92,0xa6, + 0x53,0x2b,0x23,0xfb,0xde,0xdd,0x9c,0xe8,0x6a,0x7b,0xb4,0xfe,0xfc,0xcd,0xb7,0x7b, + 0xea,0x5a,0xa2,0x66,0xdf,0x1f,0xeb,0x38,0xd8,0xc4,0x7b,0xa6,0xb8,0x6e,0xf6,0x87, + 0x82,0x3e,0xf0,0xe8,0x5d,0xd7,0xa5,0x46,0xfa,0xbe,0x6c,0x9c,0x17,0x67,0xa,0x53, + 0xd3,0x8b,0x53,0xa3,0x83,0x8b,0x7b,0xef,0xfb,0xf9,0xda,0xea,0x8f,0x5d,0xf6,0xaf, + 0x66,0x16,0xcb,0x54,0x34,0x1a,0xf8,0xf3,0x3,0xb7,0xaa,0xe3,0xe3,0x37,0x2,0x30, + 0xa1,0x5b,0x24,0x99,0xae,0x37,0xa9,0xe1,0x89,0x6b,0xc6,0xb6,0x3d,0x79,0x51,0xa2, + 0xed,0xfd,0xef,0xd6,0x6d,0xba,0xea,0x25,0xb3,0xef,0x8d,0xb4,0xed,0xab,0x33,0xfa, + 0x4e,0x22,0x49,0xa3,0x44,0xfa,0xdf,0x28,0x74,0x74,0xfb,0xb3,0xab,0xa2,0x87,0xf, + 0x7c,0x8d,0xa9,0xe9,0x45,0x3c,0xdf,0x4f,0x4f,0x26,0xd6,0x8d,0xbf,0xb1,0xed,0x9e, + 0x58,0xeb,0x81,0x5f,0x35,0x5e,0x71,0xfd,0xfd,0x44,0x51,0x84,0x84,0x37,0xd6,0xd9, + 0x5e,0xc9,0x28,0xad,0xe0,0x28,0xf5,0x23,0xc7,0xce,0xcb,0x92,0x7c,0x72,0x14,0x81, + 0xe4,0x2b,0xea,0x30,0x7a,0x97,0x13,0xf3,0x95,0xbc,0xbe,0xe,0x9d,0x63,0x40,0xf4, + 0x64,0xac,0x62,0xca,0x77,0x50,0x8e,0x3c,0x31,0xe6,0x8b,0x76,0xee,0xaf,0x2e,0x5d, + 0xb8,0x7c,0x24,0x9b,0xb9,0x95,0x2d,0x5f,0xd9,0x9f,0xe8,0x3c,0xf8,0xd,0x7f,0xc3, + 0xec,0xd6,0xf2,0x75,0xa7,0x77,0x9e,0x30,0x2b,0xa1,0x31,0xd2,0x83,0xdd,0xa5,0x8c, + 0xea,0x86,0x86,0x4e,0xf6,0xfa,0x3a,0xac,0xd0,0xb0,0xe2,0x8c,0x73,0x7f,0x3e,0xfa, + 0xc2,0xd3,0x1b,0x8d,0x4a,0x91,0x99,0x9a,0x5e,0xa8,0x8e,0xf4,0x6,0xbc,0xf5,0x8d, + 0x51,0xab,0xf3,0x95,0x14,0x6f,0xa7,0x5d,0x32,0x2a,0x29,0x9e,0x36,0x9a,0x4e,0xad, + 0x35,0x5c,0x37,0x6d,0xfb,0x5a,0x2a,0xeb,0x6b,0xf,0x18,0x6b,0x74,0xea,0xdc,0x9d, + 0xe8,0x14,0x0,0xac,0x12,0x60,0xe4,0xc5,0xad,0xeb,0x62,0x6d,0xef,0x7f,0x8d,0xe9, + 0xea,0x5c,0xb,0xc3,0x10,0x2d,0x12,0xbc,0xba,0xff,0xf1,0xfb,0x37,0x14,0x35,0xcf, + 0xf9,0xef,0xfa,0xcd,0xd7,0x3c,0x67,0xe6,0xc7,0xe9,0xf1,0x61,0xc3,0xa,0x1b,0x22, + 0x49,0x21,0xb9,0xbc,0x24,0xcd,0xb4,0x94,0xd4,0xf7,0xc7,0x3b,0xbf,0xaa,0x86,0x27, + 0xae,0x31,0xe5,0xc1,0x26,0x13,0xa7,0x8d,0x3c,0xf7,0xf0,0xef,0xcb,0x57,0x9d,0xf2, + 0x7f,0x2b,0x4f,0xdb,0x70,0xc8,0xec,0xc7,0x8d,0x6e,0x7f,0xf6,0xe4,0xe8,0xc1,0xfd, + 0x5f,0x67,0x7a,0x76,0xe7,0x8,0x18,0xa5,0xe5,0xb1,0xce,0xd6,0xff,0xec,0xb9,0xf7, + 0x97,0x8f,0x37,0x6c,0xda,0xf2,0x63,0x4f,0x75,0x6d,0x42,0xf4,0xb7,0xa9,0xa1,0xc1, + 0x26,0xe3,0xf4,0x8d,0xf2,0xa1,0x52,0x19,0x7e,0xfe,0x89,0x33,0x63,0xed,0x7,0xbf, + 0xf,0x8c,0xf9,0xc4,0x27,0xc7,0x7c,0xa9,0x91,0x81,0x2f,0xf,0x3c,0x76,0xaf,0xd4, + 0xb4,0xe5,0x96,0xbb,0x85,0xa2,0xb0,0x8e,0x36,0xee,0x7e,0x82,0xe2,0x2f,0xb2,0xa9, + 0x2,0x2b,0xec,0x61,0xba,0x3a,0xcb,0x50,0x71,0x95,0x94,0x1e,0x71,0x72,0xbe,0x53, + 0x5d,0xe2,0xa6,0xf8,0x8b,0x3a,0xf4,0x58,0xc4,0x98,0xd4,0x69,0xb5,0x6c,0xaa,0xdf, + 0x12,0x45,0x99,0xe0,0xd2,0xfc,0xd0,0x81,0xb5,0x65,0xf3,0x56,0x6e,0xcd,0x96,0x8e, + 0xd,0x9b,0xae,0x7d,0xd6,0x84,0xbd,0xf8,0x8,0xc2,0x87,0xf8,0x3d,0xa5,0x64,0x7f, + 0xd1,0x11,0x2b,0x17,0xdc,0x95,0xcd,0x5b,0x39,0x1c,0xa9,0x7c,0xe7,0xee,0xd4,0xf8, + 0xf0,0xe7,0x8c,0x14,0x67,0x70,0xcf,0xbb,0xab,0xea,0xcf,0xbf,0xe2,0x35,0xab,0xf3, + 0x95,0x7c,0xfe,0x4e,0xbb,0x2e,0xe4,0x93,0xfd,0xfe,0x76,0x9e,0x1,0xd1,0xe2,0xf1, + 0x12,0x81,0xf7,0x39,0xd9,0xca,0x64,0x52,0x98,0xb3,0xfd,0xeb,0x7d,0xe0,0xb7,0x9f, + 0x8d,0x1e,0x7a,0xef,0x76,0x8b,0xc6,0xe3,0xb8,0x30,0x2d,0xde,0xd3,0xf1,0x9d,0xde, + 0xfb,0x7e,0xfd,0x37,0x66,0xe6,0xa1,0xc5,0xa2,0xd,0xc6,0xdc,0x51,0x46,0x88,0x2e, + 0xb1,0xbe,0x3f,0xde,0x61,0xda,0x78,0x1c,0x13,0xd,0xd4,0x87,0xf6,0xed,0xfa,0x26, + 0xa8,0xe6,0x68,0x36,0xfc,0xf4,0x23,0x1b,0x23,0xfb,0x77,0xff,0x22,0x5b,0xe3,0x71, + 0x9c,0x0,0x45,0xc2,0x97,0xf7,0x3d,0x72,0xcf,0x5d,0xda,0xe8,0xb8,0x4f,0x98,0x36, + 0x91,0x89,0x26,0x4e,0xda,0x60,0xf8,0xe8,0x3c,0xcf,0x8f,0xb5,0xbd,0xff,0x43,0x53, + 0xc6,0xe3,0x58,0x43,0x35,0x3a,0xfc,0xe9,0x58,0xfb,0x91,0xa,0x91,0x39,0xa9,0x13, + 0x63,0xf3,0xb9,0xa,0xb9,0xa4,0xfc,0x88,0x15,0xd9,0xfc,0xe0,0x2f,0x72,0x60,0xff, + 0x6c,0xe0,0x34,0x13,0xf4,0x57,0xd5,0x1d,0x71,0x72,0xbe,0x53,0xf2,0xc1,0xeb,0xd, + 0xf1,0xb5,0x8c,0x92,0xcc,0xc0,0x43,0xae,0x1,0x49,0xe,0xf5,0x5f,0xa5,0x85,0x82, + 0xd3,0xda,0xde,0xc4,0x30,0xfd,0x16,0x1c,0xe3,0x1b,0xe1,0xb2,0xa,0xcb,0x4e,0x43, + 0xdd,0x79,0x97,0xdf,0xd,0x84,0x24,0x39,0xe,0xe7,0x5a,0x3b,0xe6,0xeb,0xe1,0x94, + 0x7e,0x1f,0x93,0x55,0x62,0xbc,0x3f,0xa6,0x53,0x6e,0xe6,0xc6,0x3f,0xbb,0xb9,0x93, + 0x3b,0x96,0x4d,0x6,0x84,0xa,0x6a,0xc5,0xac,0x9b,0x29,0xf6,0x3c,0xf8,0xeb,0x2f, + 0xa9,0x13,0xa3,0x9f,0x9b,0x16,0x61,0xb,0x4f,0x5c,0x37,0xfe,0xf6,0x8b,0x4b,0xc5, + 0x53,0x14,0x89,0x7a,0x43,0xfe,0xc9,0x9e,0x81,0xa1,0x67,0x1f,0xde,0xa0,0x86,0x43, + 0xd7,0x58,0x99,0x17,0x53,0xd3,0xb,0x87,0x9f,0x7b,0xe8,0x3c,0x11,0x81,0x0,0x89, + 0xb2,0xa1,0x17,0x1e,0x39,0x3b,0xd6,0xdd,0xf6,0x1d,0x0,0xfb,0x9a,0x56,0x32,0x5d, + 0x6d,0x19,0x7e,0xf1,0x4f,0x37,0x88,0xce,0x41,0x4f,0xc4,0x9a,0x8d,0x53,0x27,0x9e, + 0x91,0x89,0x77,0x5f,0x5e,0x18,0xeb,0x69,0xff,0x56,0x86,0x68,0x56,0x34,0x12,0x29, + 0x19,0x7f,0xf3,0xb9,0xcf,0x89,0xcd,0x29,0xc2,0x5d,0x9c,0xfe,0xc6,0xc6,0x23,0xa2, + 0xdf,0x68,0xf4,0x97,0x1e,0xeb,0xe3,0x39,0x37,0xac,0x74,0xf1,0xb2,0x8e,0x99,0x9e, + 0x2f,0x8f,0x4f,0x93,0x51,0x8a,0x77,0x62,0xaa,0xdf,0x7a,0x4a,0x4a,0xbb,0xf8,0x6b, + 0x24,0xb5,0xa6,0xef,0xf1,0xdf,0xfd,0x48,0xb,0x8d,0x78,0xed,0xa0,0xab,0xe9,0xef, + 0x8b,0x45,0xf9,0x34,0x6c,0x98,0x65,0x99,0xe7,0x9e,0xea,0xaa,0x4,0x51,0x14,0xe3, + 0x53,0xfb,0xc9,0xf8,0x3c,0x3b,0xe6,0xeb,0xad,0xaa,0xee,0x14,0x9a,0x97,0x48,0xa4, + 0x9c,0x4e,0x2d,0x30,0x56,0xf7,0x24,0x5e,0xb6,0xe4,0xe4,0x41,0x91,0x95,0xe8,0x5c, + 0x4,0x22,0x68,0x1d,0x4f,0xfc,0xeb,0x79,0xe0,0x57,0x5f,0x51,0x83,0x63,0x37,0x4d, + 0xa3,0xc3,0x22,0x85,0xe,0xec,0xfa,0x7,0x46,0x53,0x44,0x64,0x3e,0x34,0x95,0x6e, + 0xe2,0x64,0xfb,0xe2,0xb1,0xee,0xf6,0x6f,0xd8,0x31,0xb1,0x78,0x5f,0xcf,0xe7,0x99, + 0xa6,0x72,0xd,0xc2,0xc8,0x2b,0x5b,0x57,0xc7,0x3a,0x5a,0xbf,0x2f,0xa2,0x94,0x89, + 0x24,0x8d,0xcb,0x5e,0xff,0xbb,0xb2,0xbf,0xe8,0xd,0x22,0x49,0xdc,0xcd,0xf2,0xd4, + 0xf8,0xd8,0xcd,0xd1,0x8e,0xd6,0x4a,0x31,0xe3,0x9a,0x9a,0x65,0x6c,0x5c,0xbd,0xe3, + 0xc1,0xf7,0xde,0xfd,0xf,0x3b,0x9a,0xef,0x69,0xd1,0xf0,0xc7,0x85,0x6c,0x4d,0x2a, + 0xc5,0xab,0x6e,0x49,0x97,0x2d,0x37,0x6e,0xdd,0x21,0x9c,0xde,0x8c,0x84,0xe7,0x1b, + 0xa7,0xf0,0xe4,0x1,0x6f,0x45,0x43,0xdc,0x28,0x62,0x10,0x99,0x6f,0xf9,0xd2,0xf5, + 0x3d,0x56,0x22,0x25,0x9a,0x4c,0xcf,0xe6,0xca,0x89,0xaf,0x78,0x62,0xaa,0xdf,0x56, + 0xae,0x5a,0xff,0xba,0x48,0x72,0x49,0x4f,0x26,0x4f,0xeb,0x79,0xf8,0xae,0xbb,0x86, + 0x9e,0x7c,0xe8,0x42,0x48,0xe9,0xc4,0x8e,0x8,0x4f,0xfc,0xfb,0x12,0xf3,0xb9,0x34, + 0x5c,0xb2,0xa6,0xd7,0x8e,0x77,0x49,0xb2,0xb7,0x87,0x93,0x4d,0x28,0xb3,0x3c,0x5f, + 0x0,0x56,0x36,0x7f,0x55,0x87,0x1d,0xf3,0x85,0x94,0x4e,0x98,0xa6,0xce,0xe3,0xec, + 0x91,0x8,0x45,0xb8,0x40,0x89,0xb3,0x27,0xd1,0xcd,0xe6,0xf0,0x6,0x9e,0x79,0xe0, + 0x62,0x35,0x3c,0x71,0x3d,0x7f,0x7a,0x24,0xe5,0x29,0xad,0x78,0xd0,0x5b,0x5a,0x79, + 0xc0,0x53,0x59,0xd5,0x2b,0xf9,0xfc,0xc9,0xe4,0x60,0xdf,0x22,0x35,0x12,0x5c,0xa6, + 0x46,0x82,0xd7,0xf0,0x14,0x16,0x53,0xd3,0xcb,0x7,0x9e,0xfc,0xe3,0x95,0xcd,0x97, + 0xdd,0xf4,0x30,0xf7,0x33,0x34,0xd5,0x70,0xf1,0xe9,0xf1,0xd8,0xc5,0x27,0x28,0x8d, + 0x6e,0xb9,0xa8,0x78,0x97,0xec,0x2f,0x3d,0xec,0x29,0x2d,0xeb,0x51,0x23,0xc1,0xb9, + 0x5a,0x34,0xb2,0x46,0x4f,0xc6,0x36,0xa,0x44,0x0,0xf3,0x86,0x9f,0x7f,0xfc,0xdc, + 0x86,0xb,0xaf,0xc9,0x58,0xf5,0xa5,0x27,0x42,0x9e,0xe8,0xe1,0xf7,0xbf,0xc1,0xfb, + 0x46,0x22,0x7b,0xba,0x3,0x2d,0xb,0x7e,0x58,0x7f,0xfe,0x95,0x6f,0x1c,0xfb,0xef, + 0xc3,0xdb,0x9f,0x59,0x1d,0x6d,0xdb,0xf7,0xef,0x4c,0xd7,0x9b,0x32,0x78,0xfb,0xc5, + 0x13,0x6f,0x6e,0xbb,0xb5,0xb4,0x65,0xc9,0xf,0xb9,0xb4,0x49,0xa5,0xd,0x17,0x42, + 0x3a,0x38,0xfa,0x89,0xc,0xef,0x61,0x44,0x96,0x7b,0x18,0x65,0x15,0xc0,0x32,0x57, + 0x87,0x9c,0x38,0xaf,0x58,0x7b,0x7b,0x45,0xc9,0xdc,0x45,0x13,0xc6,0xfc,0xe2,0x56, + 0xb7,0x74,0x49,0xc4,0xa7,0x83,0xd,0x35,0x58,0x34,0x65,0xdc,0xbc,0x4f,0xf2,0x78, + 0x3b,0xf8,0xf2,0xc5,0x9d,0x6f,0xb7,0xd5,0x6a,0x1c,0xaa,0xf2,0xd,0x88,0xaf,0xa2, + 0x6a,0x78,0xea,0xe8,0x67,0x7e,0x58,0xf6,0xfa,0x77,0xeb,0xe9,0xe4,0x3a,0x1,0xf9, + 0x9d,0x1f,0xeb,0x3b,0xf2,0xdd,0x8e,0xbb,0x7f,0xf2,0x5,0x6f,0x65,0xfd,0x83,0x65, + 0xcb,0x57,0xbf,0x50,0xb6,0x68,0xf5,0xb4,0xde,0xe8,0x77,0x74,0x8d,0xf2,0x68,0xd8, + 0x69,0x57,0xa5,0xa3,0xe4,0xf5,0xf6,0xea,0xc9,0x98,0x41,0xaa,0x9c,0x95,0xf3,0xf6, + 0x7e,0xb9,0x3c,0x97,0xe4,0x61,0x6f,0x6d,0x75,0x1c,0x6c,0x10,0xd2,0xb1,0x77,0xb7, + 0x2d,0xe5,0xa5,0x8e,0x25,0x9f,0xaf,0x4d,0x68,0xbf,0x9a,0x40,0xee,0x56,0x61,0x45, + 0x3a,0xe,0x55,0x25,0xfa,0xbb,0xbe,0xc6,0x4d,0xd5,0x16,0x7,0x9e,0xaf,0x5c,0x77, + 0xf6,0x4f,0xca,0x97,0xac,0x39,0x31,0xe4,0x3a,0x42,0x24,0x7d,0xeb,0xf8,0x5b,0xdb, + 0x9f,0x98,0xd8,0xf7,0xce,0xf,0x98,0xae,0xb7,0x18,0xe6,0x6d,0x87,0x7,0xfe,0x3a, + 0x3d,0xdc,0xbd,0xd5,0xd7,0xd0,0x1c,0x35,0xd8,0x37,0x21,0x4c,0x53,0x5b,0x44,0x13, + 0x2d,0x9e,0xb2,0x8a,0xfb,0x9a,0xaf,0xf8,0xe4,0x6d,0x4a,0x51,0xf9,0xb1,0x67,0x18, + 0x5e,0x3,0x80,0x7b,0x7b,0x1e,0xb9,0xfb,0xfa,0xd4,0xe8,0xe0,0xdf,0xf1,0xe8,0x92, + 0xe,0x4f,0x2c,0x26,0x92,0xbe,0x2d,0xa3,0x91,0x7d,0xfa,0xc1,0x9b,0x79,0x7b,0x1e, + 0x72,0x71,0xe0,0xb9,0xd9,0x5b,0x3e,0xf5,0x8d,0xc9,0x79,0x1c,0x2f,0x84,0xf5,0x1b, + 0x2e,0xda,0x5d,0xb1,0x74,0xe5,0x75,0xbd,0x4f,0xdc,0xf7,0x10,0xa3,0xb4,0x6e,0xea, + 0x34,0x5f,0x68,0x4b,0xf8,0xf0,0x8e,0xbb,0xca,0x97,0x66,0xe,0x6b,0x69,0x3a,0x2d, + 0x33,0xdd,0x98,0x36,0x27,0x1a,0xf,0xd9,0xef,0x7f,0xc3,0x5f,0xdf,0xfc,0x70,0xe5, + 0xca,0x35,0x3b,0xfc,0x4d,0xf3,0xc2,0x0,0x0,0xa1,0x83,0xbb,0x1b,0xc6,0xdf,0x7d, + 0xfd,0x4b,0x7a,0x3c,0xb6,0x89,0x1b,0xa1,0xd,0xb4,0x37,0x97,0xce,0x9f,0x9f,0xf1, + 0xe,0x8b,0x68,0x5f,0x7b,0x39,0xa3,0xb4,0x8a,0xc7,0xa7,0xbe,0x27,0xee,0xde,0x62, + 0x8b,0xe2,0x4a,0x26,0x57,0x18,0x2b,0x1b,0xe3,0xea,0x29,0x91,0xf9,0x4a,0x1e,0xaf, + 0xa5,0xa,0xac,0xe0,0x7b,0x3b,0x9a,0x99,0xae,0xb5,0xf0,0xa2,0xd4,0xca,0x35,0xa7, + 0x75,0x66,0x52,0x58,0x65,0x8b,0x97,0xfd,0x64,0x62,0xdf,0xce,0x3b,0x45,0xd3,0x90, + 0x4c,0xd7,0x5b,0x52,0xa3,0xfd,0x7f,0x37,0xf2,0x72,0xff,0x57,0xc7,0xde,0x78,0xe1, + 0x3d,0x4f,0x59,0xd5,0x73,0xe5,0x2b,0xd7,0x3d,0x5f,0xb6,0x68,0xd9,0x8,0xd8,0x8c, + 0xd4,0x60,0x5f,0x9,0xa3,0x7a,0xdd,0x74,0xd2,0xf0,0x38,0x19,0x2e,0x2a,0xee,0x51, + 0xc3,0x13,0x46,0x1f,0x5f,0xc6,0x9f,0x2f,0xad,0xe3,0x44,0x4,0xb6,0x14,0x79,0x68, + 0x89,0x90,0x27,0x74,0x68,0xdf,0xbf,0x70,0xbf,0xc9,0x1f,0x38,0x22,0xa8,0xd1,0x9d, + 0x6e,0xe7,0x2e,0xce,0xb4,0xb1,0xd7,0xb6,0x7e,0x9d,0x31,0xe3,0x66,0x60,0x4a,0x71, + 0xe0,0xe9,0xb9,0x37,0xfe,0xd5,0xd1,0x74,0xd1,0xd4,0xc2,0x5e,0x75,0xda,0x39,0xad, + 0x72,0x79,0xe9,0x5f,0x8e,0xbc,0xf2,0xdc,0x63,0x86,0x2,0xcf,0x68,0x59,0xf0,0xe0, + 0x9e,0x25,0xf5,0xd,0xcd,0x3b,0x32,0x3d,0x12,0xda,0xbf,0xbb,0x51,0xa8,0x83,0x28, + 0x21,0xc9,0x92,0xb9,0xb,0xbf,0xd6,0x70,0xe1,0x95,0x19,0xab,0x2f,0x66,0x5f,0x7d, + 0xd3,0xfd,0x1d,0xf7,0xdc,0x7e,0xb2,0x1e,0x8f,0x5d,0x60,0xec,0xd5,0x66,0x4e,0xb, + 0x5,0xdf,0xdb,0xd1,0x9c,0xa,0x8e,0xfd,0x1f,0x4e,0xda,0xa4,0xa7,0xf9,0xe2,0x2d, + 0xdf,0x3e,0xc1,0x88,0x1d,0xef,0x6d,0xd6,0x37,0xc6,0x7c,0x75,0x4d,0xbf,0x4c,0xe, + 0xf6,0x7e,0x33,0x13,0xa9,0xe3,0x47,0x5a,0x57,0x18,0x19,0x90,0xe0,0xbe,0x77,0xe6, + 0x98,0xd8,0xd7,0xd0,0x7d,0xd5,0xb5,0xb7,0xcf,0xba,0xea,0xe6,0xdf,0x9f,0xd8,0x89, + 0xa0,0x7c,0xe9,0xc9,0x83,0xe5,0x4b,0x4f,0xfe,0xe7,0x8e,0xbb,0x7e,0x56,0xac,0x27, + 0x13,0xe7,0x1a,0xe,0x12,0x9c,0x98,0x5,0x0,0x7b,0x8f,0xc9,0x91,0x1d,0x37,0x56, + 0xac,0xed,0x30,0x77,0x43,0x9a,0xa9,0xea,0xe2,0xe4,0x50,0xdf,0x3f,0x81,0x3,0x90, + 0x8b,0x4b,0xda,0x8d,0xce,0x1e,0x88,0xcc,0x57,0xf1,0x15,0x1d,0x1,0xb,0xe7,0xa9, + 0x26,0x76,0xbe,0xfe,0x75,0x0,0xe3,0x9e,0x4e,0x92,0xbf,0xe8,0x4d,0xa3,0x77,0x54, + 0x9f,0x7d,0xd1,0xfe,0xf8,0x40,0xcf,0xed,0xa9,0xb1,0x91,0x2f,0x9b,0x7c,0x3d,0xa1, + 0xe9,0xf4,0xea,0xd4,0xe8,0xe0,0xea,0xe1,0x17,0x9f,0xfa,0xea,0xd8,0x6b,0x2f,0xec, + 0xf4,0x54,0x56,0xff,0xb9,0xee,0xcc,0xf3,0xb7,0x7a,0xeb,0x9b,0x62,0x76,0xd0,0x38, + 0xd8,0x7e,0x80,0xbf,0x81,0xee,0x2b,0xb6,0x44,0xc3,0xe3,0xc6,0x2a,0x2b,0xef,0x86, + 0xa1,0x3e,0x3,0xb5,0x42,0xcb,0x8c,0xde,0x25,0x32,0x5f,0xc9,0xef,0xeb,0xb0,0x63, + 0xbe,0x7d,0x8f,0x3d,0xf4,0x5,0xa6,0xaa,0x8b,0x79,0x6b,0xb3,0x64,0xde,0x82,0xd7, + 0xc0,0xde,0x83,0x84,0xd2,0x47,0xfe,0x9f,0x6c,0xc,0x8,0x48,0x32,0x13,0xf9,0x1b, + 0x7a,0xe9,0xe9,0x53,0xf4,0x64,0xe2,0x63,0x9c,0xb0,0x6e,0xb0,0xf1,0xc2,0xab,0xbe, + 0x2f,0x32,0x5e,0xf9,0xb2,0x75,0x3,0x4a,0x71,0xe9,0x33,0xbc,0xe9,0xa9,0xa1,0xe0, + 0x1c,0xa3,0x71,0x92,0x3,0xdd,0xf3,0x45,0x3e,0xd3,0x57,0x51,0x73,0x47,0xc3,0xc5, + 0x5b,0x5e,0xe5,0xcd,0xab,0xa8,0xbe,0xf9,0x31,0x1,0x5,0xd7,0x9c,0xe9,0xf7,0xa1, + 0x3,0x3b,0x6e,0xe0,0x84,0xa3,0x5a,0xc5,0xf2,0x35,0xff,0xe0,0xad,0x6f,0x8a,0xf1, + 0xe6,0xd2,0x7c,0xe9,0xb5,0x8f,0x3,0x21,0xb1,0xcc,0xde,0x4b,0x6c,0xb6,0xd1,0xef, + 0x53,0x83,0xfd,0xf3,0x5,0x75,0x88,0x5a,0xba,0x64,0xc5,0x5f,0xcc,0xbe,0xe6,0xd6, + 0x3b,0x89,0xe2,0xa1,0x99,0xc6,0x2b,0x5b,0xbc,0xfc,0x97,0x5c,0x2b,0x94,0x4a,0x95, + 0x1f,0xf7,0xbb,0x13,0xf9,0x19,0x9c,0x98,0xf,0x39,0x4,0x7f,0x4d,0xad,0xa1,0x67, + 0x27,0x32,0x5f,0x25,0x50,0x7a,0x24,0xdb,0xf7,0xf7,0x3e,0x71,0xff,0xa5,0x7a,0x3a, + 0x79,0x3a,0xef,0x39,0x4f,0x45,0xe5,0x5b,0xbc,0x67,0x66,0x5d,0x75,0xf3,0x5d,0xb2, + 0xd7,0xff,0x8e,0x95,0xec,0x8f,0x9e,0x4e,0x9e,0x92,0x1c,0xea,0xfb,0xe7,0xee,0x3f, + 0xdd,0xbd,0xb5,0xeb,0xbe,0x5f,0xfc,0x7d,0x70,0xcf,0x3b,0xcd,0xd9,0xc,0xa4,0xe9, + 0x12,0xfb,0xe0,0x4f,0x1d,0x1b,0xe5,0x2b,0xe4,0x92,0xb2,0x23,0xc7,0xfe,0xc6,0xca, + 0x9f,0x52,0x5a,0x39,0xc2,0x71,0x26,0xd3,0x46,0xbf,0x17,0x99,0xaf,0xec,0x2b,0xb1, + 0x34,0xdf,0xf1,0x7d,0xbb,0xea,0x3b,0xee,0xba,0xed,0xdb,0x6a,0x78,0xfc,0x16,0x2e, + 0xef,0x4b,0xca,0x1f,0x28,0x3d,0x79,0x83,0xd0,0xfb,0x80,0x39,0x99,0xc2,0xa2,0x94, + 0x68,0x82,0x7b,0x20,0xf1,0xee,0x23,0xd7,0xf2,0x46,0x2b,0x9a,0xbf,0xf4,0x1b,0x72, + 0x5d,0x4b,0x44,0x13,0x4c,0xb,0x6,0x16,0xaf,0xb8,0x3b,0xb4,0xfb,0x8d,0xcb,0xc, + 0x15,0x52,0x3c,0x36,0xc7,0x68,0x8e,0xa9,0x70,0x90,0xcb,0x6c,0x22,0xcb,0xbd,0xb5, + 0x17,0x6c,0xb9,0x4b,0xe4,0x5b,0xab,0x3f,0x76,0xc5,0xeb,0xd1,0xce,0xff,0x4a,0x1b, + 0xed,0x5f,0x30,0x5d,0x9b,0x35,0xd5,0x58,0x5a,0x70,0xdc,0xab,0x46,0x8c,0x4f,0xc2, + 0xca,0xfe,0xa2,0xd7,0xca,0x4f,0xbb,0xe8,0x7d,0x21,0x1a,0x11,0x9f,0x4e,0x24,0x65, + 0x80,0xe9,0xea,0xc2,0xa9,0xd,0x48,0x72,0x96,0xd1,0x37,0xf1,0x36,0x90,0x3f,0x14, + 0xd0,0xaa,0x9a,0x5f,0x54,0x9f,0x7b,0xf9,0xe,0xde,0x9c,0x2,0x4b,0x4e,0x69,0x9f, + 0x78,0xef,0x5d,0x66,0x94,0xe2,0x23,0x8a,0x27,0x62,0x34,0x27,0x3d,0x16,0xcd,0x29, + 0x3,0x52,0x3c,0x7f,0xd5,0x11,0xab,0xf3,0xf5,0xd4,0x35,0xb5,0x6b,0x26,0xf7,0x12, + 0x23,0xad,0xfb,0x6b,0x82,0xef,0x6e,0xfb,0xb,0x3d,0x1a,0xb9,0x4a,0x40,0x7e,0xbb, + 0x6a,0xce,0xba,0x74,0x2b,0xf7,0x1d,0xc4,0xa7,0x97,0x9f,0x7e,0xe1,0xbf,0x8c,0x6f, + 0x7f,0xea,0x1,0x60,0xc6,0x7,0x1f,0xf9,0x7e,0x2c,0xb,0xa8,0xe1,0xd0,0xd,0xa3, + 0x6f,0xbc,0x70,0x5d,0x68,0xdf,0x8e,0xfb,0xea,0x2e,0xfc,0xc4,0xcf,0x3d,0xd5,0x75, + 0xc9,0x6c,0x86,0xd2,0x63,0xd1,0x5,0x5c,0x7,0xaf,0xae,0xa9,0xdd,0x2e,0x9e,0xd2, + 0x44,0x3c,0xc0,0x49,0x7,0xe,0x5b,0x9d,0xaf,0x54,0x5e,0xd1,0x69,0x8a,0xdf,0x6d, + 0x7,0xaa,0xd5,0xc1,0xae,0xe6,0x74,0x70,0xa2,0x59,0x8f,0x4c,0xac,0x52,0x63,0xe1, + 0xab,0x85,0xa,0x57,0x24,0x69,0xa2,0x76,0xe3,0x15,0xbf,0x98,0x6,0xd1,0x77,0x6e, + 0xf,0x24,0xfc,0xfe,0x8e,0x6,0x5e,0xf4,0x21,0xfb,0x8b,0x5e,0xaa,0xdb,0x78,0xc5, + 0xbb,0x66,0xbe,0xa0,0x62,0xcd,0xd9,0xed,0xa1,0xdd,0x6f,0xe8,0x60,0x50,0xa7,0x4f, + 0xd3,0xc6,0x15,0x30,0x34,0x99,0xe4,0x32,0xdb,0xdf,0x3c,0xef,0x47,0x4a,0x45,0x55, + 0x5a,0x88,0x20,0x8a,0x87,0x12,0x22,0x8d,0x31,0xa6,0x37,0x1a,0x84,0xc0,0x55,0x7a, + 0x3c,0xe8,0x91,0x8b,0x2b,0xd4,0x13,0x52,0x7c,0x1b,0x81,0x93,0xe2,0xf3,0x54,0xd4, + 0xbc,0x60,0xca,0x25,0xf4,0x28,0xfd,0x7a,0x6,0x3,0x42,0xb5,0x74,0x8b,0x71,0xaa, + 0x2d,0xc9,0x55,0x7e,0xc4,0xe3,0xdd,0xdd,0x74,0xd5,0x4d,0xbf,0x13,0x49,0x65,0x7a, + 0xaa,0xca,0x53,0x40,0x48,0x1c,0x18,0xcb,0xb8,0x40,0xa5,0x40,0x60,0xd8,0x68,0x2c, + 0x1e,0x3f,0x9d,0x4,0x91,0xe4,0x41,0x5f,0x63,0x43,0xd4,0x68,0x23,0x54,0x60,0xbe, + 0x7a,0xd9,0xca,0x75,0x5d,0x9c,0x6f,0x96,0xc3,0x87,0xf7,0x34,0xa4,0x86,0x6,0x9b, + 0x68,0x34,0xd2,0xac,0x47,0xc3,0x8b,0xd5,0x58,0xe4,0x6a,0xd1,0xcb,0x9b,0x8a,0xe6, + 0x2d,0xfe,0x77,0x4f,0x55,0x79,0x4a,0x64,0xc3,0xb6,0xfc,0xa4,0x65,0x43,0x44,0xa2, + 0xd7,0x4,0xdf,0xdc,0xf6,0x4f,0x7a,0x32,0x71,0x9e,0xd,0x64,0x92,0xd4,0x48,0xf0, + 0xc6,0xfe,0xc7,0xee,0xdc,0x50,0x32,0xef,0xa4,0x6f,0xd5,0x9c,0xbf,0x79,0x87,0x69, + 0x85,0xce,0x95,0x43,0xa2,0x96,0xaf,0x5a,0xd7,0x6d,0xd7,0x1e,0x88,0x96,0x8c,0x95, + 0x19,0x27,0x5d,0x3c,0x43,0x86,0xfc,0x12,0x58,0x37,0xf1,0xb6,0xfd,0xbf,0xee,0x6c, + 0xdb,0x3f,0xfd,0x11,0x72,0x5d,0xc3,0x6d,0xbe,0xa6,0xc6,0x88,0x89,0xcd,0x7a,0x47, + 0x37,0xd1,0x85,0xf6,0x40,0x22,0x7b,0xdf,0xd9,0x2,0xbc,0x76,0xd8,0x75,0x4d,0x7f, + 0x32,0x2b,0x0,0xc4,0x2b,0xe9,0x44,0x92,0x47,0x18,0xd5,0x33,0x1e,0x4,0xa4,0x5a, + 0x7a,0x8e,0x21,0xb3,0xd5,0xd4,0x7c,0x8e,0x82,0xdc,0xd7,0x70,0xc9,0x96,0x17,0x4d, + 0x55,0x4b,0xc8,0xf2,0x18,0x50,0xdd,0xf0,0x74,0xbb,0x5c,0x1c,0x50,0x4f,0x9c,0x57, + 0x7a,0x74,0xf0,0x4a,0x9e,0x6c,0x57,0xae,0x3b,0xeb,0x25,0x53,0x74,0x92,0xe4,0xcc, + 0xbb,0x81,0x9a,0x3a,0xdb,0x98,0x36,0x53,0x1b,0x9e,0x63,0xe5,0xa4,0xe2,0xe4,0x33, + 0xbe,0x29,0x9,0x56,0xbf,0x68,0xc1,0x71,0xaf,0x91,0xf1,0x0,0x0,0xf0,0x56,0xd6, + 0x1a,0xd6,0xaa,0x53,0x2d,0xbd,0x0,0x72,0x4,0x92,0xc7,0xc3,0xf5,0x7a,0x5,0xe6, + 0x2b,0x77,0xff,0xfe,0xa7,0xef,0x4e,0xd7,0x1c,0xe5,0xe2,0x92,0xc7,0xeb,0xcf,0xbf, + 0x5c,0x6c,0x7c,0x7d,0x32,0x65,0x58,0xb6,0x70,0xf5,0x70,0xd9,0xc2,0xd5,0x5f,0x19, + 0xdc,0xfa,0x87,0x8d,0xc9,0xfe,0xce,0xaf,0xf3,0x36,0x84,0x85,0x2,0x12,0x5d,0x9f, + 0x1d,0x69,0xdb,0xf7,0x2b,0x5d,0xd3,0xbe,0x58,0x7f,0xc1,0xd5,0x6f,0x98,0x32,0x20, + 0x9a,0xca,0x29,0xa5,0x56,0xba,0x24,0xb9,0x58,0x3,0xdd,0x1e,0x9a,0xb1,0x54,0xd2, + 0xf8,0xe2,0x2f,0x45,0x1e,0xfe,0x80,0x56,0xd9,0xcc,0xd7,0x31,0x7,0xc7,0xe3,0xdd, + 0xd9,0xb0,0xe9,0x53,0x8f,0x1a,0xcd,0x75,0x8a,0x5f,0x99,0x36,0xc2,0x16,0x2f,0x94, + 0xe2,0x4f,0x4e,0x8b,0x84,0x2e,0xe6,0x58,0xa1,0x60,0xfd,0x79,0x57,0x6f,0x37,0xf7, + 0xa1,0x1f,0x2a,0xeb,0x1,0x30,0x30,0x20,0x4c,0xd7,0x9b,0x68,0x42,0x95,0x24,0xaf, + 0xff,0xa3,0xe2,0x45,0xf9,0xf5,0xd3,0x4a,0x69,0xc5,0x9f,0xcd,0xce,0x4b,0x22,0x52, + 0xd8,0x50,0x96,0x9,0x49,0x11,0xe6,0xa1,0xc7,0xa,0xbc,0x1e,0x9f,0xf0,0xe8,0xe9, + 0x94,0x61,0x19,0xa5,0xec,0xf5,0xbf,0xe3,0x6f,0x9c,0x1f,0x32,0xb5,0x50,0x68,0xe6, + 0xfd,0x14,0x46,0x69,0x65,0xa6,0x6f,0xd3,0xe3,0x13,0x1e,0x5e,0x5,0x16,0xf1,0x78, + 0xf7,0x55,0xac,0x3e,0xab,0x4b,0x74,0x3e,0xd1,0xd6,0xc3,0xd,0xbc,0xd9,0x96,0xb6, + 0x2c,0xed,0xcf,0x34,0xa7,0x54,0x6f,0x47,0x19,0xa3,0xb4,0x26,0x67,0xc,0x88,0xd7, + 0x7f,0xc4,0x48,0x36,0x66,0x7c,0xbe,0x44,0xa,0xd6,0x9d,0x7d,0xd1,0x8f,0xb2,0x5a, + 0x57,0x0,0xd0,0xb0,0xe9,0xba,0x17,0xd3,0x83,0xbd,0x6f,0xf,0xbf,0xfc,0xf8,0x17, + 0xd4,0x68,0xf8,0x72,0xcb,0x69,0x2d,0x0,0x25,0xde,0x75,0xe8,0xc7,0x63,0xaf,0x3d, + 0x7b,0x6b,0xf5,0x59,0x17,0x1d,0x10,0xf9,0x41,0x7a,0xb0,0x37,0x60,0xe4,0x20,0x1e, + 0x35,0xe4,0x47,0xec,0x24,0x9b,0x9e,0x52,0x79,0x11,0xc8,0xb0,0x95,0xf9,0x3a,0x1, + 0xb9,0xb8,0xe4,0xb1,0xa6,0x4d,0xd7,0xff,0x87,0x71,0x69,0x73,0x7a,0xa6,0x23,0x10, + 0xca,0x4d,0x61,0x45,0x5a,0xf7,0x55,0x33,0xaa,0x1b,0xd6,0xa8,0xcb,0x3e,0xff,0xbb, + 0xd9,0xd6,0x70,0x4b,0xb2,0x3c,0xae,0x73,0x9a,0x82,0x67,0xf2,0x90,0x43,0xef,0xef, + 0x68,0xe0,0x35,0x6f,0x2c,0x59,0xbc,0xe2,0x5,0xb3,0x73,0xa2,0x8c,0xd7,0x56,0xe0, + 0xa3,0xad,0x12,0x82,0x3b,0xdf,0x5c,0xcc,0xab,0xa4,0xd1,0xd3,0xc9,0x33,0x3a,0x7e, + 0xf3,0xdd,0x3d,0x36,0x2a,0x98,0x68,0x6,0x21,0x82,0xd0,0xbe,0x77,0xe6,0x2,0xa7, + 0x85,0x87,0x52,0x5a,0xba,0x2d,0xd3,0xef,0xa7,0x42,0x72,0xac,0x77,0xe,0x27,0x25, + 0x34,0xa0,0x54,0x95,0xa7,0x32,0x8d,0x19,0x3d,0xf2,0x5e,0x4e,0xed,0x7f,0xc8,0x45, + 0xc5,0xed,0x46,0xdf,0x3f,0xd3,0xf3,0xf5,0xd7,0x35,0xfe,0xd0,0xdf,0x32,0x3f,0x68, + 0x86,0x47,0x1f,0x89,0x8,0x1b,0xea,0x62,0xb3,0xae,0xfd,0xec,0x8f,0xf4,0x78,0xec, + 0xa7,0x23,0x2f,0x3f,0x73,0x4e,0x7a,0x6c,0xe8,0xb2,0xa3,0x95,0x74,0xd9,0x75,0x1d, + 0x60,0xac,0x38,0x72,0x68,0xe7,0xcf,0x4b,0xe6,0x2f,0xbc,0xcc,0xd7,0x38,0x2b,0xca, + 0xd7,0x1f,0xbb,0xb8,0x34,0x94,0x7c,0x45,0xed,0x56,0xbe,0xf1,0x23,0xeb,0x2c,0x19, + 0x33,0x8e,0x78,0xbc,0xbe,0xa1,0x4c,0xef,0x13,0x99,0xef,0x34,0x43,0xf3,0xd7,0xd6, + 0xff,0xa0,0xf1,0x8a,0x9b,0x1e,0x30,0x30,0x12,0x46,0x66,0xc1,0xd9,0x66,0x8a,0xbc, + 0x9,0xc6,0xda,0xde,0x5b,0xcd,0x5d,0x88,0x81,0xd2,0x77,0xb3,0x16,0x0,0xca,0x4a, + 0x38,0x4a,0x32,0xc,0x92,0xce,0xa6,0x4a,0x41,0x25,0xfb,0x3b,0x17,0x70,0x14,0x5a, + 0x7f,0xc5,0x8a,0xb5,0x7d,0xa6,0xe7,0xc6,0x99,0x13,0x21,0x24,0x76,0xe2,0x98,0xc9, + 0x91,0xfe,0x95,0x4e,0x4b,0x1a,0x21,0x24,0xe3,0x2,0x4e,0x8f,0xe,0x73,0x53,0x45, + 0x25,0x73,0x4f,0x32,0x65,0x5c,0xb5,0x48,0x68,0x81,0x95,0x94,0x50,0x3a,0x38,0x91, + 0x33,0xe9,0x2b,0x0,0x0,0x6f,0x45,0xd5,0x91,0x1c,0x9d,0xaf,0xea,0x29,0xaf,0xfe, + 0x75,0xd3,0x15,0x37,0x3e,0x61,0xd7,0x80,0x4a,0x49,0x59,0xba,0x71,0xf3,0xb5,0x2f, + 0x0,0xc0,0xb,0x89,0xae,0x83,0x15,0x63,0xef,0xbe,0xb9,0x49,0xd,0x4f,0x7c,0x9c, + 0xa9,0xe9,0xd5,0x60,0xf2,0x3c,0x18,0xa3,0xb4,0x6a,0xe4,0x8d,0xe7,0xaf,0x99,0x2d, + 0x70,0xaf,0x46,0x7a,0x62,0x5c,0xa0,0x8f,0x58,0x49,0x3b,0xb1,0xf1,0x5a,0x9,0x9a, + 0x4a,0x9c,0x6c,0xec,0x38,0x14,0xd,0x65,0x7a,0x9f,0xc8,0x7c,0xa7,0x6d,0x3d,0x2b, + 0x9e,0xd6,0xd2,0xf9,0x4b,0xfe,0xbd,0xe6,0x63,0x9b,0x77,0x5b,0x18,0xc6,0x96,0x73, + 0x20,0x82,0xbd,0xb0,0x18,0xe1,0x31,0x4e,0xb,0x8f,0x9f,0xcc,0x1b,0xa6,0xa8,0x79, + 0xf6,0x8e,0x6c,0x5,0x80,0x52,0xbd,0xdc,0xd8,0x8,0x90,0x50,0xa6,0xb1,0x55,0x4e, + 0x95,0x91,0xe4,0xf5,0xed,0xcd,0x6a,0x5e,0x4c,0x37,0xe,0xf5,0x65,0xf9,0x23,0x2, + 0xa8,0x27,0x62,0xcb,0x9d,0xcf,0xc1,0x48,0xd1,0x4c,0xdf,0xa7,0xc5,0x22,0xc6,0xc6, + 0x55,0x96,0xbb,0x2b,0x4f,0x39,0xab,0xd3,0x14,0xaf,0x12,0x89,0x85,0x9c,0x94,0x50, + 0x9b,0x11,0xbd,0xf5,0x4,0xbf,0xa2,0xa9,0xe2,0xe4,0x33,0xae,0xaa,0x3a,0xf5,0x5c, + 0xcb,0x15,0x39,0x3,0x4f,0x3d,0x70,0x7e,0xa2,0xaf,0xf3,0xbf,0x8d,0x9e,0x29,0x5d, + 0xbc,0xd2,0xf2,0x7c,0x6d,0x57,0x22,0x1e,0xef,0x7b,0xe5,0xcb,0x4f,0xfe,0xd7,0xaa, + 0x53,0x37,0xb6,0x4f,0xd7,0x3b,0x8a,0xe6,0x2c,0xd,0xce,0x9a,0xb3,0xf4,0xf,0x0, + 0xf0,0x87,0xe0,0xbe,0x9d,0x8d,0x91,0x83,0xbb,0x2e,0xd6,0xc2,0xa1,0xcd,0x4c,0x53, + 0x97,0x8,0x3b,0x13,0xc1,0xf1,0x4f,0xe9,0xf1,0xe8,0xdd,0x72,0x71,0x89,0x61,0xfe, + 0x40,0x4f,0x44,0xf8,0x15,0x58,0xb5,0xf5,0xb6,0x7d,0x6b,0xaa,0xbf,0xbb,0x84,0x69, + 0xaa,0xe1,0x55,0x4,0x9e,0x92,0xca,0x61,0x2b,0xf3,0xb5,0x95,0xdf,0x92,0xdc,0xab, + 0x4,0xca,0x9e,0x9,0xcc,0x5d,0xf4,0x74,0xf5,0xa9,0xe7,0x4e,0xde,0x4c,0xa9,0x5b, + 0xd9,0xc,0x62,0xb9,0x75,0x12,0x5d,0x4b,0x26,0x79,0x9e,0x35,0x2d,0x5f,0x71,0x72, + 0xf6,0xa7,0x32,0xa9,0x5e,0xc9,0xc9,0x71,0x85,0x33,0xfe,0x34,0x19,0x5f,0xc0,0x49, + 0x51,0xec,0x25,0x26,0x6f,0x5c,0x54,0xc7,0x46,0x7c,0xbc,0xbc,0xb7,0xa4,0x28,0xfd, + 0x27,0x8e,0x4b,0xd3,0xa9,0xc5,0x4e,0x2b,0x1b,0x49,0x96,0x7,0x32,0x7d,0x1f,0x4d, + 0x26,0x38,0xd1,0x82,0xef,0x90,0x59,0xda,0x50,0xce,0x1d,0x21,0x4a,0x71,0x49,0xab, + 0xd1,0x98,0x2,0xd5,0x2d,0x5a,0xc5,0xb2,0x35,0x9d,0xc4,0x86,0x5b,0x32,0xb5,0x58, + 0x88,0x13,0x9d,0x4a,0xc3,0xfe,0xfa,0xe6,0x88,0xd1,0x62,0x15,0xa9,0xc6,0xb1,0x31, + 0x9c,0x4c,0x78,0xab,0xaa,0x6f,0x6b,0xde,0xfc,0xa9,0x7b,0x25,0x8f,0x87,0x5a,0x53, + 0x22,0xe2,0xa8,0x3c,0x69,0x75,0x7f,0xe5,0x49,0xab,0xef,0x4,0x80,0x3b,0xfb,0x9f, + 0x7e,0xe0,0xa2,0xe4,0x70,0xff,0x97,0x99,0xae,0xcf,0xe1,0xab,0x29,0x5a,0x3b,0xf4, + 0xdc,0x9f,0x2e,0x69,0xbe,0xf4,0x7a,0xc3,0x73,0x53,0x34,0xcd,0x2d,0x42,0xd0,0x2b, + 0x96,0x9d,0x62,0xb,0xcf,0x1,0x0,0x26,0xde,0xdb,0xb1,0x12,0x8c,0xb,0x7e,0x68, + 0xc9,0xec,0x79,0xdd,0x19,0xd7,0x4d,0xda,0xb9,0x22,0xf,0xb9,0xb8,0xe4,0xe1,0xb9, + 0xd7,0x7f,0xe1,0x5b,0x36,0xb,0x92,0xe9,0x7,0xad,0x9c,0x3,0x1,0x2e,0xe3,0x74, + 0xbd,0x96,0x63,0x41,0x7,0x3d,0x45,0x15,0xa9,0x6c,0x4,0xfe,0xa8,0xb2,0x36,0x6e, + 0x19,0x20,0x49,0xa1,0x8c,0xcc,0xe6,0x54,0x60,0x29,0x65,0x55,0xa6,0xef,0xee,0x8, + 0x1f,0x39,0xc4,0x3d,0x38,0x25,0x29,0xbe,0x7e,0xd3,0x86,0x70,0x3a,0xc,0x88,0xd7, + 0x9b,0xf1,0xca,0x5b,0xaa,0xa9,0x9c,0x68,0xc1,0x67,0xca,0xeb,0xa3,0xaa,0x2a,0x31, + 0x4d,0x33,0x2c,0x58,0xf0,0x56,0xd7,0x18,0x8e,0x49,0x35,0x6d,0x21,0x27,0x2a,0xea, + 0x92,0x8b,0x8a,0x35,0x93,0x1e,0x5c,0x6,0x3,0x6a,0xdc,0xdd,0x54,0x52,0x14,0x6e, + 0xda,0x84,0x37,0x5f,0x9b,0xc,0x47,0x54,0xf6,0x15,0x6d,0x2f,0x5f,0x7d,0xca,0x4f, + 0xaa,0x56,0x9d,0xd1,0x7,0x33,0x88,0xe6,0x4b,0x6f,0xf8,0xb3,0x9e,0x4a,0x3e,0xdf, + 0xfb,0xf0,0x9d,0x7f,0xaf,0xc6,0xc2,0xdc,0x66,0xa9,0x6a,0x24,0x74,0x32,0x91,0xe4, + 0x3f,0x71,0x9c,0xe,0x6e,0x24,0xac,0x4,0xec,0xbb,0x3a,0x3a,0x35,0xd2,0x6b,0xd8, + 0xd0,0x53,0xf6,0x7a,0xdf,0x2a,0x9e,0xbb,0x28,0x98,0xed,0x19,0x9b,0x16,0x19,0x0, + 0x0,0x20,0x0,0x49,0x44,0x41,0x54,0x7c,0x1,0x80,0x2,0x21,0x71,0xc1,0xc,0x4f, + 0xc0,0x48,0xa3,0xd3,0x64,0xfc,0x1c,0xaa,0xaa,0x92,0xec,0xf3,0xdb,0xe8,0x2d,0x10, + 0x67,0x23,0x10,0xde,0x22,0xe2,0xb5,0x2e,0x91,0x64,0xb9,0x3b,0xdb,0xf4,0x55,0xb8, + 0x6d,0x6f,0xb,0xcf,0x64,0x4a,0x5e,0x6f,0xc6,0x34,0x3,0xd3,0x34,0x43,0x66,0xfb, + 0x1b,0x1a,0x4c,0xcf,0x2d,0x3d,0x31,0x3c,0x8b,0xef,0x39,0xf8,0x3f,0x32,0x2e,0x63, + 0xac,0xd4,0xe9,0x5,0x2f,0xfb,0x8a,0xa7,0xfc,0x3e,0x75,0x6c,0xd8,0xc7,0x74,0xe3, + 0xc2,0x7,0x25,0x50,0xd2,0x6a,0x86,0x36,0xc1,0x3d,0xaf,0xb5,0x0,0x18,0x1e,0x7c, + 0xa2,0x15,0x4b,0xd7,0x64,0x54,0xca,0xc9,0xbe,0x2e,0x7e,0x7f,0x21,0x8f,0xcf,0xb6, + 0x5c,0x38,0xd5,0x54,0x4e,0x4,0xe6,0x6f,0x33,0xfa,0xef,0x22,0xf3,0x5,0x42,0xa2, + 0x44,0x92,0x6,0x5,0x57,0x1a,0x3,0x42,0xe2,0x92,0x24,0x8f,0x81,0xac,0x4c,0x48, + 0x5e,0xcf,0x40,0x51,0x4d,0xe3,0x5b,0x35,0x67,0x5f,0xbc,0x47,0xf2,0x78,0x29,0xe4, + 0x8,0x64,0x9f,0x5f,0x6f,0xb9,0xee,0xf3,0x3f,0xe8,0xbc,0xe7,0x67,0x8d,0x7a,0x2a, + 0x79,0x81,0x71,0x98,0x97,0x36,0x74,0xb6,0x52,0x83,0xbd,0xc5,0x8c,0x52,0xe3,0xa, + 0x2c,0xc5,0x63,0x2e,0x7d,0xa5,0x69,0x19,0xe5,0x23,0xde,0xd9,0x5a,0xa9,0x27,0x12, + 0x86,0x7,0x79,0x3d,0xe5,0xd5,0x4f,0x64,0x1a,0x23,0x35,0xd4,0xc7,0x9d,0xaf,0xec, + 0xf1,0xbe,0x35,0xef,0xc6,0x2f,0x7d,0x56,0x64,0xaa,0x1d,0xf7,0xdc,0xf6,0x6b,0x5d, + 0x4d,0x9f,0x69,0x10,0xc5,0xd5,0xd,0x3e,0xf7,0xe8,0xc6,0xe6,0x4d,0xe6,0x2e,0xd0, + 0xe3,0x48,0xbe,0xa3,0xbd,0xb0,0x88,0x71,0x98,0xaa,0x13,0x60,0x9c,0x4d,0x6e,0x59, + 0x89,0x18,0x31,0xd5,0x50,0xc0,0xc6,0x46,0xe6,0xf2,0x9e,0x51,0x4a,0x2b,0x76,0x4d, + 0x35,0xfe,0xc4,0xfe,0x5d,0xd,0x9c,0x33,0x9,0x7a,0xc5,0xc2,0x55,0x3,0x66,0xe7, + 0xa6,0x86,0x26,0x4e,0xe2,0x3d,0xe3,0xaf,0x6e,0xde,0x7b,0xec,0xb8,0x34,0x9d,0x92, + 0x79,0xd5,0x60,0xc4,0xe3,0xdd,0xe1,0x29,0x29,0x79,0xd1,0xce,0xc5,0x5e,0xdc,0x32, + 0xef,0xf5,0xa9,0xbe,0x2f,0x74,0x60,0xe7,0x5c,0x4e,0x18,0xf,0xfe,0xaa,0x86,0x56, + 0x33,0xb4,0x49,0xe,0xf7,0x2e,0xe2,0x44,0x2,0xbd,0x9e,0xf2,0xaa,0x24,0x68,0x53, + 0x7,0x10,0xe1,0x83,0x7b,0xf9,0xd5,0x38,0x5e,0x4f,0x5b,0xb6,0xb2,0x74,0x7c,0x1a, + 0x22,0x25,0x33,0x4d,0x33,0x94,0x2d,0xb9,0xc8,0x6f,0xf8,0x2e,0x91,0xf9,0x7a,0x8a, + 0xcb,0xfe,0x38,0xe7,0x93,0x9f,0xfd,0x91,0x65,0x46,0x6a,0x1a,0xe4,0x12,0x8,0x0, + 0x9b,0x75,0xd1,0x27,0xfe,0xa1,0xeb,0xc9,0x7b,0x5f,0x37,0x6a,0xcb,0x43,0x35,0xbd, + 0xd9,0x90,0x86,0x87,0xf7,0xcc,0xe3,0x3a,0x88,0x3e,0x9f,0x2d,0x3c,0x7,0x0,0x18, + 0xd9,0xf1,0xea,0x27,0xc,0x9d,0x1c,0x42,0x92,0xb5,0xeb,0xce,0x7d,0x3e,0xe3,0x7c, + 0xdb,0xf7,0xcd,0xe7,0x3b,0xb4,0xbe,0x36,0xd1,0xf9,0x78,0x2b,0x6b,0x1e,0x4d,0xc, + 0xf7,0x9f,0x69,0xe8,0xb0,0x8e,0xe,0x5e,0x7,0x0,0x36,0x1a,0x10,0xe1,0x32,0x5e, + 0xeb,0x55,0x58,0x40,0xa9,0xa1,0x45,0x4f,0xf6,0x74,0x94,0xf2,0x14,0x11,0x10,0x88, + 0x67,0xbd,0x6e,0xc2,0x13,0xdc,0xf6,0xd3,0x25,0x8b,0x97,0xed,0x9c,0xea,0xdf,0x13, + 0x83,0x5d,0x9c,0xb,0x58,0xa4,0x90,0xe4,0xf5,0x99,0xe,0xd,0x69,0x2a,0xb1,0x8c, + 0xe3,0x49,0xc6,0xab,0xd7,0x9d,0xd9,0x7e,0xbc,0xa7,0xd5,0x57,0xc2,0x35,0x84,0x45, + 0x25,0xaf,0xb4,0x5c,0xf9,0x99,0x3b,0x9d,0x50,0x0,0xa9,0xf1,0x11,0x5e,0xea,0x45, + 0xab,0x58,0x75,0x4a,0x97,0x29,0x5e,0xc5,0xc2,0x8b,0x8c,0x3d,0x7a,0x4f,0x9b,0x2a, + 0x67,0x8e,0x1e,0x92,0x11,0x7e,0x75,0x8b,0x14,0x28,0x33,0x1c,0x43,0x14,0x13,0xfb, + 0xdf,0x99,0xcd,0x89,0x96,0x40,0x2e,0xab,0x69,0xb7,0x3a,0x5f,0x52,0x5c,0x6c,0xcb, + 0x7c,0x73,0x12,0xf5,0x4d,0x9,0x22,0x2b,0x87,0x98,0xa6,0xae,0x32,0x70,0x30,0x1b, + 0xd3,0x94,0x12,0xe2,0x99,0xba,0xcc,0x3e,0x31,0x3e,0xc6,0x4d,0x1,0x4a,0xfe,0x40, + 0xbb,0x1d,0x34,0x4c,0xf5,0x74,0x94,0xaa,0xd1,0xe0,0xa7,0x8c,0xd3,0x57,0xbe,0x17, + 0xa5,0x59,0x73,0xa2,0x99,0xf2,0x65,0x22,0xf3,0x25,0x45,0x81,0x56,0xd1,0xf9,0x56, + 0x9d,0x79,0xd1,0xf3,0x7d,0x8f,0xfd,0x3e,0x2,0x6,0xd9,0x9,0x5d,0x4d,0x9f,0x36, + 0xbc,0xfb,0xb5,0x39,0x95,0xeb,0xce,0xed,0xb4,0xc5,0xf8,0x3b,0xdd,0x8d,0xd7,0x88, + 0x18,0xd1,0x70,0xb0,0xd8,0xea,0x18,0x86,0x4a,0x29,0x95,0x3c,0x85,0xe3,0xd5,0x76, + 0x15,0x2f,0x5c,0x35,0x36,0x15,0xc3,0xb5,0x48,0xc8,0x38,0x9f,0x4e,0x48,0x2c,0x9b, + 0x79,0x51,0x35,0x6d,0x58,0x4d,0x45,0x14,0xcf,0x7e,0xed,0x84,0x9c,0x65,0x34,0x12, + 0x2a,0xe2,0x72,0xcb,0xab,0x84,0x9c,0x52,0x36,0xe9,0x44,0x8c,0x97,0x77,0xee,0xa4, + 0x81,0x52,0xd5,0x4c,0xde,0x84,0xa6,0x52,0xc6,0x8b,0x8b,0xe3,0x99,0xe9,0xf1,0x38, + 0x77,0x73,0xd2,0x5b,0xd5,0xd0,0x66,0xc7,0xf7,0xa7,0x86,0x7,0xf8,0x25,0xcc,0xb, + 0x4f,0xb2,0x61,0xbe,0x35,0x6d,0x90,0x23,0x8,0xed,0xdd,0xd1,0x90,0xe8,0x69,0x5b, + 0xee,0xab,0x6b,0x38,0x52,0x79,0xca,0x6,0x5b,0x5a,0x8d,0x4b,0x3e,0xdf,0x5e,0xdd, + 0xc0,0x80,0x0,0x80,0x47,0x1b,0xef,0xf7,0x79,0x1b,0x67,0xc5,0xa7,0xa6,0x21,0xbf, + 0x8a,0xcd,0x5b,0x5d,0xd7,0x66,0x47,0xb,0x93,0x91,0x57,0x9e,0xfc,0x17,0xa0,0xd4, + 0x70,0xbf,0xd6,0x57,0xd3,0xf0,0xb8,0xd1,0xbb,0x84,0xe6,0x5b,0x5e,0xd9,0x2a,0x3a, + 0x5f,0x4f,0x5d,0x75,0x52,0xf6,0x17,0x3f,0xad,0x27,0x62,0x46,0x7d,0x4,0x49,0xec, + 0xf0,0xfe,0x6b,0xab,0xd6,0x9f,0xf5,0x7d,0xe7,0x3,0xcd,0xcc,0x6,0x44,0x50,0x37, + 0x50,0x62,0x44,0x8c,0xb2,0x25,0x8b,0x87,0x43,0x6f,0x6f,0x33,0xee,0x55,0xa5,0x69, + 0xf5,0xd9,0x8,0x40,0xbc,0xfd,0x50,0x25,0xd3,0xb4,0xc5,0x1c,0x1,0x7e,0x27,0xd3, + 0xd8,0x7a,0x92,0xb7,0xc0,0x19,0x31,0x3b,0xaf,0xf1,0xd7,0x5f,0x5a,0xc0,0x28,0xad, + 0xe7,0x84,0xb0,0xef,0x9d,0x38,0x6e,0x49,0x73,0xd3,0x58,0x68,0xd2,0x68,0x13,0x3, + 0x8b,0xa6,0xdb,0xd5,0xeb,0x87,0x6f,0x41,0x8c,0x95,0xbd,0xa4,0x78,0x5a,0xcd,0xce, + 0x85,0xaa,0xc6,0xa5,0x91,0x4a,0x51,0xc0,0x70,0x4c,0xaa,0x25,0x79,0xde,0x9d,0x5e, + 0xb1,0x76,0x5d,0x87,0x1d,0x34,0xa2,0xd1,0xb0,0xf1,0xbb,0x24,0x69,0xa4,0x68,0xee, + 0xdc,0x90,0x61,0xf,0x2c,0xfe,0x7c,0x59,0xd9,0x92,0xe5,0x6d,0x8e,0xf1,0xf4,0xd8, + 0x8,0x6b,0xd7,0x5b,0xb3,0x92,0x7d,0x9d,0xcb,0xb4,0x48,0x64,0x39,0x4d,0x26,0x97, + 0x31,0x2d,0xbd,0x1c,0x18,0xab,0x4,0x0,0xd0,0x42,0xe3,0x77,0x55,0x9d,0x7a,0xf6, + 0xf7,0xec,0x79,0x13,0xe3,0x64,0x1f,0x48,0x32,0x93,0xf1,0x98,0xa4,0x61,0x9a,0xcb, + 0xf3,0xb2,0xa5,0x2b,0x2c,0x1b,0xbb,0x81,0x27,0x1f,0xb8,0x50,0x4f,0x24,0x2e,0xe3, + 0xcc,0x35,0x58,0x7d,0xde,0xa6,0x57,0xd,0xe5,0x86,0x3f,0x5f,0x28,0x59,0x74,0x92, + 0xa9,0x3d,0x9b,0xa2,0xa6,0x96,0x47,0xa3,0xed,0xef,0x5f,0x6b,0xec,0xac,0x44,0xaf, + 0x52,0x87,0x7,0x7e,0xe2,0xa9,0x6b,0x4c,0xda,0xc1,0x34,0x27,0x23,0x10,0xc3,0x7c, + 0x9f,0x5c,0x14,0xd0,0x88,0x24,0xf7,0x30,0xaa,0xcf,0xcd,0xfc,0xf5,0xc6,0x3d,0xa3, + 0x32,0x21,0xb8,0xf3,0x8d,0x4b,0x79,0xef,0x2f,0x6a,0x9a,0xf3,0x50,0x66,0x66,0x1b, + 0x57,0x19,0x31,0x4a,0x1b,0x68,0x2a,0x29,0x4b,0x26,0x2a,0x1c,0x92,0x7d,0x9d,0x67, + 0xf3,0x9e,0xf1,0xd7,0xd6,0x6d,0xff,0x88,0xa7,0x51,0x5b,0x9f,0x22,0x92,0x34,0xc8, + 0x28,0xcd,0xdc,0x80,0x31,0x95,0xb2,0xa5,0x25,0x6,0xd1,0xf8,0x51,0xc,0x55,0x8d, + 0x17,0x82,0xe4,0xf3,0xb7,0x8a,0x8c,0xf3,0x61,0x84,0x19,0x1a,0xf4,0xf1,0xba,0x11, + 0x78,0x2b,0xeb,0xf,0x1b,0x8e,0xc9,0xe9,0xcb,0x45,0x24,0xb9,0x53,0xf1,0x94,0xa9, + 0x60,0xc3,0x76,0x0,0x4d,0xa5,0x38,0x11,0x98,0xd2,0xc6,0xfd,0x7e,0xee,0x7c,0xa5, + 0x3e,0x5f,0x4d,0x4b,0x1c,0x1c,0xdc,0xbe,0x18,0xdf,0xf5,0xc6,0xac,0xd0,0xee,0x57, + 0x1f,0x6,0xc6,0x32,0x16,0xb6,0xd0,0x44,0xfc,0x5c,0xa2,0xc9,0xdf,0xb5,0xe3,0x7d, + 0x34,0x95,0x5a,0xc3,0x89,0xf2,0x27,0x2c,0xf2,0xbc,0xcf,0x5b,0xd9,0x94,0xb4,0x42, + 0xc3,0x91,0x97,0x9f,0x58,0x93,0x1a,0xe8,0xfb,0xf,0xde,0x73,0x72,0xa0,0xe4,0x41, + 0xae,0x7c,0xf1,0x79,0x3e,0x58,0xd4,0xb4,0x30,0x6c,0x66,0xbe,0xb5,0x1b,0x2e,0xdb, + 0x1d,0xeb,0x38,0x7c,0x84,0x51,0x3d,0x73,0x74,0xc3,0x58,0xd9,0xc8,0xf6,0x17,0x36, + 0x35,0x5f,0x71,0xcb,0xa3,0x36,0x68,0x8,0x87,0x9b,0x29,0x72,0x16,0x92,0xe4,0xf1, + 0x1c,0xd1,0x53,0x99,0xd,0x8,0x63,0xb4,0xde,0x8c,0x32,0xfa,0x90,0x57,0x91,0xd0, + 0x55,0x9c,0x54,0xd1,0xbe,0xda,0xd,0x97,0xed,0xce,0xc4,0x2c,0xa6,0x69,0xbc,0x70, + 0x53,0x9,0xef,0xdf,0x5f,0x5b,0xb9,0xea,0xd4,0x1,0x21,0xb3,0x4d,0x75,0xa2,0x86, + 0x83,0x9f,0xe0,0x7a,0x31,0x67,0x7d,0xfc,0x9d,0x29,0xbf,0x57,0x56,0xba,0x80,0xa6, + 0x1b,0xd,0x3c,0xf8,0x3a,0x51,0x3a,0xa5,0xfa,0xba,0x2,0x43,0xaf,0x3c,0xf1,0xd, + 0x5f,0x55,0xdd,0xd6,0x9a,0x73,0x37,0xbf,0x2a,0x17,0x5,0x84,0x45,0x36,0x3d,0xdc, + 0xef,0x67,0x94,0x1a,0xdf,0x83,0x5e,0x5c,0xd2,0x6a,0x2e,0x3d,0xb2,0x67,0x1,0x18, + 0xb7,0x45,0xd1,0xcb,0x57,0xad,0xcf,0xe8,0x49,0xa6,0x6,0xba,0xf9,0xd5,0x38,0x1e, + 0x8f,0x7d,0xed,0xbc,0x75,0x4e,0x9,0xb3,0x62,0x5c,0xc2,0x2c,0x32,0x5f,0x90,0x3d, + 0x8e,0xa4,0xaf,0x88,0xfc,0xbf,0x7b,0x94,0x55,0x6b,0xd6,0xf6,0x86,0x76,0xbf,0xa6, + 0x1a,0x2d,0x6f,0x46,0xf5,0xb9,0xe3,0x3b,0x5f,0x6e,0xa9,0x5e,0x7f,0x56,0x97,0x95, + 0xf7,0x26,0xbb,0x3b,0x4b,0x78,0x19,0x2,0x90,0xe4,0xa1,0x63,0xe7,0x77,0x3c,0xd, + 0xfb,0x8a,0x18,0xa5,0x4d,0xc6,0x3c,0x57,0xda,0x32,0xfd,0x5e,0x4,0x43,0x5b,0x1f, + 0x39,0x33,0xd6,0xdb,0x75,0x3b,0x30,0x56,0x64,0xac,0x4b,0x94,0xd6,0xc6,0x4b,0x2e, + 0xbf,0xcd,0xe8,0x5d,0x22,0xf3,0x5,0xd9,0x93,0xd5,0x7c,0x3d,0xa5,0x65,0x8f,0xa4, + 0x43,0x13,0x7f,0x6f,0xec,0xa4,0x8d,0x5f,0x4f,0x64,0xed,0x91,0xfc,0x8a,0x40,0x28, + 0x10,0x2e,0x41,0x3c,0x9e,0x23,0x90,0x4a,0x9e,0x67,0x60,0x3d,0xfd,0xa3,0xaf,0xff, + 0x79,0x51,0xed,0x39,0xe7,0x1f,0x16,0xfd,0xc2,0xbe,0xc7,0xef,0xdf,0xcc,0x34,0xcd, + 0xb0,0xda,0xc9,0x53,0x5e,0x7d,0x77,0xa6,0xb9,0x4d,0xec,0xd9,0x51,0xf,0x2,0x65, + 0xb3,0xe9,0xc1,0x23,0x8b,0xc9,0x9a,0xb5,0xfd,0x22,0x73,0xea,0x7f,0xea,0xf,0x17, + 0x31,0x5d,0x37,0x54,0x3c,0xb2,0xdf,0xbf,0x4d,0x29,0xf6,0x68,0x30,0x85,0x55,0x93, + 0x14,0x4f,0xa7,0xae,0xa6,0x4f,0x37,0x48,0xf5,0x35,0x89,0xa,0xdf,0xe8,0xdb,0xcf, + 0x5f,0xad,0x27,0xe2,0x57,0xc6,0xfb,0x3a,0xaf,0xec,0xfe,0xc3,0xed,0x21,0xd9,0x5f, + 0xbc,0xd5,0x5f,0xdb,0xf8,0x64,0xed,0x79,0x9b,0xde,0xe5,0x95,0x7c,0x86,0xf,0xef, + 0x9e,0xf,0xbc,0xa,0xac,0xfa,0xfa,0xc3,0x66,0x16,0x42,0x3a,0x38,0xc4,0xf3,0x24, + 0xbb,0xbd,0x15,0x25,0x29,0xc8,0x60,0xed,0xc3,0x6d,0xbb,0xb9,0xd5,0x2d,0xe0,0xf1, + 0xb6,0x5a,0x51,0x26,0x1f,0x5a,0xb2,0x64,0x52,0xe6,0x9d,0x57,0x91,0x8b,0x7c,0x86, + 0xef,0x12,0x99,0xaf,0xe4,0xb3,0x67,0xbe,0xe6,0x8c,0x89,0xcc,0x64,0xaf,0xef,0x35, + 0x3d,0x95,0xb8,0xc2,0x50,0x6,0xf6,0xef,0xfc,0x4e,0xc5,0xca,0x75,0x9f,0x96,0xfd, + 0xd9,0x9f,0x2f,0x18,0x79,0x63,0xdb,0x8d,0x3c,0x39,0x92,0xfc,0xfe,0xb7,0x33,0xcb, + 0xe1,0x7e,0x11,0x9e,0x67,0x65,0x84,0xb5,0x68,0xc4,0x33,0xf8,0xf4,0x43,0xb7,0xa4, + 0x43,0x13,0x7f,0x3,0x0,0xbc,0x3b,0x35,0xd2,0x25,0xb,0x97,0xfd,0x9d,0xb7,0xa2, + 0x3e,0x65,0xbc,0x6e,0xf6,0xb,0x54,0x60,0x79,0x5b,0xb3,0x99,0x6f,0x60,0xe9,0xea, + 0xc7,0xd2,0x6f,0xbd,0xf4,0x15,0x23,0x27,0x8c,0x69,0xea,0xaa,0x91,0x97,0x9f,0x5b, + 0x56,0xbb,0xe1,0xc2,0x3,0x47,0x8d,0x73,0x76,0xb2,0x45,0xcd,0x57,0x61,0x59,0xb8, + 0x91,0x90,0xff,0x2e,0xd9,0x57,0xcc,0xed,0x94,0x19,0xef,0x38,0xfc,0x79,0xd1,0xef, + 0x9b,0x78,0x6f,0x67,0x5d,0x6a,0x78,0xf0,0x5b,0xc6,0x2b,0x45,0x1a,0xad,0xbf,0x60, + 0xf3,0xd3,0x99,0xbd,0x85,0xce,0x45,0x22,0xef,0x4a,0xc,0xd,0xdc,0x2a,0x64,0xb2, + 0x75,0x9d,0xa4,0xc7,0x86,0xff,0x8a,0xf7,0x9c,0xaf,0xba,0xf6,0xcf,0x99,0x6e,0xeb, + 0x93,0xbd,0x5e,0x43,0x8f,0x8f,0xa9,0xa9,0x33,0x62,0xad,0xef,0x57,0xf1,0x6e,0x21, + 0x54,0xc3,0x23,0x5e,0x35,0x34,0x71,0xd3,0x31,0x6,0xba,0x5c,0x4f,0xc4,0xae,0x8d, + 0x75,0xb7,0xdd,0xdd,0x75,0xd7,0xed,0x2f,0x75,0xdd,0xf7,0xeb,0x7f,0x88,0x1e,0xda, + 0x5d,0x93,0xe9,0xf7,0xe9,0xf1,0x51,0x5e,0x1e,0x37,0x5d,0xb9,0xe6,0x8c,0x6e,0xd1, + 0x9b,0x28,0x41,0x92,0x99,0x16,0x8f,0x71,0x2a,0xb0,0x94,0x56,0xa3,0xdf,0xa7,0xc7, + 0x83,0xdc,0xd,0x69,0x25,0x10,0x68,0x35,0x33,0xa7,0x4c,0x7f,0xc1,0xf7,0xde,0x9a, + 0xcd,0x53,0x2a,0x9e,0xb2,0x4a,0xeb,0xf3,0x2d,0xe,0x1c,0xb6,0x63,0xbe,0x66,0xff, + 0x94,0xf2,0xf2,0xed,0x5c,0x79,0x56,0xd5,0x53,0x7b,0x1f,0xbd,0xfb,0x6f,0xb2,0x7d, + 0x47,0xef,0x1f,0x7f,0x7f,0x8b,0x1a,0xe,0x7e,0x85,0xf7,0x9e,0xa2,0x9a,0xc6,0x17, + 0x2d,0xc8,0x21,0x28,0xc5,0x26,0x79,0xe,0x0,0x83,0xcf,0x3c,0xb4,0xa1,0xe7,0x81, + 0xdf,0x3e,0x99,0xe,0x4d,0xfc,0x5f,0x1,0xe3,0x1,0xde,0xf2,0xca,0x1f,0xd7,0x6e, + 0xb8,0xf8,0x20,0x6f,0x6c,0x91,0xf9,0xca,0xfe,0xe2,0xac,0x78,0x5e,0x79,0xf2,0xfa, + 0x21,0xe2,0xf1,0xbd,0xca,0xd5,0xa3,0x3d,0x47,0xae,0xcf,0x74,0x93,0x67,0x6e,0x46, + 0x20,0x0,0x84,0x37,0x59,0x6f,0x65,0x45,0x5b,0x7a,0x6c,0xc8,0xd8,0xeb,0x4b,0x25, + 0x3e,0x3e,0xb6,0xe3,0xcd,0x9f,0x54,0xaf,0x3f,0xab,0x87,0xf7,0xc2,0xe0,0xce,0x37, + 0xbe,0x7,0x8c,0x19,0xb6,0x5b,0xf6,0xd5,0x37,0x7f,0xcb,0x53,0x51,0x95,0xd1,0x63, + 0xd0,0xc2,0x51,0xa1,0x76,0x3,0x4c,0x55,0x4f,0x1d,0xfa,0xf3,0x63,0xa7,0xd7,0x5f, + 0x62,0x7c,0x7f,0x41,0xdf,0x23,0x77,0x7f,0x92,0x69,0xda,0x52,0x4e,0xfe,0xb3,0xab, + 0xfe,0xa2,0xab,0x5e,0xce,0xf8,0xdf,0x8b,0x4b,0x3b,0x20,0x34,0x61,0x48,0xca,0xf1, + 0x9d,0x6f,0xdc,0x10,0x58,0xb2,0xe2,0x36,0xc3,0x48,0xe8,0xf1,0x47,0xbe,0xce,0x28, + 0x6d,0x99,0x3a,0x3d,0x41,0xeb,0xf5,0x78,0x74,0x8b,0x12,0xa8,0xfc,0x59,0x46,0xda, + 0x24,0x8d,0x95,0x3d,0x51,0x94,0x23,0x92,0xaf,0xc8,0x94,0x67,0x4a,0x53,0x69,0xe3, + 0x54,0x86,0xc7,0xd7,0x6a,0x2c,0x1f,0x31,0xae,0xc1,0xf7,0x55,0xd5,0xdb,0x92,0x12, + 0x4a,0xe,0xd,0x73,0x15,0x41,0xe9,0x82,0xa5,0x6d,0x56,0xe7,0xeb,0xad,0xac,0x3e, + 0xec,0x74,0x4,0x2,0x0,0x50,0xb1,0x7c,0xd5,0xab,0x43,0xc3,0x83,0x8c,0xe7,0x2d, + 0xeb,0xd1,0xc8,0xe7,0xbb,0x7e,0xf7,0xb3,0xe6,0x92,0x93,0x96,0xff,0xb4,0xe6,0xcc, + 0x73,0x84,0x36,0xaa,0x87,0xb7,0x3d,0x7b,0x52,0xbc,0xab,0xf3,0x1a,0x3d,0x11,0xbb, + 0x89,0xaf,0x39,0xc8,0x58,0xed,0x79,0xe7,0xef,0xca,0x44,0x3,0x2d,0x19,0x5d,0xc8, + 0xa7,0x61,0x95,0x61,0x14,0xa7,0xc7,0x63,0x4a,0xe8,0xfd,0x3,0x35,0xe9,0xfe,0xde, + 0x45,0xc9,0xd1,0x91,0xb,0x68,0x2a,0x71,0x81,0x99,0xbb,0x4d,0x88,0xc7,0xf3,0xfa, + 0xac,0xeb,0x6e,0xfa,0xad,0x8,0x9f,0x84,0xe6,0x5b,0x55,0x99,0x35,0xcf,0xbd,0x55, + 0xd5,0xf,0xa7,0x86,0xfa,0x37,0x18,0x47,0xcf,0xf1,0xcb,0x52,0x3d,0xad,0xdf,0xf3, + 0xcf,0x9d,0x17,0xcd,0x5a,0x40,0x88,0x3d,0xbd,0xb0,0x84,0x7,0xe1,0x11,0xa4,0x6e, + 0xe3,0x5,0x7b,0x62,0x9d,0xed,0x7b,0x99,0xa6,0x19,0xf5,0xc4,0x92,0xc3,0xbb,0xdf, + 0xfc,0x1d,0x8d,0x5,0xbf,0x54,0x77,0xfe,0xc5,0x53,0x5e,0xd3,0x35,0xf6,0xd6,0xeb, + 0xb3,0x23,0xfb,0x76,0xff,0x13,0x53,0x53,0x67,0x1b,0x47,0x3c,0x45,0x4f,0xce,0xba, + 0xfa,0x13,0x7f,0x6,0x83,0x9d,0x2a,0x3d,0x1d,0x17,0x6e,0x31,0x11,0xeb,0x39,0x72, + 0xdb,0xe0,0x53,0xf7,0xff,0x7d,0xe3,0xe5,0xd7,0xbc,0x38,0x55,0xe4,0xd1,0x75,0xef, + 0xef,0xfe,0x56,0x8f,0x86,0xb9,0xd1,0x87,0xa7,0xa2,0xe2,0xe,0xc9,0x2f,0xe9,0x99, + 0xe6,0xd5,0x78,0xf1,0xa6,0x97,0xbb,0xee,0xfa,0x4d,0x17,0xa3,0x34,0x63,0x1f,0x21, + 0x35,0x12,0xba,0x75,0xf0,0xa9,0xfb,0xdf,0x6b,0xbc,0xfc,0x9a,0x97,0xa6,0x9a,0x4b, + 0xef,0x1f,0xee,0xfe,0xac,0x9e,0x88,0x5d,0x6f,0x9c,0x4f,0x2d,0xfd,0x6d,0xd1,0xbc, + 0x96,0x48,0xa6,0x79,0xd0,0x94,0x71,0xbf,0x2a,0x49,0xf6,0x98,0x5f,0x4,0xba,0xba, + 0x98,0x17,0x3d,0x18,0x8d,0x49,0x53,0xfc,0x6a,0x9c,0xca,0x53,0x4e,0x39,0x62,0x87, + 0x42,0xa6,0x71,0xe3,0xf2,0x6e,0x20,0x64,0x2c,0xb0,0x64,0xe1,0x84,0x91,0x7c,0x9, + 0xcc,0x97,0x56,0x2c,0x5b,0x61,0xeb,0x1d,0x16,0xa2,0x28,0x39,0x69,0xf9,0xd8,0xf0, + 0xf6,0x6d,0x7,0x98,0xa6,0xf1,0x9a,0x77,0x12,0x3d,0x95,0xb8,0x34,0xb4,0xfb,0xdd, + 0x4b,0xa2,0xef,0xef,0xdd,0x2a,0xfb,0x8b,0xf7,0x11,0xbf,0x7f,0xc0,0x53,0x1a,0xe8, + 0x93,0x4b,0x2a,0x42,0x7a,0x34,0x58,0xae,0xc6,0x12,0xd5,0x2c,0x9d,0xae,0xd2,0x53, + 0xa9,0x59,0x34,0x1e,0xbb,0x98,0x51,0x5d,0xb8,0xf,0x94,0xb7,0xb2,0xf2,0x67,0x92, + 0x41,0x8a,0x8c,0xa6,0x54,0xae,0x11,0x8e,0xb6,0x1e,0xfc,0x79,0xb4,0xf5,0xa0,0x3e, + 0x75,0x66,0x9c,0x95,0x1c,0xad,0x2c,0x23,0xd9,0x29,0x52,0x12,0xaa,0x58,0x77,0xfa, + 0xd7,0x88,0x60,0xe9,0xbc,0xc0,0x7c,0x59,0xc5,0xb2,0x95,0xad,0x44,0x56,0xb2,0xbb, + 0x9b,0xe5,0xa2,0x8f,0x3f,0xdf,0x75,0xcf,0x1d,0x41,0x60,0x2c,0x73,0xa3,0x56,0xc6, + 0x8a,0x46,0xde,0x7c,0xe5,0xca,0x96,0x5,0x8b,0xee,0xce,0x97,0x8,0x44,0xc0,0x8a, + 0x7b,0x69,0x60,0xde,0xc2,0x6f,0x45,0x5b,0xf,0x3e,0x68,0x94,0x13,0x65,0x94,0xce, + 0x8e,0x1c,0x3a,0xf0,0xc7,0x78,0x6f,0xd7,0x7d,0x4a,0x49,0xc9,0x7b,0xbe,0xaa,0xda, + 0xc3,0x54,0x4d,0x16,0xa9,0x91,0xc8,0x2c,0x2d,0x1a,0x5d,0xad,0xc7,0x62,0x37,0x70, + 0x43,0x4e,0x42,0x46,0xeb,0xce,0xdd,0xf8,0x6f,0xc7,0xe7,0x7d,0x3f,0xca,0x30,0xaa, + 0x6a,0x3c,0x25,0x11,0xfb,0xf0,0x94,0x3a,0x63,0x65,0xf1,0xde,0xde,0x5f,0x75,0xde, + 0xf1,0xcb,0xc7,0xe5,0x40,0xd1,0xe,0x6f,0x75,0xf5,0x1,0x9a,0x48,0x54,0xa9,0xe1, + 0xf0,0x72,0x2d,0x91,0x38,0x93,0xa9,0xea,0x7a,0x3e,0x11,0xa4,0x91,0x86,0x4b,0x2e, + 0x79,0xd8,0x48,0x78,0x94,0xd2,0x72,0xd5,0x5b,0xd7,0xf0,0xc3,0xd4,0x60,0xff,0xcf, + 0xc,0x4,0xa4,0x38,0xde,0xdb,0xfb,0xcb,0xce,0xbb,0xee,0xf8,0xb5,0xbf,0xba,0xe6, + 0xd5,0x8a,0x95,0xab,0xf7,0xc5,0x47,0x46,0x4a,0xe3,0xdd,0x1d,0x2b,0xd2,0xa3,0xc3, + 0xb7,0x30,0x55,0x3d,0x9d,0xb7,0x28,0xea,0xce,0x3d,0xff,0xf7,0x86,0x42,0xcc,0xd9, + 0x40,0x96,0xfd,0xde,0xc3,0x66,0x16,0x41,0xa2,0xa3,0xad,0xc4,0xa8,0xba,0x6c,0x32, + 0xb5,0x57,0x73,0xd8,0xca,0x9c,0x88,0x24,0x77,0x7a,0x2a,0x2a,0x6d,0xb9,0x10,0x82, + 0xa7,0x8,0x88,0xa2,0xf0,0x95,0x0,0x77,0xbe,0x52,0x8f,0x6f,0x56,0x4b,0x2,0x66, + 0x8,0xc5,0x8d,0x8d,0x3f,0x8a,0xf5,0xf4,0xfc,0x6,0x78,0x87,0x7c,0x8f,0xb2,0x5c, + 0x4f,0xa5,0x36,0xeb,0xa9,0xd4,0x66,0x8,0x1,0xa4,0x86,0x6c,0xd0,0x9,0x92,0xdc, + 0x3e,0x6b,0xcb,0xf5,0xf7,0x59,0xe1,0xf9,0x51,0x9d,0xd1,0x3c,0x1d,0xf4,0x21,0x92, + 0x74,0xa4,0x6c,0xe5,0xca,0xbf,0xac,0x5e,0x7f,0xfa,0xa0,0xf0,0x8f,0xf8,0x3c,0xef, + 0xf7,0xb7,0xcc,0xcd,0xfa,0xd0,0xb4,0xa7,0xa2,0x32,0x2d,0xfb,0x8b,0x9f,0xd4,0x13, + 0xb1,0x1b,0x8d,0x9e,0x53,0xc3,0xe1,0x1b,0x0,0xc0,0x82,0x1,0x91,0x9c,0x35,0x20, + 0x22,0xca,0xa4,0x61,0xd3,0x65,0x7b,0x3a,0x7a,0xbb,0x1e,0xd0,0x13,0x89,0xeb,0x79, + 0x8e,0x89,0x1e,0x8b,0x7d,0x5a,0x8f,0xc5,0x20,0x35,0x64,0x52,0x52,0x9,0x89,0x96, + 0x2c,0x58,0xf0,0x57,0x81,0xa5,0xcb,0x27,0xb8,0x82,0xa7,0x1b,0x1b,0x10,0x6f,0x59, + 0xc5,0xed,0x47,0x73,0xa4,0xc7,0x7a,0x63,0x57,0xe8,0xa9,0xc4,0x15,0xe9,0xf1,0x71, + 0xd3,0x2c,0xf1,0xd5,0x37,0xfe,0xab,0xb7,0xaa,0x29,0xc5,0x7b,0x6e,0xf6,0x35,0x9f, + 0xda,0xda,0xfe,0x8b,0x9f,0xec,0x62,0x9a,0xba,0xc6,0x70,0x41,0x47,0xc3,0x5f,0x88, + 0x45,0xc3,0x5f,0x88,0x75,0x99,0x73,0x62,0x3d,0x65,0x65,0xbf,0x29,0x9a,0xb7,0x30, + 0x63,0x78,0x9b,0xec,0xee,0x2c,0xe6,0x2d,0x4a,0xa9,0xb8,0xd4,0x5c,0x5,0xd6,0xc1, + 0xbd,0xbc,0x2e,0xc3,0x5a,0xf5,0xe9,0x67,0x67,0xfc,0x90,0x74,0x7f,0xaf,0x5f,0xa4, + 0x1a,0xe7,0xb8,0xff,0x6d,0xa1,0xb5,0x5,0xbf,0x2,0x4b,0x69,0x35,0x1a,0x3f,0x39, + 0x2a,0x30,0x5f,0xd9,0xd3,0x2a,0x69,0xda,0x8c,0x9d,0x40,0x6f,0xbe,0xf4,0x13,0x2f, + 0x77,0xdc,0x73,0xc7,0x4f,0xd4,0x48,0xf8,0xab,0x8e,0xbf,0x9c,0x90,0x44,0x60,0xce, + 0xbc,0x7f,0x54,0x14,0xaf,0x96,0xa9,0x5,0xcb,0x51,0x1a,0x36,0xcf,0x4,0x6d,0x64, + 0x8f,0xef,0x85,0xc6,0xf3,0x2f,0xfe,0x6a,0xf1,0xbc,0x5,0x51,0xd1,0x16,0x31,0x42, + 0xf3,0x95,0x65,0xcb,0x3c,0x2f,0x6e,0x9e,0xf5,0x60,0xa4,0xed,0x90,0xa1,0x1,0x61, + 0x9a,0xb6,0x68,0xf0,0x89,0x7,0xd7,0x37,0x5d,0x72,0xd5,0xdb,0x59,0xae,0x0,0xd3, + 0x6,0x24,0xeb,0x4d,0x74,0x46,0x29,0x91,0x34,0x8d,0x89,0xfc,0xd5,0x9f,0x71,0xee, + 0x7f,0x1,0x21,0x13,0xd3,0x24,0x94,0xe1,0xd2,0xf9,0x8b,0x6e,0x6e,0xba,0xf0,0xb2, + 0x1d,0xbc,0x79,0x8c,0xef,0x78,0xad,0x8e,0xb3,0x87,0xc2,0x1a,0xce,0x3d,0xef,0xf7, + 0x44,0x92,0xba,0x6c,0x11,0x48,0x9f,0xef,0x4f,0x73,0xae,0xfa,0xe4,0x9f,0x45,0xe9, + 0x14,0x98,0x3d,0xe7,0xbb,0xd3,0xb4,0x30,0x9e,0x9f,0x7d,0xd5,0x75,0xbf,0x32,0x7a, + 0x77,0x68,0xdf,0x9e,0x85,0xbc,0x90,0xdf,0xdf,0xd0,0x78,0x48,0xf4,0x5b,0x24,0x4d, + 0x63,0xe9,0xb1,0x9,0x4e,0xf,0x2c,0xa9,0xd3,0xe3,0xf3,0xab,0x99,0x7e,0x3f,0xb1, + 0x67,0x17,0xb7,0x2a,0xc,0x3c,0x93,0xa,0xf9,0x83,0xbf,0x6c,0x69,0xa4,0x25,0xe2, + 0x32,0xaf,0xbc,0x5b,0xf6,0x15,0x19,0xee,0x7f,0x4c,0xec,0xda,0xbb,0x80,0x3b,0x5f, + 0x9f,0xe7,0x30,0xcc,0x30,0xe6,0x5c,0x7f,0xcb,0xed,0xb2,0xc7,0xf7,0xbc,0xc3,0xaf, + 0x4d,0x7,0x9a,0x66,0x7f,0xa1,0x69,0xd3,0x65,0x3b,0x2d,0xd3,0xd0,0x7e,0x30,0xb9, + 0xa4,0xe4,0xb6,0xe6,0xcf,0xfe,0xd5,0xe7,0xe5,0x85,0x8b,0x23,0x29,0x59,0x66,0xa2, + 0x7f,0xa3,0x2,0xf3,0x95,0x3c,0xbe,0x43,0x66,0xc6,0x9c,0xea,0xaf,0x6a,0xd3,0x65, + 0x7b,0x89,0xa4,0x70,0x3b,0x84,0xc7,0x6,0x6,0x6e,0xc8,0xf6,0x1d,0xd4,0xc9,0x2b, + 0x6d,0x8d,0x1e,0x4a,0x9d,0x90,0x3b,0xf4,0x2c,0x5b,0x39,0xe1,0xdb,0xbb,0xe7,0x9b, + 0xa9,0x91,0xc1,0x1f,0x3,0x80,0xc7,0x46,0xe3,0x31,0x51,0xbc,0x60,0xc9,0x2d,0x55, + 0x9b,0x2e,0xdd,0x97,0x12,0x78,0x3c,0xde,0xdd,0xcb,0xe9,0x81,0x45,0x46,0xc8,0x9c, + 0x79,0x71,0xb9,0xaa,0xea,0xe7,0xda,0xe8,0xe8,0xf,0x2c,0x4d,0x4d,0x51,0xf6,0x56, + 0x6f,0xbc,0xf8,0x5f,0x53,0x26,0x5a,0x90,0x54,0x6f,0xbe,0x72,0x47,0xe2,0xb7,0xbf, + 0xb8,0x43,0x8f,0xc7,0x6e,0xb5,0x8d,0x44,0x8a,0xb2,0xab,0xee,0xea,0x2b,0xbf,0xac, + 0x97,0x94,0x6a,0x46,0xbb,0xdf,0x89,0xd0,0x38,0x2f,0xb5,0x97,0x28,0x3b,0xfd,0xec, + 0x1e,0x33,0xdf,0xa3,0xa7,0x12,0x9c,0xd,0x74,0xcf,0x61,0xa3,0xf1,0xd2,0xc1,0x71, + 0x6e,0x2e,0x5c,0x29,0xa,0xb4,0xa6,0x6c,0x68,0xf3,0x32,0xba,0xf3,0xed,0x16,0x5e, + 0x9a,0x54,0xae,0x28,0xb3,0x63,0xbe,0x87,0x53,0x33,0xdd,0x3,0x4b,0x96,0x59,0xcd, + 0x85,0x9b,0xbe,0x3a,0xbc,0xf5,0x89,0xc7,0x18,0xa5,0xf3,0x1c,0x88,0x3c,0xc6,0xfd, + 0x4d,0xb3,0xfe,0xae,0xe6,0xaa,0x4f,0x6e,0xe7,0xad,0xd3,0x74,0x70,0x62,0xa1,0xa3, + 0xb4,0x20,0x24,0xe8,0x6b,0x68,0xf8,0xa7,0x86,0x2d,0x9f,0xfa,0x73,0x36,0x3f,0xd7, + 0x5,0xe6,0xab,0x14,0xfb,0x5b,0x6d,0x61,0x5b,0x69,0xe0,0x21,0x2d,0x14,0xfa,0x67, + 0x43,0xbd,0x9c,0x4a,0x6d,0x8a,0xed,0xdb,0x53,0x1d,0x58,0xb1,0x7a,0x2c,0xb,0x62, + 0x38,0x77,0xa5,0x2d,0x0,0x23,0x66,0x16,0x42,0xc3,0xb5,0x37,0x3e,0x35,0xfa,0xd2, + 0xd6,0xc3,0xf1,0x83,0x7,0x7f,0xc0,0x34,0x6d,0xb5,0x45,0x5a,0x32,0xe2,0x2b,0x7a, + 0xa4,0xfa,0xcc,0x73,0xbe,0x17,0x58,0xbe,0x4a,0x38,0xaf,0xa4,0x45,0xa3,0x8b,0x38, + 0x29,0xb9,0x4e,0x0,0x80,0xe6,0xeb,0x3e,0xfd,0x50,0xef,0x6f,0x7f,0xb9,0x48,0x8f, + 0x47,0x3f,0x97,0xa5,0xd2,0xde,0x59,0x77,0xd1,0xe6,0x4f,0xfb,0xe7,0x2f,0x32,0x5d, + 0x11,0x31,0xeb,0xff,0xfc,0xe5,0x7f,0xc,0x3e,0x7c,0xef,0xbb,0xa9,0xc1,0xc1,0xef, + 0x7e,0xd0,0x62,0x22,0xeb,0xb5,0x21,0x49,0xed,0xd5,0xe7,0x9e,0xff,0x59,0x6f,0xed, + 0x6c,0x6e,0x9b,0x3,0x16,0x4f,0x2e,0x36,0xa6,0x8d,0xdc,0x9e,0x69,0x53,0x91,0x68, + 0x4a,0x86,0xb,0x76,0x8c,0x37,0xd0,0x65,0x8f,0xef,0x70,0xa6,0xdf,0x2,0x0,0x68, + 0x71,0x7e,0xc1,0x83,0x52,0x5d,0x73,0xc8,0x68,0xc,0x61,0xd9,0x18,0x1c,0xe4,0xbe, + 0x2b,0x30,0x7b,0x89,0xe5,0xf9,0xca,0x95,0xd5,0x87,0xed,0x98,0xaf,0x55,0x14,0xb5, + 0x9c,0x14,0xa9,0x5c,0x3f,0x7a,0x43,0x68,0xcf,0xce,0xbf,0xd1,0x93,0x89,0x2d,0xb6, + 0x3a,0x76,0xc7,0xca,0x86,0xcf,0xf7,0x68,0xcd,0x69,0xe7,0xfd,0x7b,0x60,0xd9,0xea, + 0x9,0x91,0x53,0xd8,0x5a,0x3c,0xe6,0x88,0x1,0x21,0x92,0x72,0x50,0x2e,0x2f,0xbf, + 0xab,0xf6,0xcc,0xb,0xfe,0xe4,0x9b,0x3d,0x2f,0x91,0xed,0x89,0x76,0x91,0xf9,0xca, + 0xa5,0x35,0xb6,0xf0,0xbc,0x62,0xe5,0x69,0x8f,0x8e,0xbe,0xfa,0xec,0x3f,0x82,0xf1, + 0xc1,0x5c,0x4f,0x70,0xc7,0xdb,0x9f,0x2c,0x59,0xba,0xee,0x76,0xf3,0x44,0x1,0x7, + 0xab,0xb0,0x68,0x66,0xc5,0x91,0x9,0xb5,0x67,0x5f,0x7a,0x58,0x5f,0xb7,0x71,0xcb, + 0xc0,0x23,0x77,0x7d,0x56,0x8b,0x84,0xbe,0x2,0x0,0xbe,0x2c,0x18,0x7f,0xc0,0x3f, + 0x6b,0xf6,0xbf,0xd6,0x7f,0xfc,0xda,0x77,0x27,0x39,0x68,0xc2,0xea,0x24,0x13,0xc6, + 0x55,0x46,0x8a,0xd2,0xfe,0xc1,0x37,0xcd,0xba,0xe1,0xb,0xdf,0xeb,0xbd,0xe7,0xe7, + 0x1,0x3d,0x99,0xb8,0xc1,0xc4,0xf4,0x54,0xb9,0xb8,0xe4,0xb7,0x75,0x1b,0x37,0xff, + 0x8f,0x15,0xa1,0x6c,0xbc,0xe2,0x96,0xad,0x91,0xdd,0xaf,0xee,0x1a,0x7f,0xf7,0xad, + 0x1f,0x31,0x4d,0x3d,0x2b,0x8b,0xd5,0x31,0xa8,0x94,0x57,0xdc,0xde,0xf0,0xf1,0x6b, + 0xfe,0xa0,0x94,0x55,0xa,0xb5,0xf8,0xa0,0x6a,0x6a,0x11,0x27,0xf,0x66,0x5a,0x51, + 0x33,0x5d,0x33,0xbc,0xe6,0x54,0x2e,0x2e,0x3e,0x6c,0x3c,0x27,0x6e,0x75,0x8b,0x5e, + 0xb9,0xf6,0x6c,0x5b,0x2a,0x9a,0xf4,0x44,0x7c,0x11,0x2f,0xda,0x2d,0x59,0xbe,0x66, + 0xdc,0xf2,0x7c,0xd7,0x9c,0x35,0x6d,0xd7,0xcd,0x9a,0x45,0xd9,0x9a,0x73,0x6,0xcb, + 0xd6,0x9c,0xf3,0x4f,0xe1,0x9d,0xaf,0xfc,0x34,0xf4,0xde,0xee,0x2f,0xe8,0xc9,0xf8, + 0xb5,0xd9,0xac,0xc9,0x29,0x68,0x15,0x27,0x5e,0xff,0x33,0xfe,0x86,0x59,0xf7,0x35, + 0x5c,0xfa,0xc9,0x1d,0x66,0x7e,0x2a,0x40,0x43,0x4b,0x6c,0x26,0x5e,0xdf,0xb3,0xfe, + 0x86,0xa6,0xdf,0x35,0x5c,0x76,0xc3,0x5b,0x76,0xc,0x28,0x30,0x5f,0x56,0xb1,0x62, + 0x4d,0x2b,0xb1,0x21,0xea,0x2c,0x5d,0xbd,0x7e,0x74,0xec,0xad,0x97,0xb7,0x31,0x35, + 0x75,0xa1,0xe1,0x47,0xc6,0x22,0xd7,0x33,0x4d,0xfb,0x85,0xe4,0xf3,0x99,0xbd,0x2b, + 0xc6,0xc9,0x4d,0x74,0x46,0xb2,0x21,0x8a,0x52,0x52,0xa6,0xcd,0xbe,0xf9,0x8b,0xbf, + 0x1c,0x79,0x69,0xeb,0xb3,0x89,0x8e,0xf7,0x6f,0xa6,0x69,0xf5,0x24,0xa6,0x6b,0x8b, + 0x80,0xb1,0x2a,0x3,0x4f,0xba,0x43,0xf2,0x17,0x3f,0xed,0x9f,0x3d,0xe7,0xc9,0xba, + 0xb,0xae,0x7c,0x3f,0x6b,0x66,0xf3,0x6e,0xb5,0xf3,0xfa,0xda,0x3e,0xf8,0x26,0x22, + 0xcb,0xac,0xe5,0xd6,0xaf,0x7e,0x7d,0xe8,0xb9,0x47,0xee,0x4d,0x74,0x1c,0xf9,0x5b, + 0x43,0xa6,0x11,0x69,0x48,0xf6,0xf9,0x9e,0x2f,0x5a,0xb8,0xfc,0x37,0xb5,0x1b,0x2e, + 0xb6,0xa5,0x9b,0x69,0xd9,0xba,0xd,0x83,0xa5,0x27,0x9f,0x7d,0x63,0xef,0x3,0xbf, + 0xbe,0x5e,0x8f,0x84,0x2f,0x67,0x9a,0x7a,0x4a,0x6,0x7e,0x7d,0x30,0x89,0x24,0x91, + 0xe4,0x4e,0xb9,0xac,0xfc,0xde,0x86,0x4b,0xaf,0xfd,0x83,0xa7,0xbc,0xd2,0xd4,0x4d, + 0x6d,0x4c,0xd3,0x8d,0xa3,0x5,0xaf,0xf7,0xb0,0x19,0x7e,0x47,0xde,0x7b,0xb7,0xda, + 0x88,0xa7,0x0,0x0,0x4a,0x4d,0xa3,0xf1,0x98,0xfc,0xea,0x96,0x6e,0x4f,0x65,0x8d, + 0x2d,0x15,0x58,0x7a,0x8a,0x17,0x81,0x29,0x7c,0x25,0x20,0x30,0x5f,0x6f,0x4d,0x5d, + 0xa,0x72,0xc,0xe5,0xeb,0x37,0xf6,0x97,0xaf,0xdf,0xf8,0xcd,0xf0,0xae,0x37,0x7f, + 0x16,0xdc,0xfd,0xd6,0x67,0x69,0x3a,0xb9,0x96,0xe9,0xb4,0x19,0x18,0xad,0xe3,0x78, + 0xbb,0x1f,0x3a,0xe2,0x44,0x52,0xda,0xc0,0xe3,0xd9,0x2f,0x7,0x2,0x6f,0xd4,0x9c, + 0xb6,0xf1,0x99,0xa2,0xf9,0x8b,0x63,0xd9,0x31,0xc2,0x6,0x3,0x42,0x48,0x9c,0x10, + 0xb9,0x7,0x64,0xb9,0x47,0xf2,0x28,0xdd,0x44,0xf1,0xf4,0x2a,0x45,0xc5,0xdd,0x81, + 0xf9,0xb,0xf6,0x96,0xad,0x3d,0x77,0xc8,0x56,0xe2,0x71,0xe6,0x4b,0x24,0xa9,0xc7, + 0xd7,0x32,0xdf,0xb6,0xaa,0x3b,0x5f,0x55,0xd5,0x83,0xc9,0xa1,0x1,0x43,0x3,0xc2, + 0x28,0x9d,0x35,0xf4,0xe4,0x3,0x1f,0x6b,0xdc,0x72,0xf3,0xb6,0xe9,0x36,0x20,0x53, + 0x6d,0x9a,0xfe,0x10,0x0,0xbe,0xc8,0x35,0x4,0x81,0x92,0x5f,0xce,0xfe,0xf4,0xdf, + 0xfc,0xc4,0x2e,0xc2,0x84,0x77,0xbd,0x59,0x17,0xeb,0x68,0x5d,0xf2,0xc1,0xdd,0x11, + 0xb2,0xdf,0x3f,0x28,0x15,0x95,0xe,0x15,0x55,0xd5,0xe,0x94,0x9f,0xb9,0xb1,0xdf, + 0x8e,0x77,0x74,0xdc,0xfe,0xdd,0xdd,0x46,0xb5,0xd4,0xfe,0x86,0x96,0x5b,0x1a,0xb7, + 0xdc,0xf4,0x72,0x26,0x85,0x18,0xeb,0x3e,0x32,0x97,0x46,0xc2,0x2d,0xba,0x9a,0x6c, + 0x0,0x59,0x8e,0xc9,0x5e,0xdf,0x88,0x5c,0x51,0xd1,0x5d,0x77,0xde,0x15,0x7,0xc8, + 0x34,0xe7,0xb5,0x13,0x6d,0x7,0x4b,0x42,0x7,0x76,0xac,0xa2,0xf1,0x44,0xad,0xae, + 0xa6,0xaa,0x81,0x31,0xaf,0xec,0x2f,0xea,0x93,0x3,0xe5,0x3d,0xc5,0xb3,0xe6,0xf4, + 0x96,0xad,0x3b,0x73,0x4,0x10,0x8,0x3b,0x75,0x63,0x2c,0x2a,0x47,0x76,0xbe,0x51, + 0x9f,0x18,0x1b,0x68,0xa6,0xd1,0x58,0xb3,0x9e,0x4e,0x36,0x2,0x0,0x3,0x45,0x89, + 0xc8,0x92,0x12,0x25,0x1e,0x5f,0x58,0x2a,0xe,0x8c,0x56,0x9d,0x7e,0xee,0x61,0x6f, + 0x6d,0x63,0xa,0x29,0x96,0xdf,0xe8,0xbe,0xeb,0xb6,0xeb,0xb4,0x89,0xb1,0x7f,0x13, + 0x78,0xf4,0x31,0x0,0xb8,0xe,0x8c,0x3d,0x5a,0x1,0x3b,0xaf,0x78,0x6c,0x53,0x9a, + 0xe5,0xeb,0xcf,0x19,0x2a,0x5f,0x7f,0xce,0x10,0x0,0xbc,0x32,0x1d,0xc4,0x9,0xef, + 0x78,0xbd,0xd6,0xf0,0x20,0xe,0x0,0x14,0x37,0xce,0x6a,0xcd,0xf4,0x4d,0x65,0x6b, + 0xcf,0x18,0x2d,0x5b,0x7b,0xc6,0x28,0x0,0xbc,0x3b,0x13,0xcc,0x2d,0x5e,0xba,0x32, + 0x52,0xbc,0x74,0xe5,0x6b,0x28,0xe6,0x85,0xd,0xa2,0xaa,0x8e,0xed,0x9f,0x28,0x5e, + 0x9f,0x56,0x79,0xfa,0xc7,0xfa,0x2a,0x1,0xf8,0xf7,0xad,0xab,0x2a,0x32,0x27,0xdf, + 0x41,0xa9,0xc3,0xe7,0x40,0x1c,0x14,0x66,0xab,0x88,0x1d,0x79,0x9f,0xb3,0xd9,0x45, + 0x12,0x15,0xeb,0xcf,0xe9,0xcb,0xa7,0x6f,0x42,0x20,0x10,0x5,0xe0,0x34,0xc8,0x1e, + 0x67,0x74,0x12,0x71,0xb6,0x9d,0x3b,0xc9,0x27,0x26,0xa8,0xd1,0x88,0xe1,0x86,0x2e, + 0x91,0xe4,0x76,0xa2,0x28,0x2c,0xe7,0x98,0x8a,0x40,0x20,0x10,0x8e,0xc0,0xd1,0x93, + 0xe8,0x2c,0xaf,0x94,0x28,0xe3,0xdc,0xb4,0x7,0x8a,0x7c,0x18,0x8d,0x2,0x22,0xe3, + 0xd2,0xc2,0xc8,0x14,0xe1,0xf6,0x48,0x7,0xa8,0x73,0x65,0xbc,0x8c,0x32,0x92,0x4f, + 0x8b,0x8a,0x6a,0xbc,0x33,0x9,0xde,0x56,0x54,0x12,0x8,0x4,0x2,0x0,0x20,0xa1, + 0x14,0xa4,0x33,0xe9,0xe8,0x1e,0x88,0x94,0x4f,0x4c,0x65,0xba,0x6e,0x5c,0x6e,0x57, + 0x5c,0xdc,0x5a,0xa0,0x42,0x83,0x40,0x20,0x10,0x60,0xe2,0x24,0xba,0x3d,0xad,0x4c, + 0xf2,0x45,0xe1,0x46,0xdf,0xd9,0x5e,0xc3,0x3b,0x93,0xe0,0xab,0xa8,0x6b,0x45,0x1, + 0xca,0x4d,0x48,0x4a,0x1a,0xd,0x3b,0x2,0x31,0xed,0xf6,0x83,0x3a,0xb9,0x89,0xce, + 0x48,0xbe,0x2c,0xec,0x58,0xd7,0x41,0x5e,0x57,0x58,0xb5,0xec,0xec,0x73,0x3a,0x50, + 0x51,0x21,0x10,0x39,0xa0,0xc7,0xd2,0x5e,0x5c,0x87,0x33,0x1,0x5d,0x72,0xb0,0x17, + 0x16,0xcd,0x1f,0x46,0xd3,0x98,0x71,0xf,0x2c,0x90,0xa4,0x4e,0x6f,0x51,0x9d,0xa, + 0x69,0x94,0x21,0x4,0x2,0x51,0xb0,0x70,0xf8,0x4a,0xdb,0x3c,0x1,0x4d,0xa5,0x38, + 0x25,0xbc,0xca,0x61,0x94,0x9d,0x13,0x68,0xe2,0xc1,0x68,0xc,0x81,0x28,0xac,0x45, + 0x4f,0x1d,0xbd,0xd2,0x36,0x6f,0x94,0xc,0xd3,0x35,0xe3,0x3e,0x47,0x1e,0xf9,0x30, + 0x2a,0x4c,0x4,0x2,0x40,0x4a,0x61,0xfa,0x8,0x23,0x10,0x47,0x22,0x10,0x26,0xe5, + 0x8b,0xb0,0x31,0xca,0x6b,0x14,0xe8,0x3f,0x8c,0xb,0x7,0x81,0x40,0x14,0x5c,0xd0, + 0xe1,0x49,0x1d,0xa3,0xf7,0x28,0x9e,0x44,0x3f,0x11,0xc1,0xb7,0xb7,0x55,0x3,0x63, + 0xd5,0x86,0x6,0xa4,0xa4,0xb2,0x35,0x77,0x99,0x8a,0x40,0x20,0x10,0x4e,0x40,0x76, + 0xf8,0x24,0x7a,0x1e,0x28,0xba,0x48,0x5f,0x1b,0xaf,0x2,0x8b,0x55,0xad,0x5d,0xd7, + 0x8a,0x4a,0x1b,0x31,0x53,0x90,0x52,0x3e,0x94,0x3d,0xc4,0xcc,0x83,0x3a,0x99,0xc2, + 0xa2,0x40,0xf2,0x41,0xf0,0xe7,0x5e,0xf1,0xf9,0xd7,0x0,0xa0,0x96,0xfb,0x20,0x36, + 0xa3,0x46,0x20,0x10,0x4e,0x39,0xd,0x39,0xe9,0xb0,0x52,0x5d,0x74,0xfa,0x36,0x44, + 0x20,0xf9,0xd5,0x4c,0x31,0x7f,0x99,0x8a,0x40,0x20,0x10,0x8e,0xc0,0xd9,0x76,0xee, + 0xa8,0x70,0x11,0xf9,0x8c,0xa8,0x17,0x53,0x47,0x8,0xc4,0x87,0xf1,0x7,0xb1,0xc7, + 0x80,0x8,0xee,0xc4,0x33,0x9,0x17,0x20,0x2,0x81,0xc8,0x17,0x48,0xc9,0x24,0xea, + 0x2b,0x63,0x13,0xe2,0x68,0x15,0x16,0x32,0x17,0x81,0x40,0x20,0xdc,0x3,0x47,0xab, + 0xb0,0x8,0x2a,0x7d,0x44,0xd6,0xe,0x83,0xcf,0x8f,0xb2,0x83,0x40,0x14,0xae,0x1, + 0x1,0x82,0x4a,0x0,0x81,0x40,0x8,0x39,0xc,0x71,0xd4,0x15,0x39,0xf,0x9d,0x79, + 0x4,0x9f,0x54,0x8d,0xc,0x88,0x58,0x29,0x17,0x5,0x5,0x85,0x2,0x81,0x40,0x20, + 0x5c,0x12,0x7e,0x50,0x56,0x26,0xf8,0x68,0xd4,0xc8,0x80,0x44,0xc5,0x62,0x1d,0x16, + 0x40,0x92,0xe7,0x1b,0x26,0x90,0x4,0x8,0x4,0x62,0x6a,0x68,0xa9,0x39,0x82,0x4f, + 0x6,0x8d,0xc,0x48,0x58,0xcc,0x5a,0xe9,0xb3,0x50,0x21,0x21,0x10,0xb9,0xf,0xc9, + 0x57,0x84,0x99,0x2,0x84,0x80,0x4e,0xa7,0x6b,0x4,0x1f,0xed,0x30,0x32,0x20,0x3d, + 0x62,0x6f,0x63,0x8b,0x92,0x3,0xdd,0x9e,0xe2,0xb9,0x4b,0xf0,0x16,0xd,0x4,0x2, + 0x81,0xc8,0x11,0xc8,0xb1,0xb8,0x69,0x87,0x61,0x7c,0xef,0xdb,0x1,0xa6,0xeb,0x6b, + 0x5,0x1f,0x6f,0x35,0x32,0x20,0x87,0x4,0x7,0xf1,0xf,0xbd,0xbc,0xf5,0xd4,0x79, + 0x73,0x97,0xbc,0x8a,0x2c,0x9b,0x1e,0xa6,0x22,0x10,0x8,0x84,0x13,0x18,0xdf,0xfb, + 0xf6,0xe5,0x0,0xe0,0x17,0x7c,0x7c,0x97,0x91,0x1,0x19,0x3,0x80,0x7e,0x0,0x68, + 0xe2,0x6,0x21,0xb1,0xf0,0x95,0x72,0x2c,0xbe,0x1d,0xc9,0x8f,0x40,0x1c,0xf,0xc5, + 0x5f,0x8c,0xe,0x3,0x22,0x2f,0xa0,0x25,0xe3,0x44,0x4f,0x25,0xbe,0x20,0xf8,0x78, + 0x3f,0x0,0x1c,0x36,0x32,0x20,0x0,0x0,0xdb,0x1,0xe0,0x5a,0xde,0x48,0x54,0xd7, + 0xaf,0x1e,0x79,0xfb,0xc5,0x7f,0x6f,0x3c,0x77,0x33,0x6e,0x86,0x20,0x10,0x88,0x82, + 0xc6,0x68,0x24,0x9a,0x97,0x4e,0xc3,0xe8,0x83,0x3f,0xdb,0x2,0x8c,0x9d,0x24,0xf8, + 0xf8,0xb3,0xc7,0x39,0x4a,0x19,0x1e,0xda,0x26,0x62,0x40,0x0,0x20,0x10,0x3c,0xb8, + 0xe7,0x4b,0x8d,0xe7,0x6e,0xfe,0x36,0x32,0x15,0x81,0x40,0x20,0xf2,0xb,0xe1,0xd7, + 0x9e,0xa9,0xd6,0x93,0xc9,0x7f,0x33,0xf1,0x93,0x7,0x8f,0xfd,0x1f,0x99,0x3a,0xea, + 0x56,0xc2,0xe4,0x4e,0xbb,0x4f,0x60,0xc0,0xb4,0xa7,0xac,0xfa,0x82,0xaa,0x2b,0x3e, + 0x73,0x0,0xd9,0x81,0x98,0x69,0xc8,0x45,0x25,0xe8,0x30,0x20,0x10,0x2,0x48,0x1c, + 0xd9,0xef,0x99,0x78,0xe1,0xa1,0x7,0x81,0xb1,0x73,0x4,0x7f,0xd2,0x7,0x0,0x4b, + 0xe0,0x98,0xb3,0x82,0x99,0x22,0x90,0x9,0x0,0x78,0x6,0x0,0xae,0x14,0x18,0xd4, + 0xab,0x46,0xc6,0xef,0x88,0xee,0xda,0x7e,0x61,0xf9,0x99,0x97,0x44,0x90,0x2d,0x8, + 0x4,0xc2,0x29,0x48,0x81,0x10,0x3a,0xc,0x59,0x20,0x7e,0xf0,0xa0,0x67,0x62,0xdb, + 0x9f,0x7f,0x65,0xc2,0x78,0x0,0x0,0xdc,0x6,0x27,0x1c,0x34,0x37,0xba,0xd3,0xe3, + 0xc,0x98,0x4c,0x65,0x89,0x81,0x90,0xed,0x15,0x1b,0xae,0xf8,0x64,0xf1,0xe2,0x93, + 0xd3,0xc8,0x5c,0x4,0x2,0x81,0xc8,0x4d,0x8c,0x6f,0xdd,0x5a,0x11,0x3f,0x78,0xf0, + 0x37,0xc0,0xd8,0x79,0x26,0x7e,0x36,0x6,0x0,0x4b,0xe1,0x84,0x83,0xe6,0xbc,0x4b, + 0xa1,0xb6,0x2,0xc0,0x6,0x33,0x46,0xa4,0x68,0xd1,0xa2,0xcf,0x54,0x6f,0xde,0x3c, + 0x8e,0x6c,0x2a,0x3c,0x28,0x13,0xe5,0xe8,0x30,0x20,0x10,0x39,0x8c,0x9e,0xfb,0x7f, + 0x70,0xa1,0x9e,0x8a,0xff,0x18,0x0,0x66,0x99,0xfc,0xe9,0x97,0x1,0xe0,0xd7,0x1f, + 0x51,0xf9,0x9c,0x1f,0x9d,0x9,0x0,0xcf,0x83,0xb9,0xdb,0x7,0x7,0x64,0x5f,0xf1, + 0x17,0x67,0x5f,0xff,0xb5,0x6d,0xc8,0x2e,0x4,0xc2,0xc5,0xe,0x43,0xe9,0x18,0x3a, + 0xc,0x79,0x80,0x78,0x67,0xa7,0x3c,0xf4,0xec,0xb3,0xe7,0xe9,0xe9,0xf4,0x5f,0x1, + 0x63,0x1b,0xb3,0x18,0x62,0x37,0x0,0x9c,0xd,0x53,0xf4,0x49,0x14,0x31,0xc,0xbf, + 0x4,0x80,0x5b,0x4c,0xbf,0x52,0x92,0x1e,0xf3,0xf8,0xfd,0xff,0x35,0xe7,0xd6,0x5b, + 0xf7,0x22,0xb,0x11,0x8,0x4,0x22,0xb3,0x82,0xf,0xed,0xdb,0x57,0x6a,0xc7,0x58, + 0x34,0x9d,0xf6,0xe8,0xf1,0x78,0x25,0x4d,0x24,0x2a,0x99,0xae,0x2f,0xd1,0x75,0xfd, + 0x14,0xa0,0x74,0x13,0x0,0xd4,0x65,0x3b,0x3d,0x0,0x38,0x7,0x0,0xa6,0x2c,0x92, + 0x12,0x31,0x20,0x15,0x0,0xf0,0x36,0x0,0xcc,0xce,0xea,0xf5,0x84,0xbc,0x27,0xc9, + 0xf2,0xe3,0x92,0xa2,0xbc,0xea,0x6b,0x6c,0x3c,0xd8,0x78,0xe9,0xa5,0xc1,0x5c,0x65, + 0x64,0x68,0xef,0x5e,0x4f,0xbc,0xab,0xcb,0x96,0x26,0x91,0x4c,0xd3,0x64,0x3d,0x91, + 0xb0,0x45,0x28,0x18,0xa5,0x32,0x33,0x1e,0xcb,0x8c,0x27,0x48,0x98,0x4a,0xcb,0xed, + 0xa2,0x19,0x63,0xac,0xc2,0x3e,0xe,0xb0,0xa,0xc6,0x4c,0x45,0xbb,0x46,0x63,0x95, + 0x2,0x80,0x64,0xcb,0xa2,0x4,0x5a,0xa,0x99,0xb,0x4e,0xcc,0x22,0x60,0xf3,0x58, + 0x5e,0x9b,0x18,0xe9,0x7,0xf1,0x93,0xc8,0x9c,0xb1,0xc0,0x7,0x0,0x45,0x36,0x7d, + 0xa3,0x17,0x80,0x15,0xdb,0x37,0x16,0xd8,0x35,0x96,0xc,0x0,0xa5,0xe0,0x7e,0xfc, + 0x5,0x0,0xdc,0x95,0x51,0x99,0xfc,0xff,0xf6,0xce,0x3c,0x46,0x8a,0x2a,0x88,0xc3, + 0x1f,0xae,0x80,0xe0,0x1a,0x11,0x2f,0x8c,0x1a,0x45,0xd,0x6,0x45,0x5,0x3c,0x23, + 0x41,0x89,0x27,0x1e,0x88,0x82,0x17,0xae,0xac,0x92,0xac,0xa,0xd1,0x78,0x4,0x3c, + 0x50,0xd0,0xa0,0x89,0x26,0x5e,0x91,0x98,0x60,0x34,0x10,0xf,0x30,0xa8,0xa8,0x78, + 0x13,0x45,0x45,0x51,0xe2,0x85,0x17,0xca,0x11,0x51,0xe2,0x11,0x9,0xa2,0x20,0x88, + 0x2b,0x82,0xec,0xae,0x7f,0x54,0x75,0x6c,0x9b,0x9e,0xe9,0x9e,0x99,0xde,0xd9,0x9d, + 0xdd,0xdf,0x97,0x74,0x76,0xbb,0xdf,0xf4,0xeb,0xd7,0x35,0x3d,0x55,0xef,0x55,0xd5, + 0x7b,0x9d,0xb2,0x92,0x63,0xb0,0x9,0x24,0x1d,0x33,0x68,0xd0,0x16,0x52,0xae,0xf8, + 0xdb,0x2,0xf,0x85,0x10,0x42,0x8,0xe3,0x1e,0xe0,0xd6,0xbc,0xbd,0xd1,0x2,0x2d, + 0xd1,0x3,0x92,0xa9,0x10,0x42,0xb4,0x79,0x9e,0x0,0x46,0x93,0xe0,0xdd,0xa8,0x2a, + 0xa0,0xc2,0x4f,0xfd,0xef,0x71,0x92,0xad,0x10,0x42,0xb4,0x59,0xee,0x3,0xc6,0x92, + 0xc2,0x35,0x5e,0x55,0x60,0xc5,0xef,0x1,0x1b,0x81,0x13,0xa,0x1c,0xbd,0x8,0x21, + 0x84,0x68,0xdd,0x6c,0x6,0xc6,0x1,0x77,0xa7,0x3d,0xa1,0xaa,0x88,0x8b,0x7c,0x80, + 0x2d,0x73,0x72,0x2a,0xd9,0x5,0x3,0x85,0x10,0x42,0xb4,0x1c,0xcb,0x80,0x61,0xc0, + 0xcb,0x85,0x9c,0x54,0xca,0x28,0xe2,0x50,0x60,0x3a,0xd0,0x4b,0xb2,0x17,0x42,0x88, + 0x8a,0x64,0x23,0x70,0x17,0x30,0xd9,0x47,0x20,0x5,0x51,0x55,0xc2,0x85,0x7f,0x1, + 0x1e,0xc7,0xfc,0x64,0x47,0x6a,0x34,0x22,0x84,0x10,0x15,0xc3,0x1f,0xc0,0x43,0xc0, + 0x28,0x6c,0xc5,0x91,0x86,0x62,0x2a,0xc9,0x2a,0x8e,0xb1,0x2f,0x70,0x3d,0x30,0x92, + 0x6c,0x52,0x7d,0x85,0x10,0x42,0x64,0x4b,0x3,0x30,0x1f,0xf3,0x1c,0xbd,0x4,0xd4, + 0x97,0x5a,0x61,0xd6,0x81,0xf0,0x3d,0x81,0xe1,0x40,0xd,0xe6,0xe2,0x12,0x42,0x8, + 0x51,0x3e,0x9a,0x80,0xf5,0xc0,0x6,0xe0,0x37,0x60,0x85,0x6f,0x1f,0x2,0xb,0xbc, + 0x2c,0x33,0x9a,0x33,0x93,0xaa,0xf,0x30,0x8,0x38,0xa,0x5b,0x43,0xfe,0x40,0xd2, + 0xbd,0x5f,0xa4,0x2d,0x59,0xfb,0xac,0x96,0xb7,0x6f,0xcc,0xf0,0x8b,0x6f,0xca,0xf8, + 0x21,0x5a,0x47,0x61,0x33,0xe1,0x93,0x86,0xd5,0x8d,0x19,0xd6,0xd5,0x90,0x51,0x5d, + 0xf5,0xc0,0x3f,0x19,0xd6,0xb5,0x39,0xa3,0xba,0x36,0x2,0x9b,0x32,0xac,0xeb,0xef, + 0x8c,0xea,0xda,0x8c,0x2d,0x81,0x91,0x55,0x5d,0xf5,0x19,0xd5,0x95,0xe5,0x24,0xe6, + 0x6,0x7f,0xc6,0x5a,0xe3,0x6f,0xb2,0x6c,0x94,0x3b,0x15,0xb7,0x1a,0x5b,0x1a,0x25, + 0x4b,0x37,0x57,0x6b,0x7d,0xc0,0x84,0x10,0x42,0x8,0x21,0x84,0x10,0x42,0x8,0x21, + 0x9a,0x87,0x6e,0x98,0x3b,0xaa,0xd0,0x2d,0xec,0xf5,0x78,0x3f,0x74,0x7c,0x41,0xc2, + 0xf5,0x7a,0x45,0xea,0xa9,0x2b,0xf7,0xd,0x2b,0xf5,0x56,0x8,0x21,0xb2,0x61,0xb, + 0xf0,0x51,0xcc,0xf1,0xae,0xc0,0x21,0xfe,0xff,0x42,0xb6,0x8e,0xcd,0xe5,0x8a,0x17, + 0x1d,0x8b,0xbd,0x5,0x70,0x59,0x8e,0xf2,0x3a,0x89,0x5c,0x8,0x21,0xda,0x36,0x7d, + 0x43,0xa3,0x84,0xa4,0xd7,0x1f,0x4,0x23,0x90,0x8f,0xfd,0xef,0x3d,0x39,0x3e,0xd7, + 0x11,0x58,0x85,0x5,0xf2,0x97,0xb6,0xd4,0x8,0x64,0x1b,0x7d,0xb7,0x42,0x8,0xd1, + 0xea,0x78,0x1a,0xcb,0xe2,0xac,0x25,0x3e,0xe9,0x68,0x8,0xb0,0x3b,0x30,0x93,0xec, + 0x92,0x88,0x2a,0xc2,0x80,0x54,0x1,0x37,0x1,0xaf,0x2,0x73,0xfc,0xef,0x55,0x29, + 0xcf,0xbd,0x5,0x7b,0xbd,0xe2,0x6,0x60,0x2e,0x30,0x86,0xad,0x67,0xd3,0x8f,0x5, + 0x96,0xbb,0x75,0x9e,0x12,0x11,0x7e,0xbe,0x32,0x30,0x9f,0xe2,0x6b,0xd8,0xb,0xe4, + 0x57,0x3,0xf7,0xa7,0x68,0xd3,0xcd,0x6e,0xfd,0x87,0xc5,0x94,0xbd,0x49,0xbc,0xcf, + 0xf3,0x18,0x2f,0x9f,0x1a,0x53,0x56,0x17,0x39,0xff,0xde,0xd0,0x7e,0x67,0xe0,0x15, + 0x60,0x11,0xb0,0x6b,0x19,0xe4,0x75,0x1e,0xf0,0xb6,0x9f,0x1f,0x97,0x9d,0x96,0x54, + 0x1e,0x27,0x8f,0x7c,0xf7,0xf3,0x6,0x30,0x2d,0xc7,0xb9,0xb,0x22,0xdf,0x47,0xae, + 0x76,0xf7,0x0,0x6e,0x73,0x57,0x41,0x3d,0xf6,0x26,0xb5,0x7b,0xa5,0x8f,0x44,0x85, + 0x51,0xf,0x3c,0x85,0xbd,0x49,0xf0,0xcc,0x98,0xf2,0x40,0x4f,0x4c,0x6b,0x4f,0x42, + 0xe9,0x8,0xcc,0x6,0x2e,0x88,0x1c,0xbf,0xc,0x98,0x41,0x72,0x5a,0xf1,0x67,0xc0, + 0x95,0xc0,0xf1,0xc0,0x78,0x57,0x5a,0x61,0xc5,0x7d,0x9,0x96,0xd6,0x7b,0xbb,0xff, + 0xbf,0x6,0x78,0x30,0x45,0x19,0x40,0x4f,0x60,0xad,0x2b,0xb1,0xf3,0xb0,0x39,0x2c, + 0x35,0x29,0xee,0x69,0x9,0xb6,0xd4,0xfd,0xf3,0x39,0x14,0xe6,0xe3,0x3e,0x84,0xd, + 0x6f,0x5d,0x43,0x6,0xe4,0xc9,0x48,0x59,0xf7,0x1c,0xa,0x37,0x50,0xb6,0x5f,0x2, + 0xbb,0xa4,0x94,0x77,0x29,0xf2,0xa,0xca,0xc7,0x3,0x77,0xe4,0x30,0x10,0x49,0xe5, + 0xf9,0xc,0x48,0xdc,0xfd,0xd4,0x2,0xbf,0xb3,0xf5,0x7c,0xa1,0x9e,0x6e,0x5c,0xfb, + 0xa7,0x68,0xf7,0x23,0xc0,0x27,0xc0,0x85,0xc0,0x61,0xc0,0xb9,0x7e,0x4c,0x88,0x96, + 0xa2,0x18,0x17,0xd6,0x68,0x6c,0xe,0x5d,0x93,0x77,0xb2,0xc3,0xec,0x85,0xc5,0x51, + 0x16,0xf9,0xfe,0x42,0x5a,0xc8,0x85,0x55,0x6e,0x26,0x62,0xab,0xf8,0xf6,0xf1,0x5e, + 0xe3,0x62,0x17,0xc2,0x0,0xe0,0x62,0x17,0x5a,0x21,0x4c,0x71,0xa5,0x14,0xf0,0x71, + 0xa4,0x97,0x7a,0xbe,0xf7,0x8e,0xab,0x13,0xca,0x2,0x65,0xfe,0x76,0x81,0xd7,0x3f, + 0xdc,0x15,0xde,0x41,0xd8,0x44,0xac,0x6e,0x9,0x3d,0xee,0x28,0x53,0xc9,0xff,0x92, + 0xae,0xe0,0xfc,0x62,0x8c,0x47,0xa9,0xf2,0xa,0x73,0x76,0x82,0x81,0x48,0x2a,0x4f, + 0x7b,0x3f,0xd5,0xde,0xf3,0x1a,0x16,0x33,0x92,0x5a,0x92,0xa2,0xdd,0x3d,0xb0,0x80, + 0xe4,0x89,0xd2,0x59,0xa2,0xd,0x18,0x10,0x5c,0x3f,0x6e,0xc1,0x56,0xf9,0x8,0xb8, + 0xd5,0x3f,0x73,0x4d,0x4b,0x1b,0x90,0x72,0xba,0xb0,0x3a,0x60,0x99,0x8,0xaf,0x7b, + 0xaf,0x7c,0xbe,0xef,0xf7,0x77,0x43,0x32,0xa3,0x88,0x1f,0xfe,0xa6,0xc8,0xbd,0xf4, + 0x7,0xbe,0xa,0x1d,0xfb,0xda,0x95,0xd2,0xc1,0x79,0xca,0x7a,0xfb,0xfe,0x19,0xfe, + 0x65,0xcd,0xc5,0xb2,0x1e,0x6e,0x4c,0xa1,0xac,0x47,0x2,0xb3,0x5c,0xb9,0x2d,0x74, + 0x45,0x56,0x28,0xb5,0xd8,0x2c,0xd4,0x67,0x7d,0xa8,0x1a,0x75,0x31,0x75,0x6,0x9e, + 0xf3,0x5e,0xc7,0x9,0xd8,0xf2,0x4,0xc5,0x92,0x56,0x5e,0xbd,0x9b,0xf1,0x39,0xc8, + 0x77,0x3f,0x7f,0x2,0x2f,0xc4,0x8c,0xfc,0x2e,0xf2,0xe7,0x23,0xa9,0xdd,0x7b,0x3, + 0x3f,0x3,0x27,0xd1,0xbe,0x56,0x3d,0x10,0x6d,0x97,0xa9,0xae,0x13,0x2e,0xd,0xe9, + 0xd1,0x51,0xfe,0x5b,0x9e,0xde,0x9e,0x4,0xd1,0xd3,0x5d,0x1d,0xbd,0x81,0x6f,0xf2, + 0xf4,0x90,0xd3,0xbe,0xa8,0x7e,0x7f,0xef,0x75,0x6,0xfe,0xc1,0x1e,0xfc,0xb7,0x32, + 0x70,0xc0,0xb6,0x2e,0xe8,0x2b,0xf2,0x94,0xd,0x5,0xba,0xf0,0xdf,0x72,0x2,0x93, + 0x80,0xd3,0xb0,0x97,0x67,0xcd,0xcb,0x73,0xfd,0x2a,0xcc,0xff,0x3e,0xd0,0xf7,0x2f, + 0x77,0xa3,0x18,0xed,0x71,0xc7,0xc5,0x40,0xb6,0xf3,0xf2,0x11,0x7e,0xfd,0x81,0x3e, + 0x12,0xf9,0xd3,0xd,0x4a,0xf8,0xfc,0x4d,0xee,0xa2,0xd9,0xb9,0x44,0xf9,0x17,0x22, + 0xaf,0xa1,0xcd,0x38,0x2,0x49,0xba,0x9f,0xc1,0xd8,0x92,0x1a,0x3b,0x86,0x7a,0x6f, + 0x8d,0xc0,0x3e,0x29,0xdb,0x7d,0xe,0xb6,0xf6,0xcf,0x3a,0x37,0xca,0x27,0x4b,0x7, + 0x89,0xa,0x1e,0x81,0x74,0xf7,0xdf,0xc3,0x77,0x6e,0x3c,0x4e,0xf1,0xf2,0xa7,0x42, + 0xe7,0xb4,0x8b,0x11,0x48,0xb8,0x17,0xdc,0x89,0xf8,0x78,0x47,0x13,0xe9,0x96,0x57, + 0xe9,0xee,0x3d,0xd5,0xc7,0xdc,0x15,0x92,0x95,0x1c,0xde,0xc5,0x2,0xb0,0x73,0xfc, + 0xb,0x1c,0x48,0xee,0x60,0xf5,0xc9,0xee,0x2e,0x79,0xdf,0xf7,0x9f,0x1,0x8e,0x8, + 0x29,0xba,0x80,0x27,0x80,0x7e,0x91,0x2d,0x18,0x9,0xcc,0x4,0x5e,0x74,0x63,0x75, + 0x2d,0x16,0x10,0x1b,0x19,0xf3,0x40,0x75,0xc2,0x82,0xc6,0xc5,0x92,0xb5,0xbc,0x4a, + 0x21,0xe9,0x7e,0xe6,0xba,0xf2,0x1f,0xee,0xfb,0x35,0x7e,0xce,0xf,0x29,0xeb,0x9f, + 0xd,0x1c,0xe0,0xc6,0x79,0xa5,0x8f,0x10,0xe7,0x4b,0x87,0x89,0xa,0x65,0x2d,0x16, + 0x5f,0xdd,0xf,0x8b,0xcb,0xd6,0x85,0x46,0x26,0x2d,0x4e,0x39,0xd,0xc8,0xf7,0xd8, + 0xa4,0x98,0x15,0xee,0x66,0xb8,0x1a,0xd8,0x1e,0xb,0x28,0xef,0xe6,0x9f,0xd9,0x95, + 0xe4,0x5,0xca,0x76,0xc0,0xd6,0xaf,0x5f,0xe4,0x75,0x4,0xac,0xc6,0x2,0x4b,0x7d, + 0x42,0xc7,0x7a,0xb9,0xb2,0xfa,0x22,0x4f,0xd9,0x4a,0xcc,0xef,0xbe,0x1,0x5b,0xb1, + 0x32,0x60,0xb1,0x1b,0x88,0x81,0x79,0xdc,0x57,0xfb,0x62,0x8b,0xec,0x6d,0x71,0x57, + 0x4c,0x97,0x18,0xf7,0xcb,0xaf,0x7e,0xfd,0xf0,0x96,0x6b,0xf1,0xc1,0x39,0x58,0xc0, + 0xbb,0x53,0xe8,0xd8,0xe7,0xc0,0x59,0xc0,0x75,0xc0,0xd,0x45,0xc8,0xbd,0x18,0x79, + 0xad,0x6c,0xc6,0xe7,0x20,0xe9,0x7e,0x1a,0xbc,0x77,0x55,0xe3,0xcf,0xe7,0x88,0x90, + 0xfb,0x2a,0x6d,0xbb,0x1b,0x5d,0x96,0x57,0xbb,0xc1,0x1e,0xe0,0x9b,0x10,0x95,0xea, + 0xc6,0xc2,0x7f,0x2f,0x43,0xb1,0x37,0xc2,0xbe,0xd5,0x1a,0x1a,0x56,0xce,0x99,0xe8, + 0x4d,0xae,0x94,0x4f,0x71,0xa5,0x30,0xa,0x78,0xc7,0x87,0x67,0xd7,0x60,0x7e,0xeb, + 0xa4,0x9e,0x62,0x17,0xef,0x41,0xaf,0xc2,0xb2,0x6f,0xc2,0x8a,0xb8,0x11,0xcb,0x3a, + 0x3a,0x24,0x74,0xac,0x8f,0xbb,0x56,0x16,0xe7,0x29,0x5b,0xea,0xfb,0x1f,0x61,0x59, + 0xf,0x1,0xbd,0xdd,0xb8,0xbd,0x17,0xd3,0x8e,0x6a,0x77,0xdb,0xc,0x3,0xbe,0x8d, + 0x8c,0x4a,0xea,0x80,0x3b,0x8b,0x94,0xd1,0xe9,0x98,0xdb,0x2c,0xba,0x5a,0xeb,0x3c, + 0x2c,0xbe,0xf2,0x1c,0xe6,0x66,0x7b,0x38,0x65,0x7d,0xc5,0xca,0x6b,0x69,0x33,0x3f, + 0xb,0x49,0xf7,0x33,0x1d,0xb,0x94,0x8f,0xc0,0xe2,0x50,0xb3,0x4a,0x68,0xf7,0x1a, + 0xef,0x8,0xec,0x21,0x3d,0x24,0x2a,0x94,0x79,0xde,0xf1,0x1e,0xec,0xfb,0x8f,0x92, + 0xdd,0xa,0xd8,0x15,0x45,0x27,0x77,0x31,0x44,0x83,0xcd,0x75,0x24,0xa7,0xf1,0x6e, + 0xe3,0x3d,0xe9,0xe5,0xd8,0x3c,0x8a,0x20,0xed,0x35,0xdc,0x13,0xd,0xd2,0x3b,0x27, + 0x61,0xb1,0x84,0xb8,0x34,0xde,0xb8,0x32,0xb0,0xd8,0xc0,0x5f,0xd8,0x1c,0x95,0x41, + 0x58,0x46,0xd6,0xdc,0x1c,0x6d,0xa9,0x5,0x7e,0x8a,0x39,0xbe,0x93,0x8f,0x48,0x82, + 0x74,0xd3,0x5c,0x69,0xbc,0xdd,0x42,0x8a,0xf2,0x2c,0xbf,0xde,0x64,0x57,0x82,0xe1, + 0x11,0x4c,0x34,0x8b,0xab,0xc6,0xeb,0xbf,0x30,0x74,0xec,0x8,0xe2,0xd3,0x8d,0x4b, + 0x95,0x57,0xe0,0xfa,0xea,0xeb,0xa3,0x85,0xbf,0x42,0x75,0x74,0x48,0x59,0x1e,0x25, + 0xcd,0xfd,0x4,0x2c,0xc1,0x32,0xdc,0xe2,0xd2,0xa3,0x73,0xb5,0x7b,0x4f,0xef,0x94, + 0xd4,0xfa,0x77,0x30,0xc4,0x8d,0xd4,0x8f,0x68,0xd9,0x1e,0xd1,0x72,0x94,0x12,0x3, + 0x9,0x18,0xe7,0x5e,0x8e,0xd5,0x58,0x2,0x4a,0x98,0x76,0x93,0xc6,0xb,0x16,0x7c, + 0x9e,0xe0,0xca,0x2d,0xd8,0xae,0x25,0x39,0xf6,0x51,0x4d,0x7c,0x40,0x3a,0x9a,0x95, + 0x34,0xd6,0x47,0x5,0xab,0xb0,0x57,0x36,0x76,0x4c,0x59,0x86,0x8f,0x8a,0x16,0x63, + 0xfe,0xf6,0x9,0x21,0xd7,0x5a,0x94,0x1,0xb1,0x12,0x97,0x0,0x0,0x0,0x8a,0x49, + 0x44,0x41,0x54,0x37,0xb0,0x80,0x7f,0xae,0xde,0xc2,0xfd,0x21,0x85,0x19,0xd7,0xe6, + 0x40,0x61,0xce,0xf6,0xb6,0xac,0xc7,0xe2,0x21,0x67,0x47,0x14,0x5d,0x5c,0x1a,0xf0, + 0x18,0x57,0x9e,0x41,0x30,0x7c,0xa2,0xb7,0xb9,0x39,0xe4,0x55,0x47,0xfe,0x24,0x80, + 0xa4,0xf2,0x24,0x3,0x12,0x77,0x3f,0x1,0xf9,0x26,0x68,0xe6,0x6a,0x77,0x57,0xe0, + 0x6e,0x2c,0x43,0xab,0xde,0xe5,0x32,0x19,0x38,0x5a,0x3a,0x4c,0x54,0xb8,0x1,0xc9, + 0x47,0xbb,0x32,0x20,0x22,0x5b,0x66,0x7a,0x4f,0x5c,0x8,0x21,0x3,0x52,0x56,0xb4, + 0x16,0x56,0xe5,0xd3,0x8f,0xff,0xbb,0x9d,0x84,0x10,0x42,0x8,0x21,0x84,0x10,0x42, + 0x8,0x21,0x84,0x10,0x42,0x8,0x21,0x84,0x10,0x42,0x8,0x21,0x84,0x10,0x42,0x8, + 0x21,0x84,0x10,0x42,0x8,0xd1,0x36,0xf9,0x17,0x6,0xc,0xad,0x73,0x6f,0xe3,0xc1, + 0x6c,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/rightBottom.png + 0x0,0x0,0x0,0xc8, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x18,0x8,0x6,0x0,0x0,0x0,0xc7,0xd9,0xbc,0x10, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x5d,0x49,0x44,0x41,0x54,0x38,0x4f,0x63,0x8c,0x8c,0x4f, + 0xf9,0xcf,0x0,0x4,0x8f,0xef,0xde,0x0,0x51,0x70,0x20,0xab,0xac,0xc1,0xb0,0x7c, + 0xe1,0x1c,0x6,0xa6,0x47,0x8f,0x1e,0x62,0x48,0x22,0x2b,0x64,0x42,0xd1,0x6,0xe5, + 0xfc,0x67,0xe5,0x86,0xb,0x33,0x31,0xfe,0xfe,0x8e,0xa1,0x86,0xf1,0xf7,0x57,0x84, + 0x2,0x6c,0x26,0x10,0xb4,0x62,0x54,0x1,0x66,0xb0,0x61,0x8d,0x8b,0x41,0x17,0x50, + 0xff,0x59,0x39,0x31,0x9c,0x8e,0x92,0x60,0x68,0x9f,0x1e,0x58,0xe4,0xe4,0xe4,0xf1, + 0xda,0x2,0x0,0x96,0x98,0x13,0xd8,0xa8,0x8c,0x27,0xa5,0x0,0x0,0x0,0x0,0x49, + 0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/leftTop.png + 0x0,0x0,0x0,0xa2, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x8,0x0,0x0,0x0,0x8,0x8,0x6,0x0,0x0,0x0,0xc4,0xf,0xbe,0x8b, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x37,0x49,0x44,0x41,0x54,0x28,0x53,0x63,0x64,0x60,0x60, + 0xf8,0x1f,0x19,0x9f,0x2,0xa4,0xb0,0x3,0x46,0x98,0x82,0xc7,0x77,0x6f,0x60,0xa8, + 0xf8,0xcf,0xca,0xc9,0xc0,0x4,0x13,0xfd,0xcf,0xca,0x8d,0xd5,0x8,0xb8,0x2,0x5c, + 0x56,0xc,0xa4,0x2,0x59,0x65,0xd,0x6,0x39,0x39,0x79,0x6,0x0,0xe2,0xe4,0x9, + 0xbc,0x34,0xec,0xd6,0x3d,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60, + 0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/hide_high.png + 0x0,0x0,0x1,0x8a, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x1f,0x49,0x44,0x41,0x54,0x38,0x4f,0x63,0xac,0xaf,0xaf, + 0xff,0xaf,0xa9,0xa9,0xc9,0xf0,0xf2,0xe5,0x4b,0x6,0x62,0x81,0xb8,0xb8,0x38,0xc3, + 0xf5,0xeb,0xd7,0x19,0x18,0x77,0xef,0xde,0xfd,0x5f,0x4a,0x4a,0x8a,0xe1,0xd3,0xa7, + 0x4f,0xc,0xff,0xfe,0xfd,0x63,0xf8,0xf5,0xeb,0x17,0xd8,0x8c,0x9f,0x3f,0x7f,0x32, + 0xfc,0xf9,0xf3,0x7,0xce,0x6,0x31,0xfe,0xfe,0xfd,0xb,0x56,0xc3,0xc4,0xc4,0x4, + 0x66,0x33,0x2e,0x5b,0xbe,0xfc,0xff,0xdd,0xbb,0x77,0x89,0xb5,0x14,0xac,0x8e,0x83, + 0x83,0x83,0x81,0x99,0x85,0x85,0x81,0xb1,0xb8,0xb8,0xe4,0x3f,0x4c,0x67,0x48,0x48, + 0x30,0x83,0x85,0x85,0x5,0x4e,0x83,0x4e,0x9c,0x38,0xc1,0xb0,0x66,0xcd,0x5a,0xb8, + 0x3c,0xd3,0xbb,0xf7,0x1f,0x19,0x60,0x98,0x18,0xeb,0x91,0xd5,0x33,0x6,0x6,0x5, + 0xc3,0x6d,0xfe,0xfe,0xe3,0x7,0xc3,0x4f,0x20,0x86,0x81,0xb6,0xd6,0x16,0x86,0xaa, + 0xea,0x1a,0x38,0x9f,0x1d,0xe8,0x5c,0x4e,0x20,0x86,0x1,0x46,0x55,0x75,0xed,0xff, + 0x32,0x32,0x32,0x18,0x96,0x4e,0x99,0xd4,0x7,0x17,0xcb,0xc9,0x2b,0xc2,0x90,0x7f, + 0xf2,0xe4,0x9,0x3,0xa3,0x8c,0x82,0x12,0xdc,0x66,0x98,0x8a,0x9d,0x5b,0x37,0x63, + 0x28,0x76,0xf7,0xf6,0xc5,0x10,0x63,0x54,0x54,0xd3,0xc2,0xd0,0xc,0x53,0xb5,0x65, + 0xfd,0x6a,0x6,0x9f,0xc0,0x50,0x9c,0x41,0xc1,0xc4,0xc6,0xc6,0xc6,0x80,0xb,0x83, + 0x74,0xe1,0x93,0x67,0xc2,0x17,0xc2,0xa0,0x84,0x83,0xf,0xe0,0xd5,0x4c,0x28,0xea, + 0x18,0xd5,0x75,0xc,0x70,0xfa,0x99,0x90,0x66,0x26,0x2d,0x35,0x65,0x6,0x16,0x56, + 0x36,0xac,0xf8,0x3f,0x3,0x23,0x4e,0x39,0x90,0x3e,0xb0,0xcd,0x20,0x6,0xa9,0xe0, + 0xda,0xad,0xbb,0xc,0x0,0xee,0x6e,0x6d,0x7,0xc1,0xe6,0x35,0xf8,0x0,0x0,0x0, + 0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/left_arrow.png + 0x0,0x0,0x0,0xc5, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x2,0x0,0x0,0x0,0xb4,0xb4,0x2,0x1d, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x20,0x63,0x48,0x52,0x4d,0x0,0x0,0x7a,0x26,0x0,0x0,0x80,0x84,0x0,0x0,0xfa, + 0x0,0x0,0x0,0x80,0xe8,0x0,0x0,0x75,0x30,0x0,0x0,0xea,0x60,0x0,0x0,0x3a, + 0x98,0x0,0x0,0x17,0x70,0x9c,0xba,0x51,0x3c,0x0,0x0,0x0,0x43,0x49,0x44,0x41, + 0x54,0x28,0x53,0x63,0x60,0x18,0xdc,0xe0,0xff,0xff,0xff,0xc4,0x3a,0x10,0xa8,0x94, + 0x58,0xd5,0x10,0xa5,0x44,0xa9,0x86,0x2b,0x25,0xac,0x1a,0x59,0x29,0x26,0x1b,0xdd, + 0x1b,0xd,0xd,0xd,0xc8,0x8a,0x80,0x5c,0x64,0x80,0xc5,0xd3,0xc8,0x1a,0x88,0xa, + 0x13,0xb8,0x6,0xa2,0x54,0x3,0x15,0x41,0x34,0x10,0xab,0x7a,0x80,0xd4,0x1,0x0, + 0x71,0xca,0x67,0x27,0xc6,0xe,0xff,0xdd,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44, + 0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/maximize_high.png + 0x0,0x0,0x1,0x8e, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0xf,0x0,0x0,0x0,0xf,0x8,0x6,0x0,0x0,0x0,0x3b,0xd6,0x95,0x4a, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x1,0x23,0x49,0x44,0x41,0x54,0x38,0x4f,0x63,0x2c,0x2e,0x2e, + 0xf9,0x6f,0x6a,0x6a,0xc2,0xf0,0xf2,0xe5,0x4b,0x6,0x62,0x81,0xb8,0xb8,0x38,0xc3, + 0xe9,0xd3,0x67,0x18,0x18,0x77,0xef,0xde,0xfd,0x5f,0x4a,0x4a,0x8a,0xe1,0xd3,0xa7, + 0x4f,0xc,0xff,0xfe,0xfd,0x63,0xf8,0xf5,0xeb,0x17,0xd8,0x8c,0x9f,0x3f,0x7f,0x32, + 0xfc,0xf9,0xf3,0x7,0xce,0x6,0x31,0xfe,0xfe,0xfd,0xb,0x56,0xc3,0xc4,0xc4,0x4, + 0x66,0x33,0x2e,0x5b,0xbe,0xfc,0xff,0xdd,0xbb,0x77,0x89,0xb5,0x14,0xac,0x8e,0x83, + 0x83,0x83,0x81,0x99,0x85,0x85,0x81,0x11,0xe4,0x6c,0x92,0x74,0x22,0x29,0x66,0x79, + 0xf7,0xfe,0x23,0x8a,0x5e,0x47,0x47,0x7b,0x86,0xd8,0x98,0x68,0xc,0xf3,0x16,0x2f, + 0x59,0xca,0xb0,0x7f,0xff,0x41,0x14,0x71,0xc6,0xc0,0xa0,0x60,0x14,0x9b,0x17,0x2e, + 0x5e,0x82,0xd3,0x21,0xf1,0xb1,0x31,0x28,0x72,0x2c,0x57,0xae,0xde,0x60,0x90,0x91, + 0x91,0x41,0x11,0x74,0x76,0x74,0xc6,0x30,0x60,0xef,0xfe,0xbd,0xc,0x1f,0x3e,0x7e, + 0x81,0x8b,0x3f,0x79,0xf2,0x84,0x81,0x51,0x46,0x41,0x9,0xc5,0xe6,0x9d,0xfb,0x8f, + 0x30,0xb8,0x3b,0xda,0x60,0x68,0xc6,0x26,0xce,0xc4,0xca,0xc6,0xc1,0x80,0x8c,0x41, + 0xba,0xd0,0xc5,0x40,0x7c,0x6c,0xe2,0x4c,0x6c,0x6c,0x6c,0xc,0xc8,0x18,0xa4,0x8, + 0x5d,0xc,0xc4,0xc7,0x26,0xce,0x82,0xee,0xbe,0x85,0x33,0xa7,0x32,0xac,0xdb,0xbc, + 0xd,0xc3,0xd9,0x20,0x71,0x74,0xc0,0xa8,0xae,0x63,0x40,0x76,0x3c,0x33,0x91,0x9b, + 0x40,0x40,0xfa,0x98,0xb4,0xd4,0x94,0x19,0x58,0x58,0xd9,0xe0,0xf8,0x3f,0x3,0x23, + 0xc3,0xef,0xdf,0x7f,0x30,0x30,0x48,0x1c,0x59,0x1d,0x48,0x1f,0x38,0xaa,0x4c,0x8d, + 0xc,0x49,0x76,0xc0,0xe9,0x73,0xe7,0x19,0x0,0xf5,0x51,0x6e,0x55,0xe,0xb1,0x2, + 0x8,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae,0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/img/bottomBorder.png + 0x0,0x0,0x0,0xa4, + 0x89, + 0x50,0x4e,0x47,0xd,0xa,0x1a,0xa,0x0,0x0,0x0,0xd,0x49,0x48,0x44,0x52,0x0, + 0x0,0x0,0x15,0x0,0x0,0x0,0x18,0x8,0x6,0x0,0x0,0x0,0x15,0x89,0xb6,0x48, + 0x0,0x0,0x0,0x1,0x73,0x52,0x47,0x42,0x0,0xae,0xce,0x1c,0xe9,0x0,0x0,0x0, + 0x4,0x67,0x41,0x4d,0x41,0x0,0x0,0xb1,0x8f,0xb,0xfc,0x61,0x5,0x0,0x0,0x0, + 0x9,0x70,0x48,0x59,0x73,0x0,0x0,0xe,0xc4,0x0,0x0,0xe,0xc4,0x1,0x95,0x2b, + 0xe,0x1b,0x0,0x0,0x0,0x39,0x49,0x44,0x41,0x54,0x48,0x4b,0x63,0x8c,0x8c,0x4f, + 0xf9,0xcf,0x40,0x65,0xc0,0x68,0x63,0x63,0x43,0x75,0x43,0x99,0xa8,0xec,0x48,0xb0, + 0x71,0xa3,0x86,0x52,0x3f,0x54,0x47,0xc3,0x74,0x34,0x4c,0xa9,0x1c,0x2,0xa3,0x49, + 0x8a,0xca,0x1,0x3a,0x5a,0xf4,0xd,0x9d,0x24,0xc5,0x48,0x8b,0x2a,0x1a,0x0,0x23, + 0x47,0x6,0x17,0xb6,0x4d,0xc5,0x92,0x0,0x0,0x0,0x0,0x49,0x45,0x4e,0x44,0xae, + 0x42,0x60,0x82, + // C:/Users/hvh/Documents/Visual Studio 2010/Projects/cuSDR32/res/cl/vectoradd.cl + 0x0,0x0,0x9,0x37, + 0x2f, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0xa,0x2a,0x2a,0xa, + 0x2a,0x2a,0x20,0x43,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20,0x28,0x43,0x29, + 0x20,0x32,0x30,0x31,0x30,0x20,0x4e,0x6f,0x6b,0x69,0x61,0x20,0x43,0x6f,0x72,0x70, + 0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x2f,0x6f,0x72,0x20,0x69, + 0x74,0x73,0x20,0x73,0x75,0x62,0x73,0x69,0x64,0x69,0x61,0x72,0x79,0x28,0x2d,0x69, + 0x65,0x73,0x29,0x2e,0xa,0x2a,0x2a,0x20,0x41,0x6c,0x6c,0x20,0x72,0x69,0x67,0x68, + 0x74,0x73,0x20,0x72,0x65,0x73,0x65,0x72,0x76,0x65,0x64,0x2e,0xa,0x2a,0x2a,0x20, + 0x43,0x6f,0x6e,0x74,0x61,0x63,0x74,0x3a,0x20,0x4e,0x6f,0x6b,0x69,0x61,0x20,0x43, + 0x6f,0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x20,0x28,0x71,0x74,0x2d,0x69, + 0x6e,0x66,0x6f,0x40,0x6e,0x6f,0x6b,0x69,0x61,0x2e,0x63,0x6f,0x6d,0x29,0xa,0x2a, + 0x2a,0xa,0x2a,0x2a,0x20,0x54,0x68,0x69,0x73,0x20,0x66,0x69,0x6c,0x65,0x20,0x69, + 0x73,0x20,0x70,0x61,0x72,0x74,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x65,0x78, + 0x61,0x6d,0x70,0x6c,0x65,0x73,0x20,0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x51,0x74, + 0x20,0x54,0x6f,0x6f,0x6c,0x6b,0x69,0x74,0x2e,0xa,0x2a,0x2a,0xa,0x2a,0x2a,0x20, + 0x24,0x51,0x54,0x5f,0x42,0x45,0x47,0x49,0x4e,0x5f,0x4c,0x49,0x43,0x45,0x4e,0x53, + 0x45,0x3a,0x42,0x53,0x44,0x24,0xa,0x2a,0x2a,0x20,0x59,0x6f,0x75,0x20,0x6d,0x61, + 0x79,0x20,0x75,0x73,0x65,0x20,0x74,0x68,0x69,0x73,0x20,0x66,0x69,0x6c,0x65,0x20, + 0x75,0x6e,0x64,0x65,0x72,0x20,0x74,0x68,0x65,0x20,0x74,0x65,0x72,0x6d,0x73,0x20, + 0x6f,0x66,0x20,0x74,0x68,0x65,0x20,0x42,0x53,0x44,0x20,0x6c,0x69,0x63,0x65,0x6e, + 0x73,0x65,0x20,0x61,0x73,0x20,0x66,0x6f,0x6c,0x6c,0x6f,0x77,0x73,0x3a,0xa,0x2a, + 0x2a,0xa,0x2a,0x2a,0x20,0x22,0x52,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75, + 0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x75,0x73,0x65,0x20,0x69,0x6e,0x20, + 0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x61,0x6e,0x64,0x20,0x62,0x69,0x6e,0x61,0x72, + 0x79,0x20,0x66,0x6f,0x72,0x6d,0x73,0x2c,0x20,0x77,0x69,0x74,0x68,0x20,0x6f,0x72, + 0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74,0xa,0x2a,0x2a,0x20,0x6d,0x6f,0x64,0x69, + 0x66,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,0x2c,0x20,0x61,0x72,0x65,0x20,0x70,0x65, + 0x72,0x6d,0x69,0x74,0x74,0x65,0x64,0x20,0x70,0x72,0x6f,0x76,0x69,0x64,0x65,0x64, + 0x20,0x74,0x68,0x61,0x74,0x20,0x74,0x68,0x65,0x20,0x66,0x6f,0x6c,0x6c,0x6f,0x77, + 0x69,0x6e,0x67,0x20,0x63,0x6f,0x6e,0x64,0x69,0x74,0x69,0x6f,0x6e,0x73,0x20,0x61, + 0x72,0x65,0xa,0x2a,0x2a,0x20,0x6d,0x65,0x74,0x3a,0xa,0x2a,0x2a,0x20,0x20,0x20, + 0x2a,0x20,0x52,0x65,0x64,0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x69,0x6f,0x6e, + 0x73,0x20,0x6f,0x66,0x20,0x73,0x6f,0x75,0x72,0x63,0x65,0x20,0x63,0x6f,0x64,0x65, + 0x20,0x6d,0x75,0x73,0x74,0x20,0x72,0x65,0x74,0x61,0x69,0x6e,0x20,0x74,0x68,0x65, + 0x20,0x61,0x62,0x6f,0x76,0x65,0x20,0x63,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74, + 0xa,0x2a,0x2a,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x74,0x69,0x63,0x65,0x2c,0x20, + 0x74,0x68,0x69,0x73,0x20,0x6c,0x69,0x73,0x74,0x20,0x6f,0x66,0x20,0x63,0x6f,0x6e, + 0x64,0x69,0x74,0x69,0x6f,0x6e,0x73,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20, + 0x66,0x6f,0x6c,0x6c,0x6f,0x77,0x69,0x6e,0x67,0x20,0x64,0x69,0x73,0x63,0x6c,0x61, + 0x69,0x6d,0x65,0x72,0x2e,0xa,0x2a,0x2a,0x20,0x20,0x20,0x2a,0x20,0x52,0x65,0x64, + 0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x69,0x6f,0x6e,0x73,0x20,0x69,0x6e,0x20, + 0x62,0x69,0x6e,0x61,0x72,0x79,0x20,0x66,0x6f,0x72,0x6d,0x20,0x6d,0x75,0x73,0x74, + 0x20,0x72,0x65,0x70,0x72,0x6f,0x64,0x75,0x63,0x65,0x20,0x74,0x68,0x65,0x20,0x61, + 0x62,0x6f,0x76,0x65,0x20,0x63,0x6f,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0xa,0x2a, + 0x2a,0x20,0x20,0x20,0x20,0x20,0x6e,0x6f,0x74,0x69,0x63,0x65,0x2c,0x20,0x74,0x68, + 0x69,0x73,0x20,0x6c,0x69,0x73,0x74,0x20,0x6f,0x66,0x20,0x63,0x6f,0x6e,0x64,0x69, + 0x74,0x69,0x6f,0x6e,0x73,0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,0x20,0x66,0x6f, + 0x6c,0x6c,0x6f,0x77,0x69,0x6e,0x67,0x20,0x64,0x69,0x73,0x63,0x6c,0x61,0x69,0x6d, + 0x65,0x72,0x20,0x69,0x6e,0xa,0x2a,0x2a,0x20,0x20,0x20,0x20,0x20,0x74,0x68,0x65, + 0x20,0x64,0x6f,0x63,0x75,0x6d,0x65,0x6e,0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61, + 0x6e,0x64,0x2f,0x6f,0x72,0x20,0x6f,0x74,0x68,0x65,0x72,0x20,0x6d,0x61,0x74,0x65, + 0x72,0x69,0x61,0x6c,0x73,0x20,0x70,0x72,0x6f,0x76,0x69,0x64,0x65,0x64,0x20,0x77, + 0x69,0x74,0x68,0x20,0x74,0x68,0x65,0xa,0x2a,0x2a,0x20,0x20,0x20,0x20,0x20,0x64, + 0x69,0x73,0x74,0x72,0x69,0x62,0x75,0x74,0x69,0x6f,0x6e,0x2e,0xa,0x2a,0x2a,0x20, + 0x20,0x20,0x2a,0x20,0x4e,0x65,0x69,0x74,0x68,0x65,0x72,0x20,0x74,0x68,0x65,0x20, + 0x6e,0x61,0x6d,0x65,0x20,0x6f,0x66,0x20,0x4e,0x6f,0x6b,0x69,0x61,0x20,0x43,0x6f, + 0x72,0x70,0x6f,0x72,0x61,0x74,0x69,0x6f,0x6e,0x20,0x61,0x6e,0x64,0x20,0x69,0x74, + 0x73,0x20,0x53,0x75,0x62,0x73,0x69,0x64,0x69,0x61,0x72,0x79,0x28,0x2d,0x69,0x65, + 0x73,0x29,0x20,0x6e,0x6f,0x72,0xa,0x2a,0x2a,0x20,0x20,0x20,0x20,0x20,0x74,0x68, + 0x65,0x20,0x6e,0x61,0x6d,0x65,0x73,0x20,0x6f,0x66,0x20,0x69,0x74,0x73,0x20,0x63, + 0x6f,0x6e,0x74,0x72,0x69,0x62,0x75,0x74,0x6f,0x72,0x73,0x20,0x6d,0x61,0x79,0x20, + 0x62,0x65,0x20,0x75,0x73,0x65,0x64,0x20,0x74,0x6f,0x20,0x65,0x6e,0x64,0x6f,0x72, + 0x73,0x65,0x20,0x6f,0x72,0x20,0x70,0x72,0x6f,0x6d,0x6f,0x74,0x65,0xa,0x2a,0x2a, + 0x20,0x20,0x20,0x20,0x20,0x70,0x72,0x6f,0x64,0x75,0x63,0x74,0x73,0x20,0x64,0x65, + 0x72,0x69,0x76,0x65,0x64,0x20,0x66,0x72,0x6f,0x6d,0x20,0x74,0x68,0x69,0x73,0x20, + 0x73,0x6f,0x66,0x74,0x77,0x61,0x72,0x65,0x20,0x77,0x69,0x74,0x68,0x6f,0x75,0x74, + 0x20,0x73,0x70,0x65,0x63,0x69,0x66,0x69,0x63,0x20,0x70,0x72,0x69,0x6f,0x72,0x20, + 0x77,0x72,0x69,0x74,0x74,0x65,0x6e,0xa,0x2a,0x2a,0x20,0x20,0x20,0x20,0x20,0x70, + 0x65,0x72,0x6d,0x69,0x73,0x73,0x69,0x6f,0x6e,0x2e,0xa,0x2a,0x2a,0xa,0x2a,0x2a, + 0x20,0x54,0x48,0x49,0x53,0x20,0x53,0x4f,0x46,0x54,0x57,0x41,0x52,0x45,0x20,0x49, + 0x53,0x20,0x50,0x52,0x4f,0x56,0x49,0x44,0x45,0x44,0x20,0x42,0x59,0x20,0x54,0x48, + 0x45,0x20,0x43,0x4f,0x50,0x59,0x52,0x49,0x47,0x48,0x54,0x20,0x48,0x4f,0x4c,0x44, + 0x45,0x52,0x53,0x20,0x41,0x4e,0x44,0x20,0x43,0x4f,0x4e,0x54,0x52,0x49,0x42,0x55, + 0x54,0x4f,0x52,0x53,0xa,0x2a,0x2a,0x20,0x22,0x41,0x53,0x20,0x49,0x53,0x22,0x20, + 0x41,0x4e,0x44,0x20,0x41,0x4e,0x59,0x20,0x45,0x58,0x50,0x52,0x45,0x53,0x53,0x20, + 0x4f,0x52,0x20,0x49,0x4d,0x50,0x4c,0x49,0x45,0x44,0x20,0x57,0x41,0x52,0x52,0x41, + 0x4e,0x54,0x49,0x45,0x53,0x2c,0x20,0x49,0x4e,0x43,0x4c,0x55,0x44,0x49,0x4e,0x47, + 0x2c,0x20,0x42,0x55,0x54,0x20,0x4e,0x4f,0x54,0xa,0x2a,0x2a,0x20,0x4c,0x49,0x4d, + 0x49,0x54,0x45,0x44,0x20,0x54,0x4f,0x2c,0x20,0x54,0x48,0x45,0x20,0x49,0x4d,0x50, + 0x4c,0x49,0x45,0x44,0x20,0x57,0x41,0x52,0x52,0x41,0x4e,0x54,0x49,0x45,0x53,0x20, + 0x4f,0x46,0x20,0x4d,0x45,0x52,0x43,0x48,0x41,0x4e,0x54,0x41,0x42,0x49,0x4c,0x49, + 0x54,0x59,0x20,0x41,0x4e,0x44,0x20,0x46,0x49,0x54,0x4e,0x45,0x53,0x53,0x20,0x46, + 0x4f,0x52,0xa,0x2a,0x2a,0x20,0x41,0x20,0x50,0x41,0x52,0x54,0x49,0x43,0x55,0x4c, + 0x41,0x52,0x20,0x50,0x55,0x52,0x50,0x4f,0x53,0x45,0x20,0x41,0x52,0x45,0x20,0x44, + 0x49,0x53,0x43,0x4c,0x41,0x49,0x4d,0x45,0x44,0x2e,0x20,0x49,0x4e,0x20,0x4e,0x4f, + 0x20,0x45,0x56,0x45,0x4e,0x54,0x20,0x53,0x48,0x41,0x4c,0x4c,0x20,0x54,0x48,0x45, + 0x20,0x43,0x4f,0x50,0x59,0x52,0x49,0x47,0x48,0x54,0xa,0x2a,0x2a,0x20,0x4f,0x57, + 0x4e,0x45,0x52,0x20,0x4f,0x52,0x20,0x43,0x4f,0x4e,0x54,0x52,0x49,0x42,0x55,0x54, + 0x4f,0x52,0x53,0x20,0x42,0x45,0x20,0x4c,0x49,0x41,0x42,0x4c,0x45,0x20,0x46,0x4f, + 0x52,0x20,0x41,0x4e,0x59,0x20,0x44,0x49,0x52,0x45,0x43,0x54,0x2c,0x20,0x49,0x4e, + 0x44,0x49,0x52,0x45,0x43,0x54,0x2c,0x20,0x49,0x4e,0x43,0x49,0x44,0x45,0x4e,0x54, + 0x41,0x4c,0x2c,0xa,0x2a,0x2a,0x20,0x53,0x50,0x45,0x43,0x49,0x41,0x4c,0x2c,0x20, + 0x45,0x58,0x45,0x4d,0x50,0x4c,0x41,0x52,0x59,0x2c,0x20,0x4f,0x52,0x20,0x43,0x4f, + 0x4e,0x53,0x45,0x51,0x55,0x45,0x4e,0x54,0x49,0x41,0x4c,0x20,0x44,0x41,0x4d,0x41, + 0x47,0x45,0x53,0x20,0x28,0x49,0x4e,0x43,0x4c,0x55,0x44,0x49,0x4e,0x47,0x2c,0x20, + 0x42,0x55,0x54,0x20,0x4e,0x4f,0x54,0xa,0x2a,0x2a,0x20,0x4c,0x49,0x4d,0x49,0x54, + 0x45,0x44,0x20,0x54,0x4f,0x2c,0x20,0x50,0x52,0x4f,0x43,0x55,0x52,0x45,0x4d,0x45, + 0x4e,0x54,0x20,0x4f,0x46,0x20,0x53,0x55,0x42,0x53,0x54,0x49,0x54,0x55,0x54,0x45, + 0x20,0x47,0x4f,0x4f,0x44,0x53,0x20,0x4f,0x52,0x20,0x53,0x45,0x52,0x56,0x49,0x43, + 0x45,0x53,0x3b,0x20,0x4c,0x4f,0x53,0x53,0x20,0x4f,0x46,0x20,0x55,0x53,0x45,0x2c, + 0xa,0x2a,0x2a,0x20,0x44,0x41,0x54,0x41,0x2c,0x20,0x4f,0x52,0x20,0x50,0x52,0x4f, + 0x46,0x49,0x54,0x53,0x3b,0x20,0x4f,0x52,0x20,0x42,0x55,0x53,0x49,0x4e,0x45,0x53, + 0x53,0x20,0x49,0x4e,0x54,0x45,0x52,0x52,0x55,0x50,0x54,0x49,0x4f,0x4e,0x29,0x20, + 0x48,0x4f,0x57,0x45,0x56,0x45,0x52,0x20,0x43,0x41,0x55,0x53,0x45,0x44,0x20,0x41, + 0x4e,0x44,0x20,0x4f,0x4e,0x20,0x41,0x4e,0x59,0xa,0x2a,0x2a,0x20,0x54,0x48,0x45, + 0x4f,0x52,0x59,0x20,0x4f,0x46,0x20,0x4c,0x49,0x41,0x42,0x49,0x4c,0x49,0x54,0x59, + 0x2c,0x20,0x57,0x48,0x45,0x54,0x48,0x45,0x52,0x20,0x49,0x4e,0x20,0x43,0x4f,0x4e, + 0x54,0x52,0x41,0x43,0x54,0x2c,0x20,0x53,0x54,0x52,0x49,0x43,0x54,0x20,0x4c,0x49, + 0x41,0x42,0x49,0x4c,0x49,0x54,0x59,0x2c,0x20,0x4f,0x52,0x20,0x54,0x4f,0x52,0x54, + 0xa,0x2a,0x2a,0x20,0x28,0x49,0x4e,0x43,0x4c,0x55,0x44,0x49,0x4e,0x47,0x20,0x4e, + 0x45,0x47,0x4c,0x49,0x47,0x45,0x4e,0x43,0x45,0x20,0x4f,0x52,0x20,0x4f,0x54,0x48, + 0x45,0x52,0x57,0x49,0x53,0x45,0x29,0x20,0x41,0x52,0x49,0x53,0x49,0x4e,0x47,0x20, + 0x49,0x4e,0x20,0x41,0x4e,0x59,0x20,0x57,0x41,0x59,0x20,0x4f,0x55,0x54,0x20,0x4f, + 0x46,0x20,0x54,0x48,0x45,0x20,0x55,0x53,0x45,0xa,0x2a,0x2a,0x20,0x4f,0x46,0x20, + 0x54,0x48,0x49,0x53,0x20,0x53,0x4f,0x46,0x54,0x57,0x41,0x52,0x45,0x2c,0x20,0x45, + 0x56,0x45,0x4e,0x20,0x49,0x46,0x20,0x41,0x44,0x56,0x49,0x53,0x45,0x44,0x20,0x4f, + 0x46,0x20,0x54,0x48,0x45,0x20,0x50,0x4f,0x53,0x53,0x49,0x42,0x49,0x4c,0x49,0x54, + 0x59,0x20,0x4f,0x46,0x20,0x53,0x55,0x43,0x48,0x20,0x44,0x41,0x4d,0x41,0x47,0x45, + 0x2e,0x22,0xa,0x2a,0x2a,0x20,0x24,0x51,0x54,0x5f,0x45,0x4e,0x44,0x5f,0x4c,0x49, + 0x43,0x45,0x4e,0x53,0x45,0x24,0xa,0x2a,0x2a,0xa,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2a, + 0x2a,0x2a,0x2a,0x2a,0x2a,0x2a,0x2f,0xa,0xa,0x2f,0x2f,0x21,0x20,0x5b,0x31,0x5d, + 0xa,0x20,0x20,0x20,0x20,0x5f,0x5f,0x6b,0x65,0x72,0x6e,0x65,0x6c,0x20,0x76,0x6f, + 0x69,0x64,0x20,0x76,0x65,0x63,0x74,0x6f,0x72,0x41,0x64,0x64,0x28,0x5f,0x5f,0x67, + 0x6c,0x6f,0x62,0x61,0x6c,0x20,0x5f,0x5f,0x72,0x65,0x61,0x64,0x5f,0x6f,0x6e,0x6c, + 0x79,0x20,0x69,0x6e,0x74,0x20,0x2a,0x69,0x6e,0x70,0x75,0x74,0x31,0x2c,0xa,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x5f,0x67,0x6c,0x6f, + 0x62,0x61,0x6c,0x20,0x5f,0x5f,0x72,0x65,0x61,0x64,0x5f,0x6f,0x6e,0x6c,0x79,0x20, + 0x69,0x6e,0x74,0x20,0x2a,0x69,0x6e,0x70,0x75,0x74,0x32,0x2c,0xa,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x5f,0x5f,0x67,0x6c,0x6f,0x62,0x61, + 0x6c,0x20,0x5f,0x5f,0x77,0x72,0x69,0x74,0x65,0x5f,0x6f,0x6e,0x6c,0x79,0x20,0x69, + 0x6e,0x74,0x20,0x2a,0x6f,0x75,0x74,0x70,0x75,0x74,0x29,0xa,0x20,0x20,0x20,0x20, + 0x7b,0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x75,0x6e,0x73,0x69,0x67,0x6e, + 0x65,0x64,0x20,0x69,0x6e,0x74,0x20,0x69,0x6e,0x64,0x65,0x78,0x20,0x3d,0x20,0x67, + 0x65,0x74,0x5f,0x67,0x6c,0x6f,0x62,0x61,0x6c,0x5f,0x69,0x64,0x28,0x30,0x29,0x3b, + 0xa,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x6f,0x75,0x74,0x70,0x75,0x74,0x5b, + 0x69,0x6e,0x64,0x65,0x78,0x5d,0x20,0x3d,0x20,0x69,0x6e,0x70,0x75,0x74,0x31,0x5b, + 0x69,0x6e,0x64,0x65,0x78,0x5d,0x20,0x2b,0x20,0x69,0x6e,0x70,0x75,0x74,0x32,0x5b, + 0x69,0x6e,0x64,0x65,0x78,0x5d,0x3b,0xa,0x20,0x20,0x20,0x20,0x7d,0xa,0x2f,0x2f, + 0x21,0x20,0x5b,0x31,0x5d,0xa, + +}; + +static const unsigned char qt_resource_name[] = { + // cl + 0x0,0x2, + 0x0,0x0,0x6,0x9c, + 0x0,0x63, + 0x0,0x6c, + // img + 0x0,0x3, + 0x0,0x0,0x70,0x37, + 0x0,0x69, + 0x0,0x6d,0x0,0x67, + // drawer.png + 0x0,0xa, + 0xd,0xc8,0x26,0x47, + 0x0,0x64, + 0x0,0x72,0x0,0x61,0x0,0x77,0x0,0x65,0x0,0x72,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // close.png + 0x0,0x9, + 0x6,0x98,0x83,0x27, + 0x0,0x63, + 0x0,0x6c,0x0,0x6f,0x0,0x73,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // leftMiddle.png + 0x0,0xe, + 0xc,0x96,0x34,0xa7, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x4d,0x0,0x69,0x0,0x64,0x0,0x64,0x0,0x6c,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // maximize.png + 0x0,0xc, + 0xf,0x79,0xb7,0xc7, + 0x0,0x6d, + 0x0,0x61,0x0,0x78,0x0,0x69,0x0,0x6d,0x0,0x69,0x0,0x7a,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // cuSDR_32.ico + 0x0,0xc, + 0xf,0x31,0xbc,0x9f, + 0x0,0x63, + 0x0,0x75,0x0,0x53,0x0,0x44,0x0,0x52,0x0,0x5f,0x0,0x33,0x0,0x32,0x0,0x2e,0x0,0x69,0x0,0x63,0x0,0x6f, + // rightMiddle.png + 0x0,0xf, + 0x0,0xd7,0xcb,0xe7, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x4d,0x0,0x69,0x0,0x64,0x0,0x64,0x0,0x6c,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // rightTop.png + 0x0,0xc, + 0x4,0x7c,0xe8,0x67, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x54,0x0,0x6f,0x0,0x70,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // minimize_high.png + 0x0,0x11, + 0x6,0x2a,0x28,0x87, + 0x0,0x6d, + 0x0,0x69,0x0,0x6e,0x0,0x69,0x0,0x6d,0x0,0x69,0x0,0x7a,0x0,0x65,0x0,0x5f,0x0,0x68,0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + + // leftBottom.png + 0x0,0xe, + 0xc,0xf1,0x66,0x87, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x42,0x0,0x6f,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6d,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // left.png + 0x0,0x8, + 0xb,0xd7,0x59,0x7, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // hide.png + 0x0,0x8, + 0xf,0xa8,0x5a,0x87, + 0x0,0x68, + 0x0,0x69,0x0,0x64,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // right_arrow.png + 0x0,0xf, + 0x2,0x9f,0x5,0x87, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x5f,0x0,0x61,0x0,0x72,0x0,0x72,0x0,0x6f,0x0,0x77,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // minimize.png + 0x0,0xc, + 0xf,0x88,0xf7,0xc7, + 0x0,0x6d, + 0x0,0x69,0x0,0x6e,0x0,0x69,0x0,0x6d,0x0,0x69,0x0,0x7a,0x0,0x65,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // close_high.png + 0x0,0xe, + 0x9,0x8,0x26,0x7, + 0x0,0x63, + 0x0,0x6c,0x0,0x6f,0x0,0x73,0x0,0x65,0x0,0x5f,0x0,0x68,0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // cusdr4.png + 0x0,0xa, + 0xb,0x5a,0xe,0x67, + 0x0,0x63, + 0x0,0x75,0x0,0x73,0x0,0x64,0x0,0x72,0x0,0x34,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // cuSDR_64.ico + 0x0,0xc, + 0xf,0xc3,0xbc,0x9f, + 0x0,0x63, + 0x0,0x75,0x0,0x53,0x0,0x44,0x0,0x52,0x0,0x5f,0x0,0x36,0x0,0x34,0x0,0x2e,0x0,0x69,0x0,0x63,0x0,0x6f, + // down_arrow.png + 0x0,0xe, + 0x4,0xa2,0xfc,0xa7, + 0x0,0x64, + 0x0,0x6f,0x0,0x77,0x0,0x6e,0x0,0x5f,0x0,0x61,0x0,0x72,0x0,0x72,0x0,0x6f,0x0,0x77,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // cusdrLogo.png + 0x0,0xd, + 0x0,0x75,0x38,0x87, + 0x0,0x63, + 0x0,0x75,0x0,0x73,0x0,0x64,0x0,0x72,0x0,0x4c,0x0,0x6f,0x0,0x67,0x0,0x6f,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // cusdrLogo2.png + 0x0,0xe, + 0x7,0x13,0xab,0x47, + 0x0,0x63, + 0x0,0x75,0x0,0x73,0x0,0x64,0x0,0x72,0x0,0x4c,0x0,0x6f,0x0,0x67,0x0,0x6f,0x0,0x32,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // right.png + 0x0,0x9, + 0xd,0xf7,0xa6,0xa7, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // topBorder.png + 0x0,0xd, + 0xc,0xc,0x7b,0xa7, + 0x0,0x74, + 0x0,0x6f,0x0,0x70,0x0,0x42,0x0,0x6f,0x0,0x72,0x0,0x64,0x0,0x65,0x0,0x72,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // up_arrow.png + 0x0,0xc, + 0x6,0xe6,0xe6,0x67, + 0x0,0x75, + 0x0,0x70,0x0,0x5f,0x0,0x61,0x0,0x72,0x0,0x72,0x0,0x6f,0x0,0x77,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // hpsdr4.png + 0x0,0xa, + 0xb,0x5a,0xb8,0x67, + 0x0,0x68, + 0x0,0x70,0x0,0x73,0x0,0x64,0x0,0x72,0x0,0x34,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // rightBottom.png + 0x0,0xf, + 0x0,0xb0,0x99,0xc7, + 0x0,0x72, + 0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x74,0x0,0x42,0x0,0x6f,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6d,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // leftTop.png + 0x0,0xb, + 0xb,0x86,0x2c,0x67, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x54,0x0,0x6f,0x0,0x70,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // hide_high.png + 0x0,0xd, + 0x2,0x2e,0x3d,0x27, + 0x0,0x68, + 0x0,0x69,0x0,0x64,0x0,0x65,0x0,0x5f,0x0,0x68,0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // left_arrow.png + 0x0,0xe, + 0xe,0xde,0xfa,0xc7, + 0x0,0x6c, + 0x0,0x65,0x0,0x66,0x0,0x74,0x0,0x5f,0x0,0x61,0x0,0x72,0x0,0x72,0x0,0x6f,0x0,0x77,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // maximize_high.png + 0x0,0x11, + 0x6,0x34,0x0,0x87, + 0x0,0x6d, + 0x0,0x61,0x0,0x78,0x0,0x69,0x0,0x6d,0x0,0x69,0x0,0x7a,0x0,0x65,0x0,0x5f,0x0,0x68,0x0,0x69,0x0,0x67,0x0,0x68,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + + // bottomBorder.png + 0x0,0x10, + 0xc,0x1c,0x20,0xa7, + 0x0,0x62, + 0x0,0x6f,0x0,0x74,0x0,0x74,0x0,0x6f,0x0,0x6d,0x0,0x42,0x0,0x6f,0x0,0x72,0x0,0x64,0x0,0x65,0x0,0x72,0x0,0x2e,0x0,0x70,0x0,0x6e,0x0,0x67, + // vectoradd.cl + 0x0,0xc, + 0x7,0xed,0x22,0x5c, + 0x0,0x76, + 0x0,0x65,0x0,0x63,0x0,0x74,0x0,0x6f,0x0,0x72,0x0,0x61,0x0,0x64,0x0,0x64,0x0,0x2e,0x0,0x63,0x0,0x6c, + +}; + +static const unsigned char qt_resource_struct[] = { + // : + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1, + // :/cl + 0x0,0x0,0x0,0x0,0x0,0x2,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x20, + // :/img + 0x0,0x0,0x0,0xa,0x0,0x2,0x0,0x0,0x0,0x1d,0x0,0x0,0x0,0x3, + // :/img/cusdrLogo.png + 0x0,0x0,0x2,0x1c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x6a,0xd4, + // :/img/rightBottom.png + 0x0,0x0,0x2,0xce,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xf7,0x71, + // :/img/rightMiddle.png + 0x0,0x0,0x0,0xa6,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x15,0x4a, + // :/img/hide_high.png + 0x0,0x0,0x3,0xe,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xf8,0xe3, + // :/img/right_arrow.png + 0x0,0x0,0x1,0x5e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1b,0x8c, + // :/img/rightTop.png + 0x0,0x0,0x0,0xca,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x15,0xd3, + // :/img/down_arrow.png + 0x0,0x0,0x1,0xfa,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x6a,0x4b, + // :/img/minimize_high.png + 0x0,0x0,0x0,0xe8,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x16,0x7d, + // :/img/maximize_high.png + 0x0,0x0,0x3,0x50,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xfb,0x3a, + // :/img/close.png + 0x0,0x0,0x0,0x30,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0xc4, + // :/img/up_arrow.png + 0x0,0x0,0x2,0x96,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0x95,0xbe, + // :/img/cusdrLogo2.png + 0x0,0x0,0x2,0x3c,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x2,0x7b,0x46, + // :/img/close_high.png + 0x0,0x0,0x1,0xa0,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1e,0x4c, + // :/img/cusdr4.png + 0x0,0x0,0x1,0xc2,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x20,0x7, + // :/img/hpsdr4.png + 0x0,0x0,0x2,0xb4,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0x96,0x3f, + // :/img/leftTop.png + 0x0,0x0,0x2,0xf2,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xf8,0x3d, + // :/img/left.png + 0x0,0x0,0x1,0x32,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x19,0x19, + // :/img/topBorder.png + 0x0,0x0,0x2,0x76,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0x95,0x2a, + // :/img/bottomBorder.png + 0x0,0x0,0x3,0x78,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xfc,0xcc, + // :/img/leftMiddle.png + 0x0,0x0,0x0,0x48,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2,0x61, + // :/img/leftBottom.png + 0x0,0x0,0x1,0x10,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x18,0x54, + // :/img/drawer.png + 0x0,0x0,0x0,0x16,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x0,0x0, + // :/img/right.png + 0x0,0x0,0x2,0x5e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0x94,0x96, + // :/img/left_arrow.png + 0x0,0x0,0x3,0x2e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xfa,0x71, + // :/img/cuSDR_32.ico + 0x0,0x0,0x0,0x88,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x4,0x88, + // :/img/maximize.png + 0x0,0x0,0x0,0x6a,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x2,0xe3, + // :/img/minimize.png + 0x0,0x0,0x1,0x82,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x1c,0x55, + // :/img/hide.png + 0x0,0x0,0x1,0x48,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x19,0xd5, + // :/img/cuSDR_64.ico + 0x0,0x0,0x1,0xdc,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x0,0x28,0x9, + // :/cl/vectoradd.cl + 0x0,0x0,0x3,0x9e,0x0,0x0,0x0,0x0,0x0,0x1,0x0,0x4,0xfd,0x74, + +}; + +QT_BEGIN_NAMESPACE + +extern Q_CORE_EXPORT bool qRegisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +extern Q_CORE_EXPORT bool qUnregisterResourceData + (int, const unsigned char *, const unsigned char *, const unsigned char *); + +QT_END_NAMESPACE + + +int QT_MANGLE_NAMESPACE(qInitResources_cusdr)() +{ + QT_PREPEND_NAMESPACE(qRegisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_CONSTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qInitResources_cusdr)) + +int QT_MANGLE_NAMESPACE(qCleanupResources_cusdr)() +{ + QT_PREPEND_NAMESPACE(qUnregisterResourceData) + (0x01, qt_resource_struct, qt_resource_name, qt_resource_data); + return 1; +} + +Q_DESTRUCTOR_FUNCTION(QT_MANGLE_NAMESPACE(qCleanupResources_cusdr)) + diff --git a/Source/src/AudioEngine/cusdr_audio_engine.cpp b/Source/src/AudioEngine/cusdr_audio_engine.cpp new file mode 100644 index 0000000..52f7fc7 --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_engine.cpp @@ -0,0 +1,1465 @@ +/** +* @file cusdr_audio_engine.cpp +* @brief cuSDR audio engine +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//#define LOG_AUDIO_ENGINE + +#include "cusdr_audio_engine.h" +#include "cusdr_audio_settingsdialog.h" +#include "cusdr_audio_utils.h" +#include "cusdr_settings.h" + +//#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +struct SWavHeader { + + char chunkID[4]; + unsigned int chunkSize; + char format[4]; + + unsigned char subchunk1id[4]; + unsigned int subchunk1size; + unsigned short audioFormat; + unsigned short nofChannels; + unsigned int sampleRate; + unsigned int byteRate; + unsigned short blockAlign; + unsigned short bitsPerSample; + + unsigned char subchunk2id[4]; + unsigned int subchunk2size; +}; + + +//const qint64 BufferDurationUs = 10 * 1000000; +const int NotifyIntervalMs = 1; + +// Size of the level calculation window in microseconds +const int LevelWindowUs = 0.1 * 1000000; + +// Waveform window size in microseconds +//const qint64 WaveformWindowDuration = 500 * 1000; + +QDebug& operator<<(QDebug &debug, const QAudioFormat &format) { + + debug << format.sampleRate() << "Hz" + << format.channelCount() << "channels"; + return debug; +} + +AudioEngine::AudioEngine(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_mode(QAudio::AudioInput) + , m_state(QAudio::StoppedState) + , m_serverMode(set->getCurrentServerMode()) + , m_generateTone(false) + , m_generateLocalChirp(false) + , m_lowerChirpFreq(set->getLowerChirpFreq()) + , m_upperChirpFreq(set->getUpperChirpFreq()) + , m_chirpAmplitude(set->getChirpAmplitude()) + , m_downRate(set->getChirpDownSampleRate()) + , m_chirpBufferDurationUs(set->getChirpBufferDurationUs()) + , m_chirpRepetition(1) + , m_file(0) + , m_analysisFile(0) + , m_availableAudioInputDevices( + QAudioDeviceInfo::availableDevices(QAudio::AudioInput)) + , m_audioInputDevice(QAudioDeviceInfo::defaultInputDevice()) + , m_audioInput(0) + , m_audioInputIODevice(0) + , m_recordPosition(0) + , m_availableAudioOutputDevices( + QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) + , m_audioOutputDevice(QAudioDeviceInfo::defaultOutputDevice()) + , m_audioOutput(0) + , m_playPosition(0) + , m_bufferPosition(0) + , m_bufferLength(0) + , m_dataLength(0) + , m_levelBufferLength(0) + , m_rmsLevel(0.0) + , m_peakLevel(0.0) + , m_spectrumBufferLength(0) + , m_spectrumAnalyser() + , m_spectrumPosition(0) + , m_count(0) + , setDialog(new SettingsDialog( + availableAudioInputDevices(), + availableAudioOutputDevices(), + this)) + , m_sampleRate(set->getSampleRate()) + , m_audioFileBuffer(0) +{ + qRegisterMetaType("FrequencySpectrum"); + qRegisterMetaType("WindowFunction"); + + setupConnections(); + initializePCMS16LE(); + + AUDIO_ENGINE_DEBUG << "defaultOutputDevice options:"; + AUDIO_ENGINE_DEBUG << " defaultOutputDevice: " << m_audioOutputDevice.defaultOutputDevice; + AUDIO_ENGINE_DEBUG << " preferredFormat: " << m_audioOutputDevice.preferredFormat(); + AUDIO_ENGINE_DEBUG << " supportedByteOrders: " << m_audioOutputDevice.supportedByteOrders(); + AUDIO_ENGINE_DEBUG << " supportedChannelCounts: " << m_audioOutputDevice.supportedChannelCounts(); + AUDIO_ENGINE_DEBUG << " supportedChannelCounts :" << m_audioOutputDevice.supportedChannelCounts(); + AUDIO_ENGINE_DEBUG << " supportedCodecs: " << m_audioOutputDevice.supportedCodecs(); + AUDIO_ENGINE_DEBUG << " supportedSampleRates: " << m_audioOutputDevice.supportedSampleRates(); + AUDIO_ENGINE_DEBUG << " supportedSampleSizes: " << m_audioOutputDevice.supportedSampleSizes(); + AUDIO_ENGINE_DEBUG << " supportedSampleTypes: " << m_audioOutputDevice.supportedSampleTypes(); + + +#ifdef DUMP_DATA + createOutputDir(); +#endif + +#ifdef DUMP_SPECTRUM + m_spectrumAnalyser.setOutputPath(outputPath()); +#endif +} + +AudioEngine::~AudioEngine() { +} + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + +bool AudioEngine::loadFile(const QString &fileName) { + + reset(); + bool result = false; + Q_ASSERT(!m_generateTone); + Q_ASSERT(!m_file); + Q_ASSERT(!fileName.isEmpty()); + m_file = new WavFile(this); + + if (m_file->open(fileName)) { + + QString formatStr = formatToString(m_file->fileFormat()); + AUDIO_ENGINE_DEBUG << "file audio format" << formatStr; + + + if (isPCMS16LE(m_file->fileFormat())) { + + result = initializePCMS16LE(); + + m_audioFileBuffer = new AudiofileBuffer(); + m_audioFileBuffer = AudiofileBuffer::loadWav(m_file->fileName()); + + qint16 channels = m_audioFileBuffer->getNofChannels(); + + AUDIO_ENGINE_DEBUG << " data length:" << m_audioFileBuffer->getDataLength(); + AUDIO_ENGINE_DEBUG << " bytes per sample:" << m_audioFileBuffer->getBytesPerSample(); + AUDIO_ENGINE_DEBUG << " bits per sample:" << m_audioFileBuffer->getBitsPerSample(); + AUDIO_ENGINE_DEBUG << " samples per second:" << m_audioFileBuffer->getSamplesPerSec(); + AUDIO_ENGINE_DEBUG << " no of channels:" << channels; + + const qint16 *ptr = reinterpret_cast(m_audioFileBuffer->getRawData()); + const int numSamples = m_audioFileBuffer->getDataLength() / (m_audioFileBuffer->getBytesPerSample() * channels); + //const int numSamples = m_audioFileBuffer->getDataLength() / m_audioFileBuffer->getBytesPerSample(); + AUDIO_ENGINE_DEBUG << " no of samples:" << numSamples; + //float realSample; + QList audioBuffer; + + for (int i = 0; i < numSamples; i++) { + + for (int j = 0; j < m_audioFileBuffer->getNofChannels(); j++) { + + //realSample = pcmToReal(*ptr); + //AUDIO_ENGINE_DEBUG << i << "\t" << *ptr << "\t" << realSample; + audioBuffer << pcmToReal(*ptr); + ptr++;// += m_audioFileBuffer->getNofChannels(); + } + + //realSample = pcmToReal(*ptr); + ////AUDIO_ENGINE_DEBUG << i << "\t" << *ptr << "\t" << realSample; + //audioBuffer << pcmToReal(*ptr); + //ptr++;// += m_audioFileBuffer->getNofChannels(); + } + + /*int lng = audioBuffer.length(); + for (int i = 0; i < lng/6; i++) + qDebug() << audioBuffer.at(i) << "\t" << audioBuffer.at(i+1) << "\t" << audioBuffer.at(i+2) << "\t" + << audioBuffer.at(i+3) << "\t" << audioBuffer.at(i+4) << "\t" << audioBuffer.at(i+5);*/ + + emit audiofileBufferChanged(audioBuffer); + } + else if (isPCMS32LE(m_file->fileFormat())) { + + result = initializePCMS32LE(); + } + else { + + m_message = "[audio engine]: audio format %1 not supported."; + emit messageEvent(m_message.arg(formatToString(m_file->fileFormat()))); + } + } + else { + + m_message = "[audio engine]: could not open %1."; + emit messageEvent(m_message.arg(fileName)); + } + + if (result) { + + m_analysisFile = new WavFile(this); + m_analysisFile->open(fileName); + } + + return result; +} + +bool AudioEngine::generateTone(const Tone &tone) { + + reset(); + Q_ASSERT(!m_generateTone); + Q_ASSERT(!m_file); + m_generateTone = true; + m_tone = tone; + AUDIO_ENGINE_DEBUG << "generateTone" + << "startFreq" << m_tone.startFreq + << "endFreq" << m_tone.endFreq + << "amp" << m_tone.amplitude; + + return initializePCMS16LE(); +} + +bool AudioEngine::generateSweptTone() { + + Q_ASSERT(!m_generateTone); + Q_ASSERT(!m_file); + m_generateTone = true; + m_tone.startFreq = m_lowerChirpFreq; + m_tone.endFreq = m_upperChirpFreq; + m_tone.amplitude = m_chirpAmplitude; + m_tone.duration = m_chirpBufferDurationUs; + AUDIO_ENGINE_DEBUG << "generateSweptTone" + << "startFreq" << m_tone.startFreq + << "endFreq" << m_tone.endFreq + << "amp" << m_tone.amplitude + << "duration" << m_tone.duration; + + m_message = "[audio engine]: set chirp signal to: low = %1 Hz, high = %2 Hz, amplitude = %3, duration = %4 s"; + emit messageEvent(m_message.arg(m_lowerChirpFreq).arg(m_upperChirpFreq).arg(m_chirpAmplitude).arg(m_chirpBufferDurationUs/1E6)); + + return initializePCMS16LE(); +} + +void AudioEngine::generateAudioChirpSignal(const SweptTone &tone, const QAudioFormat &format, QByteArray &buffer) { + + Q_ASSERT(isPCMS16LE(format)); + + const int channelBytes = format.sampleSize() / 8; + const int sampleBytes = format.channelCount() * channelBytes; + int length = buffer.size(); + const int numSamples = buffer.size() / sampleBytes; + + Q_ASSERT(length % sampleBytes == 0); + Q_UNUSED(sampleBytes) // suppress warning in release builds + + unsigned char *ptr = reinterpret_cast(buffer.data()); + + qreal phase = 0.0; + + const qreal d = TWOPI / format.sampleRate(); + + // We can't generate a zero-frequency sine wave + const qreal startFreq = tone.startFreq ? tone.startFreq : 1.0; + + // Amount by which phase increases on each sample + qreal dw = d * startFreq; + + // Amount by which phaseStep increases on each sample + // If this is non-zero, the output is a frequency-swept tone + qreal incFreq = m_chirpRepetition * d * (tone.endFreq - startFreq) / numSamples;//(numSamples - 4800); + + while (length) { + + const qreal x = tone.amplitude * qSin(phase); + const qint16 value = realToPcm(x); + for (int i = 0; i < format.channelCount(); ++i) { + + qToLittleEndian(value, ptr); + ptr += channelBytes; + length -= channelBytes; + } + + phase += dw; + if (m_chirpRepetition > 1 && (length % (buffer.size() / m_chirpRepetition) == 0)) { + + dw = d * startFreq; + //incFreq = 0; + } + + dw += incFreq; + } +} + +bool AudioEngine::initializeRecord() { + + reset(); + AUDIO_ENGINE_DEBUG << "initializeRecord"; + Q_ASSERT(!m_generateTone); + Q_ASSERT(!m_file); + m_generateTone = false; + m_tone = SweptTone(); + return initializePCMS16LE(); +} + +qint64 AudioEngine::bufferLength() const { + + return m_file ? m_file->size() : m_bufferLength; +} + +void AudioEngine::setWindowFunction(WindowFunction type) { + + m_spectrumAnalyser.setWindowFunction(type); +} + +void AudioEngine::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; +} + +//----------------------------------------------------------------------------- +// Public slots +//----------------------------------------------------------------------------- + +void AudioEngine::startRecording() { + + if (m_audioInput) { + + if (QAudio::AudioInput == m_mode && + QAudio::SuspendedState == m_state) { + + m_audioInput->resume(); + } + else { + + m_spectrumAnalyser.cancelCalculation(); + spectrumChanged(0, 0, FrequencySpectrum()); + + m_buffer.fill(0); + setRecordPosition(0, true); + stopPlayback(); + m_mode = QAudio::AudioInput; + + CHECKED_CONNECT( + m_audioInput, + SIGNAL(stateChanged(QAudio::State)), + this, + SLOT(audioStateChanged(QAudio::State))); + + CHECKED_CONNECT( + m_audioInput, + SIGNAL(notify()), + this, + SLOT(audioNotify())); + + m_count = 0; + m_dataLength = 0; + emit dataLengthChanged(0); + m_audioInputIODevice = m_audioInput->start(); + + CHECKED_CONNECT( + m_audioInputIODevice, + SIGNAL(readyRead()), + this, + SLOT(audioDataReady())); + } + } +} + +void AudioEngine::startPlayback() { + + if (m_audioOutput) { + + if (QAudio::AudioOutput == m_mode && QAudio::SuspendedState == m_state) { + +#ifdef Q_OS_WIN + // The Windows backend seems to internally go back into ActiveState + // while still returning SuspendedState, so to ensure that it doesn't + // ignore the resume() call, we first re-suspend + m_audioOutput->suspend(); +#endif + m_audioOutput->resume(); + } + else { + + m_spectrumAnalyser.cancelCalculation(); + spectrumChanged(0, 0, FrequencySpectrum()); + setPlayPosition(0, true); + stopRecording(); + m_mode = QAudio::AudioOutput; + + CHECKED_CONNECT( + m_audioOutput, + SIGNAL(stateChanged(QAudio::State)), + this, + SLOT(audioStateChanged(QAudio::State))); + + CHECKED_CONNECT( + m_audioOutput, + SIGNAL(notify()), + this, + SLOT(audioNotify())); + + m_count = 0; + + if (m_file) { + + m_file->seek(0); + m_bufferPosition = 0; + m_dataLength = 0; + m_audioOutput->start(m_file); + } + else { + + m_audioOutputIODevice.close(); + m_audioOutputIODevice.setBuffer(&m_buffer); + m_audioOutputIODevice.open(QIODevice::ReadOnly); + + m_audioOutput->start(&m_audioOutputIODevice); + } + } + } +} + +void AudioEngine::suspend() { + + if (QAudio::ActiveState == m_state || QAudio::IdleState == m_state) { + + switch (m_mode) { + + case QAudio::AudioInput: + + m_audioInput->suspend(); + break; + + case QAudio::AudioOutput: + + m_audioOutput->suspend(); + break; + } + } +} + +void AudioEngine::setAudioInputDevice(const QAudioDeviceInfo &device) { + + if (device.deviceName() != m_audioInputDevice.deviceName()) { + + m_audioInputDevice = device; + initializePCMS16LE(); + } +} + +void AudioEngine::setAudioOutputDevice(const QAudioDeviceInfo &device) { + + if (device.deviceName() != m_audioOutputDevice.deviceName()) { + + m_audioOutputDevice = device; + AUDIO_ENGINE_DEBUG << "setAudioOutputDevice to:" + << m_audioOutputDevice.deviceName(); + + AUDIO_ENGINE_DEBUG << " options:"; + AUDIO_ENGINE_DEBUG << " defaultOutputDevice" << m_audioOutputDevice.defaultOutputDevice; + AUDIO_ENGINE_DEBUG << " preferredFormat" << m_audioOutputDevice.preferredFormat(); + AUDIO_ENGINE_DEBUG << " supportedByteOrders" << m_audioOutputDevice.supportedByteOrders(); + AUDIO_ENGINE_DEBUG << " supportedChannelCounts" << m_audioOutputDevice.supportedChannelCounts(); + AUDIO_ENGINE_DEBUG << " supportedChannelCounts" << m_audioOutputDevice.supportedChannelCounts(); + AUDIO_ENGINE_DEBUG << " supportedCodecs" << m_audioOutputDevice.supportedCodecs(); + AUDIO_ENGINE_DEBUG << " supportedSampleRates" << m_audioOutputDevice.supportedSampleRates(); + AUDIO_ENGINE_DEBUG << " supportedSampleSizes" << m_audioOutputDevice.supportedSampleSizes(); + AUDIO_ENGINE_DEBUG << " supportedSampleTypes" << m_audioOutputDevice.supportedSampleTypes(); + + initializePCMS16LE(); + } +} + +void AudioEngine::showSettingsDialog() { + + setDialog->exec(); + if (setDialog->result() == QDialog::Accepted) { + + setAudioInputDevice(setDialog->inputDevice()); + setAudioOutputDevice(setDialog->outputDevice()); + //setWindowFunction(setDialog->windowFunction()); + } +} + +void AudioEngine::setChirpSignalMode(QObject* sender) { + + Q_UNUSED(sender) + + reset(); + generateSweptTone(); + +} + +void AudioEngine::setChirpLowerFrequency(QObject *sender, int lo) { + + Q_UNUSED(sender) + + m_lowerChirpFreq = lo; + reset(); + generateSweptTone(); +} + +void AudioEngine::setChirpUpperFrequency(QObject *sender, int hi) { + + Q_UNUSED(sender) + + m_upperChirpFreq = hi; + reset(); + generateSweptTone(); +} + +void AudioEngine::setChirpAmplitude(QObject *sender, qreal amp) { + + Q_UNUSED(sender) + + m_chirpAmplitude = amp; + reset(); + generateSweptTone(); +} + +void AudioEngine::setChirpBufferDurationUs(QObject *sender, qint64 value) { + + Q_UNUSED(sender) + + m_chirpBufferDurationUs = value; + reset(); + generateSweptTone(); +} + +void AudioEngine::setChirpRepetitionTimes(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_chirpRepetition = value; + reset(); + generateSweptTone(); +} + + +//----------------------------------------------------------------------------- +// Private slots +//----------------------------------------------------------------------------- + +void AudioEngine::audioNotify() { + + switch (m_mode) { + + case QAudio::AudioInput: { + + const qint64 recordPosition = qMin(m_bufferLength, audioLength(m_format, m_audioInput->processedUSecs())); + setRecordPosition(recordPosition); + const qint64 levelPosition = m_dataLength - m_levelBufferLength; + + if (levelPosition >= 0) + calculateLevel(levelPosition, m_levelBufferLength); + + if (m_dataLength >= m_spectrumBufferLength) { + const qint64 spectrumPosition = m_dataLength - m_spectrumBufferLength; + calculateSpectrum(spectrumPosition); + } + emit bufferChanged(this, 0, m_dataLength, m_buffer); + } + break; + + case QAudio::AudioOutput: { + + const qint64 playPosition = audioLength(m_format, m_audioOutput->processedUSecs()); + setPlayPosition(qMin(bufferLength(), playPosition)); + const qint64 levelPosition = playPosition - m_levelBufferLength; + const qint64 spectrumPosition = playPosition - m_spectrumBufferLength; + + if (m_file) { + + if (levelPosition > m_bufferPosition || + spectrumPosition > m_bufferPosition || + qMax(m_levelBufferLength, m_spectrumBufferLength) > m_dataLength) + { + m_bufferPosition = 0; + m_dataLength = 0; + // Data needs to be read into m_buffer in order to be analysed + const qint64 readPos = qMax(qint64(0), qMin(levelPosition, spectrumPosition)); + const qint64 readEnd = qMin(m_analysisFile->size(), qMax(levelPosition + m_levelBufferLength, spectrumPosition + m_spectrumBufferLength)); + const qint64 readLen = readEnd - readPos + audioLength(m_format, WaveformWindowDuration); + AUDIO_ENGINE_DEBUG << "audioNotify [1]" + << "analysisFileSize" << m_analysisFile->size() + << "readPos" << readPos + << "readLen" << readLen; + if (m_analysisFile->seek(readPos + m_analysisFile->headerLength())) { + m_buffer.resize(readLen); + m_bufferPosition = readPos; + m_dataLength = m_analysisFile->read(m_buffer.data(), readLen); + AUDIO_ENGINE_DEBUG << "audioNotify [2]" << "bufferPosition" << m_bufferPosition << "dataLength" << m_dataLength; + } + else { + + AUDIO_ENGINE_DEBUG << "audioNotify [2]" << "file seek error"; + } + emit bufferChanged(this, m_bufferPosition, m_dataLength, m_buffer); + } + } + else { + + if (playPosition >= m_dataLength) stopPlayback(); + } + + if (levelPosition >= 0 && levelPosition + m_levelBufferLength < m_bufferPosition + m_dataLength) + calculateLevel(levelPosition, m_levelBufferLength); + //if (spectrumPosition >= 0 && spectrumPosition + m_spectrumBufferLength < m_bufferPosition + m_dataLength) + // calculateSpectrum(spectrumPosition); + //calculateTotalSpectrum(); + } + break; + } +} + +void AudioEngine::audioStateChanged(QAudio::State state) { + + AUDIO_ENGINE_DEBUG << "audio state changed from" << m_state + << "to" << state; + + if (QAudio::IdleState == state && m_file && m_file->pos() == m_file->size()) { + + stopPlayback(); + } + else { + + if (QAudio::StoppedState == state) { + // Check error + QAudio::Error error = QAudio::NoError; + + switch (m_mode) { + + case QAudio::AudioInput: + + error = m_audioInput->error(); + break; + + case QAudio::AudioOutput: + error = m_audioOutput->error(); + break; + } + + if (QAudio::NoError != error) { + + reset(); + return; + } + } + setAudioState(state); + } +} + +void AudioEngine::audioDataReady() { + + Q_ASSERT(0 == m_bufferPosition); + + const qint64 bytesReady = m_audioInput->bytesReady(); + const qint64 bytesSpace = m_buffer.size() - m_dataLength; + const qint64 bytesToRead = qMin(bytesReady, bytesSpace); + + const qint64 bytesRead = m_audioInputIODevice->read(m_buffer.data() + m_dataLength, bytesToRead); + + if (bytesRead) { + + m_dataLength += bytesRead; + emit dataLengthChanged(dataLength()); + } + + if (m_buffer.size() == m_dataLength) + stopRecording(); +} + +void AudioEngine::spectrumChanged(const FrequencySpectrum &spectrum) { + + AUDIO_ENGINE_DEBUG << "spectrumChanged" << "pos" << m_spectrumPosition; + //emit spectrumChanged(m_spectrumPosition, m_spectrumBufferLength, spectrum); + set->setChirpSpectrum(m_spectrumPosition, m_spectrumBufferLength, spectrum); +} + +void AudioEngine::spectrumListChanged(const QList &spectrumList) { + + AUDIO_ENGINE_DEBUG << "spectrumListChanged"; + + set->setChirpSpectrumList(spectrumList); +} + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +void AudioEngine::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(chirpSignalModeChanged(QObject *)), + this, + SLOT(setChirpSignalMode(QObject *))); + + CHECKED_CONNECT( + &m_spectrumAnalyser, + SIGNAL(spectrumChanged(FrequencySpectrum)), + this, + SLOT(spectrumChanged(FrequencySpectrum))); + + CHECKED_CONNECT( + &m_spectrumAnalyser, + SIGNAL(spectrumListChanged(const QList)), + this, + SLOT(spectrumListChanged(const QList))); + + CHECKED_CONNECT( + set, + SIGNAL(lowerChirpFreqChanged(QObject *, int)), + this, + SLOT(setChirpLowerFrequency(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(upperChirpFreqChanged(QObject *, int)), + this, + SLOT(setChirpUpperFrequency(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(chirpAmplitudeChanged(QObject *, qreal)), + this, + SLOT(setChirpAmplitude(QObject *, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(chirpBufferDurationUsChanged(QObject *, qint64)), + this, + SLOT(setChirpBufferDurationUs(QObject *, qint64))); + + CHECKED_CONNECT( + set, + SIGNAL(chirpRepetitionTimesChanged(QObject *, int)), + this, + SLOT(setChirpRepetitionTimes(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); +} + +void AudioEngine::resetAudioDevices() { + + delete m_audioInput; + m_audioInput = 0; + m_audioInputIODevice = 0; + setRecordPosition(0); + delete m_audioOutput; + m_audioOutput = 0; + setPlayPosition(0); + m_spectrumPosition = 0; + setLevel(0.0, 0.0, 0); +} + +void AudioEngine::reset() { + + stopRecording(); + stopPlayback(); + setAudioState(QAudio::AudioInput, QAudio::StoppedState); + setFormat(QAudioFormat()); + m_generateTone = false; + delete m_file; + m_file = 0; + delete m_analysisFile; + m_analysisFile = 0; + m_buffer.clear(); + m_bufferPosition = 0; + m_bufferLength = 0; + m_spectrumBuffer.clear(); + m_spectrumBufferLength = 0; + m_dataLength = 0; + emit dataLengthChanged(0); + resetAudioDevices(); +} + +bool AudioEngine::initializePCMS16LE() { + + bool result = false; + + QAudioFormat format = m_format; + + if (selectFormat()) { + + if (m_format != format) { + + resetAudioDevices(); + if (m_file) { + + AUDIO_ENGINE_DEBUG << "m_file bufferLength: " << bufferLength(); + AUDIO_ENGINE_DEBUG << "m_file dataLength: " << dataLength(); + emit bufferLengthChanged(bufferLength()); + emit dataLengthChanged(dataLength()); + emit bufferChanged(this, 0, 0, m_buffer); + setRecordPosition(bufferLength()); + + result = true; + } + else if (m_serverMode == QSDR::ChirpWSPR) { + + m_bufferLength = audioLength(m_format, m_chirpRepetition * m_chirpBufferDurationUs); + m_buffer.resize(m_bufferLength); + m_buffer.fill(0); + emit bufferLengthChanged(bufferLength()); + + if (m_generateTone) { + + if (0 == m_tone.endFreq) { + + const qreal nyquist = nyquistFrequency(m_format); + m_tone.endFreq = qMin(qreal(SpectrumHighFreq), nyquist); + } + + generateAudioChirpSignal(m_tone, m_format, m_buffer); + + m_dataLength = m_bufferLength; + emit chirpSignalChanged(); + emit dataLengthChanged(dataLength()); + emit bufferChanged(this, 0, m_dataLength, m_buffer); + setRecordPosition(m_bufferLength); + result = true; + + calculateTotalSpectrum(); + } + else { + + emit bufferChanged(this, 0, 0, m_buffer); + m_audioInput = new QAudioInput(m_audioInputDevice, m_format, this); + m_audioInput->setNotifyInterval(NotifyIntervalMs); + result = true; + } + } + else if (m_serverMode == QSDR::SDRMode) { + } + + m_audioOutput = new QAudioOutput(m_audioOutputDevice, m_format, this); + m_audioOutput->setNotifyInterval(NotifyIntervalMs); + } + } + else { + + if (m_file) { + + m_message = "[audio engine]: audio format not supported, %1 ."; + emit messageEvent(m_message.arg(formatToString(m_format))); + } + else if (m_generateTone) + emit messageEvent("[audio engine]: no suitable format found."); + else + emit messageEvent("[audio engine]: no common input / output format found."); + } + + AUDIO_ENGINE_DEBUG << "initialize" << "m_bufferLength: " << m_bufferLength; + AUDIO_ENGINE_DEBUG << "initialize" << "m_dataLength: " << m_dataLength; + AUDIO_ENGINE_DEBUG << "initialize" << "format: " << m_format; + + //m_message = "[audio engine]: file format = %1."; + //emit messageEvent(m_message.arg(formatToString(m_format))); + + return result; +} + +bool AudioEngine::initializePCMS32LE() { + + bool result = false; + + QAudioFormat format = m_format; + + if (selectFormat()) { + if (m_format != format) { + + resetAudioDevices(); + + if (m_file) { + + emit bufferLengthChanged(bufferLength()); + emit dataLengthChanged(dataLength()); + emit bufferChanged(this, 0, 0, m_buffer); + setRecordPosition(bufferLength()); + + result = true; + } + } + } + else { + if (m_file) { + m_message = "[audio engine]: audio format not supported, %1 ."; + emit messageEvent(m_message.arg(formatToString(m_format))); + } + } + + AUDIO_ENGINE_DEBUG << "initialize" << "m_bufferLength" << m_bufferLength; + AUDIO_ENGINE_DEBUG << "initialize" << "m_dataLength" << m_dataLength; + AUDIO_ENGINE_DEBUG << "initialize" << "format" << m_format; + m_message = "[audio engine]: file format = %1."; + emit messageEvent(m_message.arg(formatToString(m_format))); + + return result; +} + +bool AudioEngine::selectFormat() { + + bool foundSupportedFormat = false; + + if (m_file || QAudioFormat() != m_format) { + + QAudioFormat format = m_format; + if (m_file) + // Header is read from the WAV file; just need to check whether + // it is supported by the audio output device + format = m_file->fileFormat(); + if (m_audioOutputDevice.isFormatSupported(format)) { + + setFormat(format); + foundSupportedFormat = true; + } + else { + + QAudioFormat nearestFormat = m_audioOutputDevice.nearestFormat(format); + + QString formatStr = formatToString(nearestFormat); + AUDIO_ENGINE_DEBUG << "audio format not supported!"; + AUDIO_ENGINE_DEBUG << "nearest file audio format" << formatStr; + } + } + else if ((m_serverMode == QSDR::ChirpWSPR)|| QAudioFormat() != m_format) { + + QList frequenciesList; + + if (!m_generateTone) + frequenciesList += m_audioInputDevice.supportedSampleRates(); + + frequenciesList += m_audioOutputDevice.supportedSampleRates(); + frequenciesList = frequenciesList.toSet().toList(); // remove duplicates + qSort(frequenciesList); + AUDIO_ENGINE_DEBUG << "initialize frequenciesList: " << frequenciesList; + + QList channelsList; + channelsList += m_audioInputDevice.supportedChannelCounts(); + channelsList += m_audioOutputDevice.supportedChannelCounts(); + channelsList = channelsList.toSet().toList(); + qSort(channelsList); + AUDIO_ENGINE_DEBUG << "initialize channelsList: " << channelsList; + + QAudioFormat format; + format.setByteOrder(QAudioFormat::LittleEndian); + format.setCodec("audio/pcm"); + format.setSampleSize(16); + format.setSampleType(QAudioFormat::SignedInt); + + format.setSampleRate(set->getChirpSamplingFreq()); + format.setChannelCount(set->getChirpChannels()); + const bool inputSupport = m_generateTone || m_audioInputDevice.isFormatSupported(format); + const bool outputSupport = m_audioOutputDevice.isFormatSupported(format); + + AUDIO_ENGINE_DEBUG << "initialize checking: " + << " input: " << inputSupport << "; " + << " output: " << outputSupport; + + AUDIO_ENGINE_DEBUG << "checking audio length:"; + AUDIO_ENGINE_DEBUG << " format.sampleRate() = " << format.sampleRate(); + AUDIO_ENGINE_DEBUG << " format.channelCount() = " << format.channelCount(); + AUDIO_ENGINE_DEBUG << " format.sampleSize() = " << format.sampleSize(); + + if (inputSupport && outputSupport) { + + setFormat(format); + foundSupportedFormat = true; + } + + return foundSupportedFormat; + + /*int frequency, channels; + foreach (frequency, frequenciesList) { + if (foundSupportedFormat) + break; + format.setSampleRate(frequency); + foreach (channels, channelsList) { + format.setChannelCount(channels); + const bool inputSupport = m_generateTone || + m_audioInputDevice.isFormatSupported(format); + const bool outputSupport = m_audioOutputDevice.isFormatSupported(format); + AUDIO_ENGINE_DEBUG << "initialize checking " << format + << "input" << inputSupport + << "output" << outputSupport; + if (inputSupport && outputSupport) { + foundSupportedFormat = true; + break; + } + } + } + + if (!foundSupportedFormat) + format = QAudioFormat(); + + setFormat(format);*/ + } + else if ((m_serverMode == QSDR::SDRMode)|| QAudioFormat() != m_format) { + + QList frequenciesList; + + if (!m_generateTone) + frequenciesList += m_audioInputDevice.supportedSampleRates(); + + frequenciesList += m_audioOutputDevice.supportedSampleRates(); + frequenciesList = frequenciesList.toSet().toList(); // remove duplicates + qSort(frequenciesList); + AUDIO_ENGINE_DEBUG << "initialize frequenciesList: " << frequenciesList; + + QList channelsList; + channelsList += m_audioInputDevice.supportedChannelCounts(); + channelsList += m_audioOutputDevice.supportedChannelCounts(); + channelsList = channelsList.toSet().toList(); + qSort(channelsList); + AUDIO_ENGINE_DEBUG << "initialize channelsList: " << channelsList; + + QAudioFormat format; + format.setByteOrder(QAudioFormat::LittleEndian); + format.setCodec("audio/pcm"); + format.setSampleSize(16); + format.setSampleType(QAudioFormat::SignedInt); + + format.setSampleRate(48000); + format.setChannelCount(2); + const bool inputSupport = m_generateTone || m_audioInputDevice.isFormatSupported(format); + const bool outputSupport = m_audioOutputDevice.isFormatSupported(format); + + AUDIO_ENGINE_DEBUG << "initialize checking: " + << " input: " << inputSupport << "; " + << " output: " << outputSupport; + + AUDIO_ENGINE_DEBUG << "checking audio length:"; + AUDIO_ENGINE_DEBUG << " format.sampleRate() = " << format.sampleRate(); + AUDIO_ENGINE_DEBUG << " format.channelCount() = " << format.channelCount(); + AUDIO_ENGINE_DEBUG << " format.sampleSize() = " << format.sampleSize(); + + if (inputSupport && outputSupport) { + + setFormat(format); + foundSupportedFormat = true; + } + + return foundSupportedFormat; + } +} + +void AudioEngine::stopRecording() { + + if (m_audioInput) { + m_audioInput->stop(); + QCoreApplication::instance()->processEvents(); + m_audioInput->disconnect(); + } + m_audioInputIODevice = 0; + +#ifdef DUMP_AUDIO + dumpData(); +#endif +} + +void AudioEngine::stopPlayback() { + + if (m_audioOutput) { + m_audioOutput->stop(); + QCoreApplication::instance()->processEvents(); + m_audioOutput->disconnect(); + setPlayPosition(0); + } +} + +void AudioEngine::setAudioState(QAudio::State state) { + + const bool changed = (m_state != state); + m_state = state; + if (changed) + emit stateChanged(m_mode, m_state); +} + +void AudioEngine::setAudioState(QAudio::Mode mode, QAudio::State state) { + + const bool changed = (m_mode != mode || m_state != state); + m_mode = mode; + m_state = state; + if (changed) + emit stateChanged(m_mode, m_state); +} + +void AudioEngine::setSystemState( + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (err) + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; +} + +void AudioEngine::setRecordPosition(qint64 position, bool forceEmit) { + + const bool changed = (m_recordPosition != position); + m_recordPosition = position; + if (changed || forceEmit) + emit recordPositionChanged(m_recordPosition); +} + +void AudioEngine::setPlayPosition(qint64 position, bool forceEmit) { + + const bool changed = (m_playPosition != position); + m_playPosition = position; + if (changed || forceEmit) + emit playPositionChanged(this, m_playPosition); +} + +void AudioEngine::calculateLevel(qint64 position, qint64 length) { + +#ifdef DISABLE_LEVEL + Q_UNUSED(position) + Q_UNUSED(length) +#else + Q_ASSERT(position + length <= m_bufferPosition + m_dataLength); + + qreal peakLevel = 0.0; + + qreal sum = 0.0; + const char *ptr = m_buffer.constData() + position - m_bufferPosition; + const char *const end = ptr + length; + while (ptr < end) { + const qint16 value = *reinterpret_cast(ptr); + const qreal fracValue = pcmToReal(value); + peakLevel = qMax(peakLevel, fracValue); + sum += fracValue * fracValue; + ptr += 2; + } + const int numSamples = length / 2; + qreal rmsLevel = sqrt(sum / numSamples); + + rmsLevel = qMax(qreal(0.0), rmsLevel); + rmsLevel = qMin(qreal(1.0), rmsLevel); + setLevel(rmsLevel, peakLevel, numSamples); + + AUDIO_ENGINE_DEBUG << "calculateLevel" << "pos" << position << "len" << length + << "rms" << rmsLevel << "peak" << peakLevel; +#endif +} + +void AudioEngine::calculateSpectrum(qint64 position) { + +#ifdef DISABLE_SPECTRUM + Q_UNUSED(position) +#else + Q_ASSERT(position + m_spectrumBufferLength <= m_bufferPosition + m_dataLength); + Q_ASSERT(0 == m_spectrumBufferLength % 2); // constraint of FFT algorithm + + // QThread::currentThread is marked 'for internal use only', but + // we're only using it for debug output here, so it's probably OK :) + AUDIO_ENGINE_DEBUG << "calculateSpectrum" << QThread::currentThread() + << "count" << m_count << "pos" << position << "len" << m_spectrumBufferLength + << "spectrumAnalyser.isReady" << m_spectrumAnalyser.isReady(); + + if(m_spectrumAnalyser.isReady()) { + //m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position - m_bufferPosition, + // m_spectrumBufferLength); + m_spectrumPosition = position; + //m_spectrumAnalyser.calculate(m_spectrumBuffer, m_format); + } + +#endif +} + +void AudioEngine::calculateTotalSpectrum() { + + // QThread::currentThread is marked 'for internal use only', but + // we're only using it for debug output here, so it's probably OK :) + AUDIO_ENGINE_DEBUG << "calculateTotalSpectrum" << QThread::currentThread() + //<< "count" << m_count << "pos" << position << "len" << m_spectrumBufferLength + << "spectrumAnalyser.isReady" << m_spectrumAnalyser.isReady(); + + if(m_spectrumAnalyser.isReady()) { + + //m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData() + position - m_bufferPosition, m_spectrumBufferLength); + m_spectrumBuffer = QByteArray::fromRawData(m_buffer.constData(), m_bufferLength); + + m_spectrumAnalyser.calculateTotal(0, m_dataLength, m_format, m_spectrumBuffer); + } +} + +void AudioEngine::setFormat(const QAudioFormat &format) { + + const bool changed = (format != m_format); + m_format = format; + m_levelBufferLength = audioLength(m_format, LevelWindowUs); + m_spectrumBufferLength = SpectrumLengthSamples * (m_format.sampleSize() / 8) * m_format.channelCount(); + if (changed) + emit formatChanged(this, m_format); +} + +void AudioEngine::setLevel(qreal rmsLevel, qreal peakLevel, int numSamples) { + + m_rmsLevel = rmsLevel; + m_peakLevel = peakLevel; + emit levelChanged(m_rmsLevel, m_peakLevel, numSamples); +} + +#ifdef DUMP_DATA +void AudioEngine::createOutputDir() +{ + m_outputDir.setPath("output"); + + // Ensure output directory exists and is empty + if (m_outputDir.exists()) { + const QStringList files = m_outputDir.entryList(QDir::Files); + QString file; + foreach (file, files) + m_outputDir.remove(file); + } else { + QDir::current().mkdir("output"); + } +} +#endif // DUMP_DATA + +#ifdef DUMP_AUDIO +void AudioEngine::dumpData() +{ + const QString txtFileName = m_outputDir.filePath("data.txt"); + QFile txtFile(txtFileName); + txtFile.open(QFile::WriteOnly | QFile::Text); + QTextStream stream(&txtFile); + const qint16 *ptr = reinterpret_cast(m_buffer.constData()); + const int numSamples = m_dataLength / (2 * m_format.channelCount()); + for (int i=0; i0) { + + m_data = new char[ m_dataLength ]; + } + else + m_data = 0; +}; + +AudiofileBuffer *AudiofileBuffer::loadWav(QString fileName) { + + QFile *wavFile = new QFile(fileName); + + if (wavFile->open(QIODevice::ReadOnly)) { + + SWavHeader header; + + wavFile->read(header.chunkID, 4); + if (header.chunkID[0]!='R' || header.chunkID[1]!='I' || + header.chunkID[2]!='F' || header.chunkID[3]!='F') + return 0; // incorrect header + + wavFile->read((char*)&header.chunkSize, 4); + wavFile->read((char*)&header.format, 4); + + if (header.format[0]!='W' || header.format[1]!='A' || + header.format[2]!='V' || header.format[3]!='E') + return 0; // incorrect header + + wavFile->read((char*)&header.subchunk1id, 4); + if (header.subchunk1id[0]!='f' || header.subchunk1id[1]!='m' || + header.subchunk1id[2]!='t' || header.subchunk1id[3]!=' ') + return 0; // incorrect header + + wavFile->read((char*)&header.subchunk1size, 4); + wavFile->read((char*)&header.audioFormat, 2); + wavFile->read((char*)&header.nofChannels, 2); + wavFile->read((char*)&header.sampleRate, 4); + wavFile->read((char*)&header.byteRate, 4); + wavFile->read((char*)&header.blockAlign, 2); + wavFile->read((char*)&header.bitsPerSample, 2); + + AUDIO_ENGINE_DEBUG << fileName << " opened."; + + while (1) { + + if (wavFile->read((char*)&header.subchunk2id, 4) != 4) return 0; + if (wavFile->read((char*)&header.subchunk2size, 4) != 4) return 0; + + //int deb_size = header.subchunk2size; + //char tes[4]; + //memcpy(tes, header.subchunk2id, 4 ); + //if (header.subchunk2id[0]!='d' || header.subchunk2id[1]!='a' || header.subchunk2id[2]!='t' || header.subchunk2id[3]!='a') return 0; // incorrect header + + if (header.subchunk2id[0]=='d' && header.subchunk2id[1]=='a' && + header.subchunk2id[2]=='t' && header.subchunk2id[3]=='a') + break; // found the data, chunk + + // this was not the data-chunk. skip it + if (header.subchunk2size < 1) return 0; // error in file + char *unused = new char[header.subchunk2size]; + wavFile->read(unused, header.subchunk2size ); + delete [] unused; + } + + // the data follows. + if (header.subchunk2size < 1) return 0; + + AudiofileBuffer *rval = new AudiofileBuffer; + rval->m_nofChannels = header.nofChannels; + rval->m_bitsPerSample = header.bitsPerSample; + rval->m_samplesPerSec = header.sampleRate; + rval->m_signedData = 0; // where to know this? + rval->reallocate(header.subchunk2size); + + wavFile->read((char*)rval->m_data, header.subchunk2size); + + // choose a good sampling function. + rval->m_sampleFunction = 0; + if (rval->m_nofChannels == 1) { + + if (rval->m_bitsPerSample == 8) + rval->m_sampleFunction = sampleFunction8bitMono; + if (rval->m_bitsPerSample == 16) + rval->m_sampleFunction = sampleFunction16bitMono; + + } + else { + + if (rval->m_bitsPerSample == 8) + rval->m_sampleFunction = sampleFunction8bitStereo; + if (rval->m_bitsPerSample == 16) + rval->m_sampleFunction = sampleFunction16bitStereo; + } + + return rval; + + } + else { + + AUDIO_ENGINE_DEBUG << fileName << " NOT opened"; + return 0; + } + + delete wavFile; + }; + +AUDIO_SAMPLE_TYPE AudiofileBuffer::sampleFunction8bitMono(AudiofileBuffer *abuffer, int pos, int channel) { + + Q_UNUSED(channel) + return (AUDIO_SAMPLE_TYPE)(((unsigned char*)(abuffer->m_data))[pos]-128) << 8; +}; + +AUDIO_SAMPLE_TYPE AudiofileBuffer::sampleFunction16bitMono(AudiofileBuffer *abuffer, int pos, int channel) { + + Q_UNUSED(channel) + return (AUDIO_SAMPLE_TYPE)(((short*)(abuffer->m_data))[pos]); +}; + +AUDIO_SAMPLE_TYPE AudiofileBuffer::sampleFunction8bitStereo(AudiofileBuffer *abuffer, int pos, int channel) { + + return ((AUDIO_SAMPLE_TYPE)(((char*)(abuffer->m_data))[pos*abuffer->m_nofChannels + channel]) << 8); +}; + +AUDIO_SAMPLE_TYPE AudiofileBuffer::sampleFunction16bitStereo(AudiofileBuffer *abuffer, int pos, int channel) { + + return (AUDIO_SAMPLE_TYPE)(((short*)(abuffer->m_data))[pos*abuffer->m_nofChannels + channel]); +}; diff --git a/Source/src/AudioEngine/cusdr_audio_engine.h b/Source/src/AudioEngine/cusdr_audio_engine.h new file mode 100644 index 0000000..972a53b --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_engine.h @@ -0,0 +1,442 @@ +/** +* @file cusdr_audio_engine.h +* @brief cuSDR audio engine header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _CUSDR_AUDIOENGINE_H +#define _CUSDR_AUDIOENGINE_H + +#include "cusdr_audio_spectrum.h" +#include "cusdr_audio_spectrumanalyser.h" +#include "cusdr_audio_wavfile.h" +#include "cusdr_audio_settingsdialog.h" + +//#include +//#include +//#include +//#include +//#include + +#ifdef LOG_AUDIO_ENGINE +# define AUDIO_ENGINE_DEBUG qDebug().nospace() << "AudioEngine::\t" +#else +# define AUDIO_ENGINE_DEBUG nullDebug() +#endif + + +#ifdef DUMP_CAPTURED_AUDIO +#define DUMP_DATA +#endif + +#ifdef DUMP_SPECTRUM +#define DUMP_DATA +#endif + +#ifdef DUMP_DATA +#include +#endif + +#define AUDIO_SAMPLE_TYPE short + +//class SettingsDialog; +class FrequencySpectrum; + +QT_FORWARD_DECLARE_CLASS(QAudioInput) +QT_FORWARD_DECLARE_CLASS(QAudioOutput) +QT_FORWARD_DECLARE_CLASS(QFile) + + +class AudiofileBuffer; + +typedef AUDIO_SAMPLE_TYPE(*SAMPLE_FUNCTION_TYPE)(AudiofileBuffer *abuffer, int pos, int channel); + + +/** + * This class interfaces with the QtMultimedia audio classes. Its role is + * to manage the capture and playback of audio data. + */ + +class AudioEngine : public QWidget { + Q_OBJECT + +public: + //AudioEngine(QObject *parent = 0); + AudioEngine(QWidget *parent = 0); + ~AudioEngine(); + + const QList& availableAudioInputDevices() const + { return m_availableAudioInputDevices; } + + const QList& availableAudioOutputDevices() const + { return m_availableAudioOutputDevices; } + + QAudio::Mode mode() const { return m_mode; } + QAudio::State state() const { return m_state; } + + /** + * \return Current audio format + * \note May be QAudioFormat() if engine is not initialized + */ + const QAudioFormat& format() const { return m_format; } + + /** + * Stop any ongoing recording or playback, and reset to ground state. + */ + void reset(); + + /** + * Load data from WAV file + */ + bool loadFile(const QString &fileName); + + /** + * Generate tone + */ + bool generateTone(const Tone &tone); + + /** + * Generate tone + */ + //bool generateSweptTone(qreal amplitude); + bool generateSweptTone(); + + /** + * Generate local chirp signal + */ + bool generateLocalChirp(); + + /** + * Initialize for recording + */ + bool initializeRecord(); + + /** + * Position of the audio input device. + * \return Position in bytes. + */ + qint64 recordPosition() const { return m_recordPosition; } + + /** + * RMS level of the most recently processed set of audio samples. + * \return Level in range (0.0, 1.0) + */ + qreal rmsLevel() const { return m_rmsLevel; } + + /** + * Peak level of the most recently processed set of audio samples. + * \return Level in range (0.0, 1.0) + */ + qreal peakLevel() const { return m_peakLevel; } + + /** + * Position of the audio output device. + * \return Position in bytes. + */ + qint64 playPosition() const { return m_playPosition; } + + /** + * Length of the internal engine buffer. + * \return Buffer length in bytes. + */ + qint64 bufferLength() const; + + /** + * Amount of data held in the buffer. + * \return Data length in bytes. + */ + qint64 dataLength() const { return m_dataLength; } + + /** + * Set window function applied to audio data before spectral analysis. + */ + void setWindowFunction(WindowFunction type); + +public slots: + void startRecording(); + void startPlayback(); + void showSettingsDialog(); + void suspend(); + void setAudioInputDevice(const QAudioDeviceInfo &device); + void setAudioOutputDevice(const QAudioDeviceInfo &device); + + void setSystemState( + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + /** + * set Chirp tone parameters + */ + void setChirpSignalMode(QObject *); + //void generateChirpSignal(const SweptTone &tone); + void generateAudioChirpSignal(const SweptTone &tone, const QAudioFormat &format, QByteArray &buffer); + void setChirpLowerFrequency(QObject *sender, int lo); + void setChirpUpperFrequency(QObject *sender, int lo); + void setChirpAmplitude(QObject *sender, qreal amp); + void setChirpBufferDurationUs(QObject *sender, qint64 value); + void setChirpRepetitionTimes(QObject *sender, int value); + void sampleRateChanged(QObject *sender, int value); + +signals: + void stateChanged(QAudio::Mode mode, QAudio::State state); + + /** + * Informational message for non-modal display + */ + void messageEvent(QString msg); + void infoMessage(const QString &message, int durationMs); + + /** + * Error message for modal display + */ + void errorMessage(const QString &heading, const QString &detail); + + /** + * Format of audio data has changed + */ + void formatChanged(QObject *sender, const QAudioFormat &format); + + /** + * Length of buffer has changed. + * \param duration Duration in microseconds + */ + void bufferLengthChanged(qint64 duration); + + /** + * Amount of data in buffer has changed. + * \param Length of data in bytes + */ + void dataLengthChanged(qint64 duration); + + /** + * Position of the audio input device has changed. + * \param position Position in bytes + */ + void recordPositionChanged(qint64 position); + + /** + * Position of the audio output device has changed. + * \param position Position in bytes + */ + void playPositionChanged(QObject *sender, qint64 position); + + /** + * Level changed + * \param rmsLevel RMS level in range 0.0 - 1.0 + * \param peakLevel Peak level in range 0.0 - 1.0 + * \param numSamples Number of audio samples analyzed + */ + void levelChanged(qreal rmsLevel, qreal peakLevel, int numSamples); + + /** + * Spectrum has changed. + * \param position Position of start of window in bytes + * \param length Length of window in bytes + * \param spectrum Resulting frequency spectrum + */ + void spectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + + /** + * Buffer containing audio data has changed. + * \param position Position of start of buffer in bytes + * \param buffer Buffer + */ + void bufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + //void chirpBufferChanged(qint64 length, const QList &buffer); + + void chirpSignalChanged(); + void audiofileBufferChanged(const QList &buffer); + +private slots: + void audioNotify(); + void audioStateChanged(QAudio::State state); + void audioDataReady(); + void spectrumChanged(const FrequencySpectrum &spectrum); + void spectrumListChanged(const QList &spectrumList); + +private: + void setupConnections(); + void resetAudioDevices(); + bool initializePCMS16LE(); + bool initializePCMS32LE(); + bool selectFormat(); + void stopRecording(); + void stopPlayback(); + void setAudioState(QAudio::State state); + void setAudioState(QAudio::Mode mode, QAudio::State state); + void setFormat(const QAudioFormat &format); + void setRecordPosition(qint64 position, bool forceEmit = false); + void setPlayPosition(qint64 position, bool forceEmit = false); + void calculateLevel(qint64 position, qint64 length); + void calculateSpectrum(qint64 position); + void calculateTotalSpectrum(); + void setLevel(qreal rmsLevel, qreal peakLevel, int numSamples); + +#ifdef DUMP_DATA + void createOutputDir(); + QString outputPath() const { return m_outputDir.path(); } +#endif + +#ifdef DUMP_CAPTURED_AUDIO + void dumpData(); +#endif + +private: + Settings *set; + + QAudio::Mode m_mode; + QAudio::State m_state; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QString m_message; + + bool m_generateTone; + bool m_generateLocalChirp; + SweptTone m_tone; + int m_lowerChirpFreq; + int m_upperChirpFreq; + qreal m_chirpAmplitude; + int m_chirpSamplingFreq; + int m_downRate; + qint64 m_chirpBufferDurationUs; + int m_chirpChannels; + int m_chirpRepetition; + + WavFile *m_file; + // We need a second file handle via which to read data into m_buffer + // for analysis + WavFile *m_analysisFile; + + QAudioFormat m_format; + + const QList m_availableAudioInputDevices; + QAudioDeviceInfo m_audioInputDevice; + QAudioInput* m_audioInput; + QIODevice* m_audioInputIODevice; + qint64 m_recordPosition; + + const QList m_availableAudioOutputDevices; + QAudioDeviceInfo m_audioOutputDevice; + QAudioOutput* m_audioOutput; + qint64 m_playPosition; + QBuffer m_audioOutputIODevice; + + QByteArray m_buffer; + qint64 m_bufferPosition; + qint64 m_bufferLength; + qint64 m_dataLength; + + int m_levelBufferLength; + qreal m_rmsLevel; + qreal m_peakLevel; + + int m_spectrumBufferLength; + QByteArray m_spectrumBuffer; + SpectrumAnalyser m_spectrumAnalyser; + qint64 m_spectrumPosition; + + int m_count; + + SettingsDialog* setDialog; + + int m_sampleRate; + + AudiofileBuffer *m_audioFileBuffer; + +#ifdef DUMP_DATA + QDir m_outputDir; +#endif + +}; + + +// ********************************************************************* +// AudiofileBuffer Class + +class AudiofileBuffer { + +public: + AudiofileBuffer(); + virtual ~AudiofileBuffer(); + + static AudiofileBuffer *loadWav(QString fileName); + //static AudiofileBuffer *loadWav( FILE *wavFile ); // support for stdio + + void reallocate( int length ); + + inline void *getRawData() { return m_data; } + inline int getDataLength() { return m_dataLength; } + + inline int getBytesPerSample() { return (m_bitsPerSample >> 3); } + inline int getBitsPerSample() { return m_bitsPerSample; } + inline int getSamplesPerSec() { return m_samplesPerSec; } + inline short getNofChannels() { return m_nofChannels; } + + inline SAMPLE_FUNCTION_TYPE getSampleFunction() { return m_sampleFunction; } + + // static implementations of sample functions + static AUDIO_SAMPLE_TYPE sampleFunction8bitMono(AudiofileBuffer *abuffer, int pos, int channel); + static AUDIO_SAMPLE_TYPE sampleFunction16bitMono(AudiofileBuffer *abuffer, int pos, int channel); + static AUDIO_SAMPLE_TYPE sampleFunction8bitStereo(AudiofileBuffer *abuffer, int pos, int channel); + static AUDIO_SAMPLE_TYPE sampleFunction16bitStereo(AudiofileBuffer *abuffer, int pos, int channel); + +protected: + SAMPLE_FUNCTION_TYPE m_sampleFunction; + + short m_nofChannels; + void *m_data; + int m_dataLength; // in bytes + short m_bitsPerSample; + bool m_signedData; + int m_samplesPerSec; +}; + +#endif // _CUSDR_AUDIOENGINE_H diff --git a/Source/src/AudioEngine/cusdr_audio_settingsdialog.cpp b/Source/src/AudioEngine/cusdr_audio_settingsdialog.cpp new file mode 100644 index 0000000..33d36b2 --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_settingsdialog.cpp @@ -0,0 +1,226 @@ +/** +* @file cusdr_audio_settingsdialog.cpp +* @brief cuSDR audio settings dialogue class +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "cusdr_audio_settingsdialog.h" +#include "Util/cusdr_buttons.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + +#define btn_height 18 +#define btn_width 74 + +SettingsDialog::SettingsDialog( + const QList &availableInputDevices, + const QList &availableOutputDevices, + QWidget *parent) + : QDialog(parent) + , set(Settings::instance()) + , m_inputDeviceComboBox(new QComboBox(this)) + , m_outputDeviceComboBox(new QComboBox(this)) + //, m_windowFunction(DefaultWindowFunction) + //, m_windowFunctionComboBox(new QComboBox(this)) +{ + if (parent) + setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); + else + setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + + setWindowModality(Qt::NonModal); + setWindowOpacity(0.9); + setStyleSheet(set->getDialogStyle()); + + setMouseTracking(true); + + m_titleFont.setStyleStrategy(QFont::PreferAntialias); + m_titleFont.setFixedPitch(true); + #ifdef Q_OS_MAC + m_titleFont.setPixelSize(10); + m_titleFont.setFamily("Arial"); + //m_titleFont.setBold(true); + #endif + #ifdef Q_OS_WIN + m_titleFont.setPixelSize(13); + m_titleFont.setFamily("Arial"); + m_titleFont.setBold(true); + //m_titleFont.setItalic(true); + #endif + + QVBoxLayout *dialogLayout = new QVBoxLayout(this); + + // Populate combo boxes + + QAudioDeviceInfo device; + foreach (device, availableInputDevices) + m_inputDeviceComboBox->addItem(device.deviceName(), + qVariantFromValue(device)); + foreach (device, availableOutputDevices) + m_outputDeviceComboBox->addItem(device.deviceName(), + qVariantFromValue(device)); + + //m_windowFunctionComboBox->addItem(tr("None"), qVariantFromValue(int(NoWindow))); + //m_windowFunctionComboBox->addItem("Hann", qVariantFromValue(int(HannWindow))); + //m_windowFunctionComboBox->setCurrentIndex(m_windowFunction); + + m_inputDeviceComboBox->setStyleSheet(set->getComboBoxStyle()); + m_inputDeviceComboBox->setMinimumContentsLength(30); + m_outputDeviceComboBox->setStyleSheet(set->getComboBoxStyle()); + m_outputDeviceComboBox->setMinimumContentsLength(30); + + // Initialize default devices + if (!availableInputDevices.empty()) + m_inputDevice = availableInputDevices.front(); + if (!availableOutputDevices.empty()) + m_outputDevice = availableOutputDevices.front(); + + // Add widgets to layout + + QScopedPointer titleLayout(new QHBoxLayout); + QLabel *titleLabel = new QLabel(tr("Audio Settings:"), this); + titleLabel->setFont(m_titleFont); + titleLabel->setStyleSheet(set->getLabelStyle()); + titleLayout->addWidget(titleLabel); + dialogLayout->addLayout(titleLayout.data()); + titleLayout.take(); // ownership transferred to dialogLayout + + QScopedPointer inputDeviceLayout(new QHBoxLayout); + QLabel *inputDeviceLabel = new QLabel(tr("Input device"), this); + inputDeviceLabel->setStyleSheet(set->getLabelStyle()); + inputDeviceLayout->addWidget(inputDeviceLabel); + inputDeviceLayout->addWidget(m_inputDeviceComboBox); + dialogLayout->addLayout(inputDeviceLayout.data()); + inputDeviceLayout.take(); // ownership transferred to dialogLayout + + QScopedPointer outputDeviceLayout(new QHBoxLayout); + QLabel *outputDeviceLabel = new QLabel(tr("Output device"), this); + outputDeviceLabel->setStyleSheet(set->getLabelStyle()); + outputDeviceLayout->addWidget(outputDeviceLabel); + outputDeviceLayout->addWidget(m_outputDeviceComboBox); + dialogLayout->addLayout(outputDeviceLayout.data()); + outputDeviceLayout.take(); // ownership transferred to dialogLayout + + //QScopedPointer windowFunctionLayout(new QHBoxLayout); + //QLabel *windowFunctionLabel = new QLabel(tr("Window function"), this); + //windowFunctionLayout->addWidget(windowFunctionLabel); + //windowFunctionLayout->addWidget(m_windowFunctionComboBox); + //dialogLayout->addLayout(windowFunctionLayout.data()); + //windowFunctionLayout.take(); // ownership transferred to dialogLayout + + // Connect + CHECKED_CONNECT( + m_inputDeviceComboBox, + SIGNAL(activated(int)), + this, + SLOT(inputDeviceChanged(int))); + + CHECKED_CONNECT( + m_outputDeviceComboBox, + SIGNAL(activated(int)), + this, + SLOT(outputDeviceChanged(int))); + + /*CHECKED_CONNECT( + m_windowFunctionComboBox, + SIGNAL(activated(int)), + this, + SLOT(windowFunctionChanged(int)));*/ + + AeroButton* okBtn = new AeroButton("Ok", this); + okBtn->setRoundness(10); + okBtn->setFixedSize(btn_width, btn_height); + CHECKED_CONNECT( + okBtn, + SIGNAL(clicked()), + this, + SLOT(accept())); + + AeroButton* cancelBtn = new AeroButton("Cancel", this); + cancelBtn->setRoundness(10); + cancelBtn->setFixedSize(btn_width, btn_height); + CHECKED_CONNECT( + cancelBtn, + SIGNAL(clicked()), + this, + SLOT(reject())); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setSpacing(1); + hbox->addWidget(okBtn); + hbox->addWidget(cancelBtn); + + dialogLayout->addLayout(hbox); + + setLayout(dialogLayout); +} + +SettingsDialog::~SettingsDialog() { +} + +//void SettingsDialog::windowFunctionChanged(int index) +//{ +// m_windowFunction = static_cast( +// m_windowFunctionComboBox->itemData(index).value()); +//} + +void SettingsDialog::inputDeviceChanged(int index) { + + m_inputDevice = m_inputDeviceComboBox->itemData(index).value(); +} + +void SettingsDialog::outputDeviceChanged(int index) { + + m_outputDevice = m_outputDeviceComboBox->itemData(index).value(); +} + diff --git a/Source/src/AudioEngine/cusdr_audio_settingsdialog.h b/Source/src/AudioEngine/cusdr_audio_settingsdialog.h new file mode 100644 index 0000000..6b5142f --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_settingsdialog.h @@ -0,0 +1,100 @@ +/** +* @file cusdr_audio_settingsdialog.h +* @brief cuSDR audio settings dialogue header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SETTINGSDIALOG_H +#define SETTINGSDIALOG_H + +//#include "spectrum.h" +#include +#include + +#include "cusdr_settings.h" + +QT_FORWARD_DECLARE_CLASS(QComboBox) +QT_FORWARD_DECLARE_CLASS(QCheckBox) +QT_FORWARD_DECLARE_CLASS(QSlider) +QT_FORWARD_DECLARE_CLASS(QSpinBox) +QT_FORWARD_DECLARE_CLASS(QGridLayout) + +/** + * Dialog used to control settings such as the audio input / output device + * and the windowing function. + */ +class SettingsDialog : public QDialog { + Q_OBJECT +public: + SettingsDialog(const QList &availableInputDevices, + const QList &availableOutputDevices, + QWidget *parent = 0); + ~SettingsDialog(); + + //WindowFunction windowFunction() const { return m_windowFunction; } + const QAudioDeviceInfo& inputDevice() const { return m_inputDevice; } + const QAudioDeviceInfo& outputDevice() const { return m_outputDevice; } + +private slots: + //void windowFunctionChanged(int index); + void inputDeviceChanged(int index); + void outputDeviceChanged(int index); + +private: + Settings* set; + + QFont m_titleFont; + //WindowFunction m_windowFunction; + QAudioDeviceInfo m_inputDevice; + QAudioDeviceInfo m_outputDevice; + + QComboBox* m_inputDeviceComboBox; + QComboBox* m_outputDeviceComboBox; + + //QComboBox* m_windowFunctionComboBox; + +}; + +#endif // SETTINGSDIALOG_H diff --git a/Source/src/AudioEngine/cusdr_audio_spectrum.h b/Source/src/AudioEngine/cusdr_audio_spectrum.h new file mode 100644 index 0000000..ae831e8 --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_spectrum.h @@ -0,0 +1,142 @@ +/** +* @file cusdr_audio_spectrum.h +* @brief cuSDR audio engine spectrum header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _CUSDR_AUDIO_SPECTRUM_H +#define _CUSDR_AUDIO_SPECTRUM_H + +#include +#include "cusdr_audio_utils.h" +//#include "fftreal_wrapper.h" // For FFTLengthPowerOfTwo + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +// Number of audio samples used to calculate the frequency spectrum +//const int SpectrumLengthSamples = PowerOfTwo::Result; +const int SpectrumLengthSamples = 2048;//4096;//1024;//256;//512;// + +// Number of bands in the frequency spectrum +const int SpectrumNumBands = 10; + +// Lower bound of first band in the spectrum +const qreal SpectrumLowFreq = 0.0; // Hz + +// Upper band of last band in the spectrum +const qreal SpectrumHighFreq = 1000.0; // Hz + +// Waveform window size in microseconds +const qint64 WaveformWindowDuration = 500 * 1000; + +// Length of waveform tiles in bytes +// Ideally, these would match the QAudio*::bufferSize(), but that isn't +// available until some time after QAudio*::start() has been called, and we +// need this value in order to initialize the waveform display. +// We therefore just choose a sensible value. +const int WaveformTileLength = 4096; + +// Fudge factor used to calculate the spectrum bar heights +const qreal SpectrumAnalyserMultiplier = 0.15; + +// Disable message timeout +const int NullMessageTimeout = -1; + + +//----------------------------------------------------------------------------- +// Types and data structures +//----------------------------------------------------------------------------- + +enum WindowFunction { + NoWindow, + HannWindow, + BlackmanHarrisWindow +}; + +const WindowFunction DefaultWindowFunction = HannWindow;//NoWindow;//BlackmanHarrisWindow;// + +struct Tone { + Tone(qreal freq = 0.0, qreal amp = 0.0, qint64 dur = 0) + : frequency(freq), amplitude(amp), duration(dur) + { } + + // Start and end frequencies for swept tone generation + qreal frequency; + + // Amplitude in range [0.0, 1.0] + qreal amplitude; + + // tone duration in micro seconds + qint64 duration; +}; + +struct SweptTone { + SweptTone(qreal start = 0.0, qreal end = 0.0, qreal amp = 0.0, qint64 dur = 0) + : startFreq(start), endFreq(end), amplitude(amp), duration(dur) + { Q_ASSERT(end >= start); } + + SweptTone(const Tone &tone) + : startFreq(tone.frequency), endFreq(tone.frequency), amplitude(tone.amplitude), duration(tone.duration) + { } + + // Start and end frequencies for swept tone generation + qreal startFreq; + qreal endFreq; + + // Amplitude in range [0.0, 1.0] + qreal amplitude; + + // tone duration in micro seconds + qint64 duration; +}; + +#ifdef DISABLE_WAVEFORM +#undef SUPERIMPOSE_PROGRESS_ON_WAVEFORM +#endif + +#endif // _CUSDR_AUDIO_SPECTRUM_H + diff --git a/Source/src/AudioEngine/cusdr_audio_spectrumanalyser.cpp b/Source/src/AudioEngine/cusdr_audio_spectrumanalyser.cpp new file mode 100644 index 0000000..a5df29b --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_spectrumanalyser.cpp @@ -0,0 +1,422 @@ +/** +* @file cusdr_audio_spectrumanalyser.cpp +* @brief cuSDR audio engine spectrumanalyser class +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//#define LOG_SPECTRUMANALYSER +//#define DUMP_SPECTRUMANALYSER + +#include "cusdr_audio_spectrumanalyser.h" +#include "cusdr_audio_utils.h" +#include "cusdr_settings.h" + +#include +#include +#include + + + +SpectrumAnalyserThread::SpectrumAnalyserThread(QObject *parent) + : QObject(parent) + , set(Settings::instance()) + , m_numSamples(SpectrumLengthSamples) + , m_windowFunction(DefaultWindowFunction) + , m_window(SpectrumLengthSamples, 0.0) + , m_input(SpectrumLengthSamples, 0.0) + , m_output(SpectrumLengthSamples, 0.0) + , m_spectrum(SpectrumLengthSamples) +#ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD + , m_thread(new QThread(this)) +#endif +{ +#ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD + // moveToThread() cannot be called on a QObject with a parent + setParent(0); + moveToThread(m_thread); + m_thread->start(); +#endif + + //m_cpxInput = mallocCPX(SpectrumLengthSamples); + m_cpxInput.resize(SpectrumLengthSamples); + //m_cpxOutput = mallocCPX(SpectrumLengthSamples); + m_cpxOutput.resize(SpectrumLengthSamples); + + m_fft = new QFFT(SpectrumLengthSamples); + + //memset(m_cpxInput, 0, SpectrumLengthSamples * sizeof(CPX)); + //memset(m_cpxOutput, 0, SpectrumLengthSamples * sizeof(CPX)); + + calculateWindow(); +} + +SpectrumAnalyserThread::~SpectrumAnalyserThread() { + + delete m_fft; +} + +void SpectrumAnalyserThread::setWindowFunction(WindowFunction type) { + + m_windowFunction = type; + calculateWindow(); +} + +void SpectrumAnalyserThread::calculateWindow() { + + for (int i = 0; i < m_numSamples; ++i) { + + DataType x = 0.0; + + switch (m_windowFunction) { + + case NoWindow: + x = 1.0; + break; + + case HannWindow: + x = 0.5 * (1 - qCos((TWOPI * i) / (m_numSamples - 1))); + break; + + case BlackmanHarrisWindow: { + float + a0 = 0.35875F, + a1 = 0.48829F, + a2 = 0.14128F, + a3 = 0.01168F; + + + x = a0 - a1* cos(TWOPI * (i + 0.5) / m_numSamples) + + a2* cos(2.0 * TWOPI * (i + 0.5) / m_numSamples) + - a3* cos(3.0 * TWOPI * (i + 0.5) / m_numSamples); + } + break; + + default: + Q_ASSERT(false); + } + + m_window[i] = x; + } +} + +void SpectrumAnalyserThread::calculateTotalSpectrum(const QByteArray &buffer, int inputFrequency, int bytesPerSample) { + + if (m_spectrumList.count() > 0) + m_spectrumList.clear(); + + int samples = bytesPerSample * m_numSamples; + int buffers = qRound((float) buffer.size() / samples); + + // cycle over all buffers + for (int i = 0; i < buffers; i++) { + + //if (i == buffers-1 && overhead > 0) + m_tmp = QByteArray::fromRawData(buffer.constData() + i * samples, samples); + + //Q_ASSERT(m_tmp.size() == m_numSamples * bytesPerSample); + + // Initialize data array + const char *ptr = m_tmp.constData(); + + for (int j = 0; j < m_numSamples; ++j) { + + const qint16 pcmSample = *reinterpret_cast(ptr); + // Scale down to range [-1.0, 1.0] + const DataType realSample = pcmToReal(pcmSample); + const DataType windowedSample = realSample * m_window[j]; + + m_cpxInput[j].re = windowedSample; + m_cpxInput[j].im = 0.0f; + + ptr += bytesPerSample; + } + + // calculate the FFT + m_fft->DoFFTWForward(m_cpxInput, m_cpxOutput, SpectrumLengthSamples); + + /*for (int i = 0; i < BUFFER_SIZE; i += 32) { + qDebug() << "m_cpxOutput.re =" << m_cpxOutput[i].re << "m_cpxOutput.im =" << m_cpxOutput[i].im; + }*/ + + // Analyze output to obtain amplitude and phase for each frequency + for (int i = 2; i <= m_numSamples / 2; ++i) { + + // Calculate frequency of this complex sample + m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); + + //const qreal real = m_output[i]; + const qreal real = m_cpxOutput[i].re; + qreal imag = 0.0; + + if (i > 0 && i < m_numSamples / 2) + imag = m_cpxOutput[m_numSamples/2 + i].re; + + const qreal magnitude = sqrt(real*real + imag*imag); + qreal amplitude = SpectrumAnalyserMultiplier * log(magnitude); + + // Bound amplitude to [0.0, 1.0] + m_spectrum[i].clipped = (amplitude > 1.0); + amplitude = qMax(qreal(0.0), amplitude); + amplitude = qMin(qreal(1.0), amplitude); + m_spectrum[i].amplitude = amplitude; + } + m_spectrumList.append(m_spectrum); + } + emit calculationTotalComplete(m_spectrumList); +} + +void SpectrumAnalyserThread::calculateSpectrum(const QByteArray &buffer, int inputFrequency, int bytesPerSample) { + + Q_ASSERT(buffer.size() == m_numSamples * bytesPerSample); + + // Initialize data array + const char *ptr = buffer.constData(); + for (int i = 0; i < m_numSamples; ++i) { + + const qint16 pcmSample = *reinterpret_cast(ptr); + // Scale down to range [-1.0, 1.0] + const DataType realSample = pcmToReal(pcmSample); + const DataType windowedSample = realSample * m_window[i]; + m_input[i] = windowedSample; + m_cpxInput[i].re = windowedSample; + m_cpxInput[i].im = 0.0f; + ptr += bytesPerSample; + } + + // Calculate the FFT + m_fft->DoFFTWForward(m_cpxInput, m_cpxOutput, SpectrumLengthSamples); + + // Analyze output to obtain amplitude and phase for each frequency + for (int i = 2; i <= m_numSamples / 2; ++i) { + // Calculate frequency of this complex sample + m_spectrum[i].frequency = qreal(i * inputFrequency) / (m_numSamples); + + //const qreal real = m_output[i]; + const qreal real = m_cpxOutput[i].re; + qreal imag = 0.0; + if (i > 0 && i < m_numSamples / 2) + //imag = m_output[m_numSamples/2 + i]; + imag = m_cpxOutput[m_numSamples/2 + i].re; + + const qreal magnitude = sqrt(real*real + imag*imag); + qreal amplitude = SpectrumAnalyserMultiplier * log(magnitude); + + // Bound amplitude to [0.0, 1.0] + m_spectrum[i].clipped = (amplitude > 1.0); + amplitude = qMax(qreal(0.0), amplitude); + amplitude = qMin(qreal(1.0), amplitude); + m_spectrum[i].amplitude = amplitude; + } + + emit calculationComplete(m_spectrum); +} + + + +//============================================================================= +// SpectrumAnalyser +//============================================================================= + +SpectrumAnalyser::SpectrumAnalyser(QObject *parent) + : QObject(parent) + , m_thread(new SpectrumAnalyserThread(this)) + , m_state(Idle) +#ifdef DUMP_SPECTRUMANALYSER + , m_count(0) +#endif +{ + CHECKED_CONNECT( + m_thread, + SIGNAL(calculationComplete(FrequencySpectrum)), + this, + SLOT(calculationComplete(FrequencySpectrum))); + + CHECKED_CONNECT( + m_thread, + SIGNAL(calculationTotalComplete(QList)), + this, + SLOT(calculationTotalComplete(QList))); +} + +SpectrumAnalyser::~SpectrumAnalyser() { +} + +#ifdef DUMP_SPECTRUMANALYSER +void SpectrumAnalyser::setOutputPath(const QString &outputDir) +{ + m_outputDir.setPath(outputDir); + m_textFile.setFileName(m_outputDir.filePath("spectrum.txt")); + m_textFile.open(QIODevice::WriteOnly | QIODevice::Text); + m_textStream.setDevice(&m_textFile); +} +#endif + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + +void SpectrumAnalyser::setWindowFunction(WindowFunction type) { + + const bool b = QMetaObject::invokeMethod(m_thread, "setWindowFunction", + Qt::AutoConnection, + Q_ARG(WindowFunction, type)); + Q_ASSERT(b); + Q_UNUSED(b) // suppress warnings in release builds +} + +void SpectrumAnalyser::calculateTotal( + qint64 position, + qint64 length, + const QAudioFormat &format, + const QByteArray &buffer +) { + Q_UNUSED(position) + Q_UNUSED(length) + + SPECTRUMANALYSER_DEBUG << "SpectrumAnalyser::calculateTotal" + << QThread::currentThread() + << "state" << m_state; + + SPECTRUMANALYSER_DEBUG << "buffer size =" << buffer.size(); + + if (isReady()) { + Q_ASSERT(isPCMS16LE(format)); + + const int bytesPerSample = format.sampleSize() * format.channelCount() / 8; + + m_state = Busy; + + // Invoke SpectrumAnalyserThread::calculateTotalSpectrum using QMetaObject. + // If m_thread is in a different thread from the current thread, the + // calculation will be done in the child thread. + // Once the calculation is finished, a calculationChanged signal will be + // emitted by m_thread. + const bool b = QMetaObject::invokeMethod(m_thread, "calculateTotalSpectrum", + Qt::AutoConnection, + Q_ARG(QByteArray, buffer), + Q_ARG(int, format.sampleRate()), + Q_ARG(int, bytesPerSample)); + Q_ASSERT(b); + Q_UNUSED(b) // suppress warnings in release builds + } +} + +void SpectrumAnalyser::calculate(const QByteArray &buffer, + const QAudioFormat &format) +{ + // QThread::currentThread is marked 'for internal use only', but + // we're only using it for debug output here, so it's probably OK :) + SPECTRUMANALYSER_DEBUG << "SpectrumAnalyser::calculate" + << QThread::currentThread() + << "state" << m_state; + + SPECTRUMANALYSER_DEBUG << "buffer size =" << buffer.size(); + + if (isReady()) { + Q_ASSERT(isPCMS16LE(format)); + + const int bytesPerSample = format.sampleSize() * format.channelCount() / 8; + + m_state = Busy; + + // Invoke SpectrumAnalyserThread::calculateSpectrum using QMetaObject. If + // m_thread is in a different thread from the current thread, the + // calculation will be done in the child thread. + // Once the calculation is finished, a calculationChanged signal will be + // emitted by m_thread. + const bool b = QMetaObject::invokeMethod(m_thread, "calculateSpectrum", + Qt::AutoConnection, + Q_ARG(QByteArray, buffer), + Q_ARG(int, format.sampleRate()), + Q_ARG(int, bytesPerSample)); + Q_ASSERT(b); + Q_UNUSED(b) // suppress warnings in release builds + +#ifdef DUMP_SPECTRUMANALYSER + m_textStream << "FrequencySpectrum " << m_count << "\n"; + FrequencySpectrum::const_iterator x = m_spectrum.begin(); + for (int i=0; ifrequency << "\t" + << x->amplitude<< "\t" + << x->phase << "\n"; +#endif + } +} + +bool SpectrumAnalyser::isReady() const { + + return (Idle == m_state); +} + +void SpectrumAnalyser::cancelCalculation() { + + if (Busy == m_state) + m_state = Cancelled; +} + + +//----------------------------------------------------------------------------- +// Private slots +//----------------------------------------------------------------------------- + +void SpectrumAnalyser::calculationComplete(const FrequencySpectrum &spectrum) { + + Q_ASSERT(Idle != m_state); + if (Busy == m_state) + emit spectrumChanged(spectrum); + m_state = Idle; +} + +void SpectrumAnalyser::calculationTotalComplete(const QList &m_spectrumList) { + + Q_ASSERT(Idle != m_state); + if (Busy == m_state) + emit spectrumListChanged(m_spectrumList); + m_state = Idle; +} + + + + diff --git a/Source/src/AudioEngine/cusdr_audio_spectrumanalyser.h b/Source/src/AudioEngine/cusdr_audio_spectrumanalyser.h new file mode 100644 index 0000000..bdf600d --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_spectrumanalyser.h @@ -0,0 +1,229 @@ +/** +* @file cusdr_audio_spectrumanalyser.h +* @brief cuSDR audio engine spectrumanalyser header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _CUSDR_AUDIO_SPECTRUMANALYSER_H +#define _CUSDR_AUDIO_SPECTRUMANALYSER_H + +#include +#include +#include + +#ifdef DUMP_SPECTRUMANALYSER +#include +#include +#include +#endif + +//#define SPECTRUM_ANALYSER_SEPARATE_THREAD + +//#include "frequencyspectrum.h" +#include "cusdr_audio_spectrum.h" +#include "cusdr_settings.h" +#include "QtDSP/qtdsp_fft.h" +#include "QtDSP/qtdsp_qComplex.h" +//#include "cusdr_filter.h" + +#ifdef LOG_SPECTRUMANALYSER +# define SPECTRUMANALYSER_DEBUG qDebug().nospace() << "SpectrumAnalyzer::\t" +#else +# define SPECTRUMANALYSER_DEBUG nullDebug() +#endif + + +QT_FORWARD_DECLARE_CLASS(QAudioFormat) +QT_FORWARD_DECLARE_CLASS(QThread) + +//class SpectrumAnalyserThreadPrivate; + +/** + * Implementation of the spectrum analysis which can be run in a + * separate thread. + */ +class SpectrumAnalyserThread : public QObject +{ + Q_OBJECT +public: + SpectrumAnalyserThread(QObject *parent); + ~SpectrumAnalyserThread(); + +public slots: + void setWindowFunction(WindowFunction type); + + void calculateSpectrum( + const QByteArray &buffer, + int inputFrequency, + int bytesPerSample); + + void calculateTotalSpectrum( + const QByteArray &buffer, + int inputFrequency, + int bytesPerSample); + +signals: + void calculationComplete(const FrequencySpectrum &spectrum); + void calculationTotalComplete(const QList &spectrumList); + +private: + void calculateWindow(); + +private: + Settings* set; + int m_numSamples; + + WindowFunction m_windowFunction; + + //typedef qreal DataType; + typedef float DataType; + + QVector m_window; + + QVector m_input; + QVector m_output; + + CPX m_cpxInput; + CPX m_cpxOutput; + + QFFT *m_fft; + + QByteArray m_tmp; + + FrequencySpectrum m_spectrum; + + QList m_spectrumList; + +#ifdef SPECTRUM_ANALYSER_SEPARATE_THREAD + QThread* m_thread; +#endif +}; + +/** + * Class which performs frequency spectrum analysis on a window of + * audio samples, provided to it by the Engine. + */ +class SpectrumAnalyser : public QObject +{ + Q_OBJECT +public: + SpectrumAnalyser(QObject *parent = 0); + ~SpectrumAnalyser(); + +#ifdef DUMP_SPECTRUMANALYSER + void setOutputPath(const QString &outputPath); +#endif + +public: + /* + * Set the windowing function which is applied before calculating the FFT + */ + void setWindowFunction(WindowFunction type); + + /* + * Calculate a frequency spectrum + * + * \param buffer Audio data + * \param format Format of audio data + * + * Frequency spectrum is calculated asynchronously. The result is returned + * via the spectrumChanged signal. + * + * An ongoing calculation can be cancelled by calling cancelCalculation(). + * + */ + void calculate(const QByteArray &buffer, const QAudioFormat &format); + + void calculateTotal( + qint64 position, + qint64 length, + const QAudioFormat &format, + const QByteArray &buffer); + + /* + * Check whether the object is ready to perform another calculation + */ + bool isReady() const; + + /* + * Cancel an ongoing calculation + * + * Note that cancelling is asynchronous. + */ + void cancelCalculation(); + +signals: + void spectrumChanged(const FrequencySpectrum &spectrum); + void spectrumListChanged(const QList &spectrumList); + +private slots: + void calculationComplete(const FrequencySpectrum &spectrum); + void calculationTotalComplete(const QList &m_spectrumList); + +private: + void calculateWindow(); + +private: + + SpectrumAnalyserThread* m_thread; + + enum State { + Idle, + Busy, + Cancelled + }; + + State m_state; + +#ifdef DUMP_SPECTRUMANALYSER + QDir m_outputDir; + int m_count; + QFile m_textFile; + QTextStream m_textStream; +#endif +}; + +#endif // _CUSDR_AUDIO_SPECTRUMANALYSER_H + diff --git a/Source/src/AudioEngine/cusdr_audio_utils.cpp b/Source/src/AudioEngine/cusdr_audio_utils.cpp new file mode 100644 index 0000000..0dde2ae --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_utils.cpp @@ -0,0 +1,155 @@ +/** +* @file cusdr_audio_utils.cpp +* @brief cuSDR audio utils class +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "cusdr_audio_utils.h" + +qint64 audioDuration(const QAudioFormat &format, qint64 bytes) { + + return (bytes * 1000000) / + (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8)); +} + +qint64 audioLength(const QAudioFormat &format, qint64 microSeconds) { + + qint64 result = (format.sampleRate() * format.channelCount() * (format.sampleSize() / 8)) + * microSeconds / 1000000; + result -= result % (format.channelCount() * format.sampleSize()); + return result; +} + +qreal nyquistFrequency(const QAudioFormat &format) { + + return format.sampleRate() / 2; +} + +QString formatToString(const QAudioFormat &format) { + + QString result; + + if (QAudioFormat() != format) { + if (format.codec() == "audio/pcm") { + Q_ASSERT(format.sampleType() == QAudioFormat::SignedInt); + + const QString formatEndian = (format.byteOrder() == QAudioFormat::LittleEndian) + ? QString("LE") : QString("BE"); + + QString formatType; + switch(format.sampleType()) { + case QAudioFormat::SignedInt: + formatType = "signed"; + break; + case QAudioFormat::UnSignedInt: + formatType = "unsigned"; + break; + case QAudioFormat::Float: + formatType = "float"; + break; + case QAudioFormat::Unknown: + formatType = "unknown"; + break; + } + + QString formatChannels = QString("%1 channels").arg(format.channelCount()); + switch (format.channelCount()) { + case 1: + formatChannels = "mono"; + break; + case 2: + formatChannels = "stereo"; + break; + } + + result = QString("%1 Hz %2 bit %3 %4 %5") + .arg(format.sampleRate()) + .arg(format.sampleSize()) + .arg(formatType) + .arg(formatEndian) + .arg(formatChannels); + } else { + result = format.codec(); + } + } + + return result; +} + +bool isPCM(const QAudioFormat &format) { + + return (format.codec() == "audio/pcm"); +} + + +bool isPCMS16LE(const QAudioFormat &format) { + + return (isPCM(format) && + format.sampleType() == QAudioFormat::SignedInt && + format.sampleSize() == 16 && + format.byteOrder() == QAudioFormat::LittleEndian); +} + +bool isPCMS32LE(const QAudioFormat &format) { + + return (isPCM(format) && + format.sampleType() == QAudioFormat::SignedInt && + format.sampleSize() == 32 && + format.byteOrder() == QAudioFormat::LittleEndian); +} + +const qint16 PCMS16MaxValue = 32767; +const quint16 PCMS16MaxAmplitude = 32768; // because minimum is -32768 + +qreal pcmToReal(qint16 pcm) { + + return qreal(pcm) / PCMS16MaxAmplitude; +} + +qint16 realToPcm(qreal real) { + + return real * PCMS16MaxValue; +} diff --git a/Source/src/AudioEngine/cusdr_audio_utils.h b/Source/src/AudioEngine/cusdr_audio_utils.h new file mode 100644 index 0000000..ae1046a --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_utils.h @@ -0,0 +1,96 @@ +/** +* @file cusdr_audio_utils.h +* @brief cuSDR audio utils header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _CUSDR_AUDIO_UTILS_H +#define _CUSDR_AUDIO_UTILS_H + +#include +#include + +#include + +#if defined(Q_OS_WIN32) + QT_FORWARD_DECLARE_CLASS(QAudioFormat) +#endif + +//----------------------------------------------------------------------------- +// Miscellaneous utility functions +//----------------------------------------------------------------------------- + +qint64 audioDuration(const QAudioFormat &format, qint64 bytes); +qint64 audioLength(const QAudioFormat &format, qint64 microSeconds); + +QString formatToString(const QAudioFormat &format); + +qreal nyquistFrequency(const QAudioFormat &format); + +// Scale PCM value to [-1.0, 1.0] +qreal pcmToReal(qint16 pcm); + +// Scale real value in [-1.0, 1.0] to PCM +qint16 realToPcm(qreal real); + +// Check whether the audio format is PCM +bool isPCM(const QAudioFormat &format); + +// Check whether the audio format is signed, little-endian, 16-bit PCM +bool isPCMS16LE(const QAudioFormat &format); + +// Check whether the audio format is float, little-endian, 32-bit PCM +bool isPCMS32LE(const QAudioFormat &format); + +// Compile-time calculation of powers of two + +template class PowerOfTwo +{ public: static const int Result = PowerOfTwo::Result * 2; }; + +template<> class PowerOfTwo<0> +{ public: static const int Result = 1; }; + + +#endif // _CUSDR_AUDIO_UTILS_H diff --git a/Source/src/AudioEngine/cusdr_audio_waveform.cpp b/Source/src/AudioEngine/cusdr_audio_waveform.cpp new file mode 100644 index 0000000..271ca4b --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_waveform.cpp @@ -0,0 +1,484 @@ +/** +* @file cusdr_audio_waveform.cpp +* @brief cuSDR waveform graphics +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//#define LOG_WAVEFORM +//#define LOG_PAINT_EVENT + +#include "cusdr_audio_utils.h" +#include "cusdr_audio_waveform.h" + +#include +#include +#include + + + +Waveform::Waveform(QObject *parent) + : QObject(parent) + , set(Settings::instance()) + , m_bufferPosition(0) + , m_bufferLength(0) + , m_audioPosition(0) + , m_active(false) + , m_tileLength(0) + , m_tileArrayStart(0) + , m_windowPosition(0) + , m_windowLength(0) + , m_waveformDisplayWidth(0) +{ +} + +Waveform::~Waveform() { + + deletePixmaps(); +} + +QImage* Waveform::createWaveformImage(const QRect &rect) { + + if (!rect.isValid()) return NULL; + + QImage *image = new QImage(rect.size(), QImage::Format_ARGB32_Premultiplied); + if (!image) return NULL; + + m_waveformDisplayWidth = image->width(); + + image->fill(QColor(0, 0, 0, 255).rgba()); + + QPainter painter(image); + + if (m_active) { + + WAVEFORM_PAINT_DEBUG << "paintEvent" + << "windowPosition" << m_windowPosition + << "windowLength" << m_windowLength; + qint64 pos = m_windowPosition; + const qint64 windowEnd = m_windowPosition + m_windowLength; + int destLeft = 0; + int destRight = 0; + while (pos < windowEnd) { + + const TilePoint point = tilePoint(pos); + WAVEFORM_PAINT_DEBUG << "paintEvent" << "pos" << pos + << "tileIndex" << point.index + << "positionOffset" << point.positionOffset + << "pixelOffset" << point.pixelOffset; + + if (point.index != NullIndex) { + + const Tile &tile = m_tiles[point.index]; + if (tile.painted) { + + const qint64 sectionLength = qMin((m_tileLength - point.positionOffset), + (windowEnd - pos)); + Q_ASSERT(sectionLength > 0); + + const int sourceRight = tilePixelOffset(point.positionOffset + sectionLength); + //destRight = windowPixelOffset(pos - m_windowPosition + sectionLength); + destRight = windowPixelOffset(pos - m_windowPosition + sectionLength, rect); + + QRect destRect = rect;//(); + destRect.setTop(20); + destRect.setHeight(rect.height() - 20); + destRect.setLeft(destLeft); + destRect.setRight(destRight); + //destRect.setRect(0, 0, destLeft + destRight, rect.height()); + + QRect sourceRect(QPoint(), m_pixmapSize); + sourceRect.setLeft(point.pixelOffset); + sourceRect.setRight(sourceRight); + + WAVEFORM_PAINT_DEBUG << "paintEvent" << "tileIndex" << point.index + << "source" << point.pixelOffset << sourceRight + << "dest" << destLeft << destRight; + + //painter.drawPixmap(destRect, *tile.pixmap, sourceRect); + painter.drawPixmap(destRect, *tile.pixmap, sourceRect); + + destLeft = destRight; + + if (point.index < m_tiles.count()) { + + pos = tilePosition(point.index + 1); + WAVEFORM_PAINT_DEBUG << "paintEvent" << "pos ->" << pos; + } + else { + // Reached end of tile array + WAVEFORM_PAINT_DEBUG << "paintEvent" << "reached end of tile array"; + break; + } + } + else { + // Passed last tile which is painted + WAVEFORM_PAINT_DEBUG << "paintEvent" << "tile" << point.index << "not painted"; + break; + } + } + else { + // pos is past end of tile array + WAVEFORM_PAINT_DEBUG << "paintEvent" << "pos" << pos << "past end of tile array"; + break; + } + } + + WAVEFORM_PAINT_DEBUG << "paintEvent" << "final pos" << pos << "final x" << destRight; + } + painter.end(); + + return image; +} + +void Waveform::initialize(const QAudioFormat &format, qint64 audioBufferSize, qint64 windowDurationUs, const QRect &rect) { + + WAVEFORM_DEBUG << "initialize" + << "audioBufferSize" << audioBufferSize + << "windowDurationUs" << windowDurationUs; + + reset(); + + m_format = format; + m_audioRect = rect; + + // Calculate tile size + m_tileLength = audioBufferSize; + + // Calculate window size + m_windowLength = audioLength(m_format, windowDurationUs); + + // Calculate number of tiles required + int nTiles; + if (m_tileLength > m_windowLength) { + nTiles = 2; + } else { + nTiles = m_windowLength / m_tileLength + 1; + if (m_windowLength % m_tileLength) + ++nTiles; + } + + WAVEFORM_DEBUG << "initialize" + << "tileLength" << m_tileLength + << "windowLength" << m_windowLength + << "nTiles" << nTiles; + + m_pixmaps.fill(0, nTiles); + m_tiles.resize(nTiles); + + createPixmaps(m_audioRect.size()); + + m_active = true; +} + +void Waveform::reset() +{ + WAVEFORM_DEBUG << "reset"; + + m_bufferPosition = 0; + m_buffer = QByteArray(); + m_audioPosition = 0; + m_format = QAudioFormat(); + m_active = false; + deletePixmaps(); + m_tiles.clear(); + m_tileLength = 0; + m_tileArrayStart = 0; + m_windowPosition = 0; + m_windowLength = 0; +} + +void Waveform::bufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer) { + + Q_UNUSED (sender) + + WAVEFORM_DEBUG << "bufferChanged" + << "audioPosition" << m_audioPosition + << "bufferPosition" << position + << "bufferLength" << length; + m_bufferPosition = position; + m_bufferLength = length; + m_buffer = buffer; + paintTiles(); +} + +void Waveform::audioPositionChanged(QObject *sender, qint64 position) +{ + Q_UNUSED (sender) + + WAVEFORM_DEBUG << "audioPositionChanged" + << "audioPosition" << position + << "bufferPosition" << m_bufferPosition + << "bufferLength" << m_bufferLength; + + if (position >= m_bufferPosition) { + if (position + m_windowLength > m_bufferPosition + m_bufferLength) + position = qMax(qint64(0), m_bufferPosition + m_bufferLength - m_windowLength); + m_audioPosition = position; + setWindowPosition(position); + } +} + +void Waveform::deletePixmaps() +{ + QPixmap *pixmap; + foreach (pixmap, m_pixmaps) + delete pixmap; + m_pixmaps.clear(); +} + +void Waveform::createPixmaps(const QSize &rect) { + + m_pixmapSize = rect; + + if (m_windowLength > 0) + m_pixmapSize.setWidth(qreal(rect.width()) * m_tileLength / m_windowLength); + else + m_pixmapSize.setWidth(qreal(rect.width())); + + WAVEFORM_DEBUG << "createPixmaps" + << "rectSize" << rect + << "pixmapSize" << m_pixmapSize; + + Q_ASSERT(m_tiles.count() == m_pixmaps.count()); + + // (Re)create pixmaps + for (int i = 0; i < m_pixmaps.size(); ++i) { + + delete m_pixmaps[i]; + m_pixmaps[i] = 0; + m_pixmaps[i] = new QPixmap(m_pixmapSize); + } + + // Update tile pixmap pointers, and mark for repainting + for (int i = 0; i < m_tiles.count(); ++i) { + + m_tiles[i].pixmap = m_pixmaps[i]; + m_tiles[i].painted = false; + } +} + +void Waveform::setWindowPosition(qint64 position) +{ + WAVEFORM_DEBUG << "setWindowPosition" + << "old" << m_windowPosition << "new" << position + << "tileArrayStart" << m_tileArrayStart; + + const qint64 oldPosition = m_windowPosition; + m_windowPosition = position; + + if((m_windowPosition >= oldPosition) && + (m_windowPosition - m_tileArrayStart < (m_tiles.count() * m_tileLength))) { + // Work out how many tiles need to be shuffled + const qint64 offset = m_windowPosition - m_tileArrayStart; + const int nTiles = offset / m_tileLength; + shuffleTiles(nTiles); + } else { + resetTiles(m_windowPosition); + } + + if(!paintTiles() && m_windowPosition != oldPosition) + emit waveformImageChanged(true); + // update(); +} + +qint64 Waveform::tilePosition(int index) const { + + return m_tileArrayStart + index * m_tileLength; +} + +Waveform::TilePoint Waveform::tilePoint(qint64 position) const { + + TilePoint result; + + if (position >= m_tileArrayStart) { + + const qint64 tileArrayEnd = m_tileArrayStart + m_tiles.count() * m_tileLength; + + if (position < tileArrayEnd) { + + const qint64 offsetIntoTileArray = position - m_tileArrayStart; + result.index = offsetIntoTileArray / m_tileLength; + Q_ASSERT(result.index >= 0 && result.index <= m_tiles.count()); + result.positionOffset = offsetIntoTileArray % m_tileLength; + result.pixelOffset = tilePixelOffset(result.positionOffset); + Q_ASSERT(result.pixelOffset >= 0 && result.pixelOffset <= m_pixmapSize.width()); + } + } + + return result; +} + +int Waveform::tilePixelOffset(qint64 positionOffset) const { + + Q_ASSERT(positionOffset >= 0 && positionOffset <= m_tileLength); + const int result = (qreal(positionOffset) / m_tileLength) * m_pixmapSize.width(); + return result; +} + +int Waveform::windowPixelOffset(qint64 positionOffset, const QRect &rect) const { + + Q_ASSERT(positionOffset >= 0 && positionOffset <= m_windowLength); + + const int result = (qreal(positionOffset) / m_windowLength) * rect.width(); + return result; +} + +bool Waveform::paintTiles() { + + WAVEFORM_DEBUG << "paintTiles"; + bool updateRequired = false; + + for (int i = 0; i < m_tiles.count(); ++i) { + //for (int i = 0; i < 1; ++i) { + + const Tile &tile = m_tiles[i]; + + if (!tile.painted) { + + const qint64 tileStart = m_tileArrayStart + i * m_tileLength; + const qint64 tileEnd = tileStart + m_tileLength; + + if (m_bufferPosition <= tileStart && m_bufferPosition + m_bufferLength >= tileEnd) { + + paintTile(i); + updateRequired = true; + } + } + } + + if (updateRequired) + emit waveformImageChanged(true); + + return updateRequired; +} + +void Waveform::paintTile(int index) { + + const qint64 tileStart = m_tileArrayStart + index * m_tileLength; + + WAVEFORM_DEBUG << "paintTile" + << "index" << index + << "bufferPosition" << m_bufferPosition + << "bufferLength" << m_bufferLength + << "start" << tileStart + << "end" << tileStart + m_tileLength; + + Q_ASSERT(m_bufferPosition <= tileStart); + Q_ASSERT(m_bufferPosition + m_bufferLength >= tileStart + m_tileLength); + + Tile &tile = m_tiles[index]; + Q_ASSERT(!tile.painted); + + const qint16* base = reinterpret_cast(m_buffer.constData()); + const qint16* buffer = base + ((tileStart - m_bufferPosition) / 2); + const int numSamples = m_tileLength / (2 * m_format.channelCount()); + + QPainter painter(tile.pixmap); + + painter.fillRect(tile.pixmap->rect(), Qt::black); + //painter.fillRect(tile.pixmap->rect(), QColor(60, 60, 60)); + + //QPen pen(Qt::white); + QPen pen(QColor(85, 210, 250)); + painter.setPen(pen); + + // Calculate initial PCM value + qint16 previousPcmValue = 0; + if (buffer > base) + previousPcmValue = *(buffer - m_format.channelCount()); + + // Calculate initial point + const qreal previousRealValue = pcmToReal(previousPcmValue); + const int originY = ((previousRealValue + 1.0) / 2) * m_pixmapSize.height(); + const QPoint origin(0, originY); + + QLine line(origin, origin); + + for (int i = 0; i < numSamples; ++i) { + + const qint16* ptr = buffer + i * m_format.channelCount(); + + Q_ASSERT((reinterpret_cast(ptr) - m_buffer.constData()) >= 0); + Q_ASSERT((reinterpret_cast(ptr) - m_buffer.constData()) < m_bufferLength); + + const qint16 pcmValue = *ptr; + const qreal realValue = pcmToReal(pcmValue); + + const int x = tilePixelOffset(i * 2 * m_format.channelCount()); + const int y = ((realValue + 1.0) / 2) * m_pixmapSize.height(); + + line.setP2(QPoint(x, y)); + painter.drawLine(line); + line.setP1(line.p2()); + } + + tile.painted = true; +} + +void Waveform::shuffleTiles(int n) +{ + WAVEFORM_DEBUG << "shuffleTiles" << "n" << n; + + while (n--) { + Tile tile = m_tiles.first(); + tile.painted = false; + m_tiles.erase(m_tiles.begin()); + m_tiles += tile; + m_tileArrayStart += m_tileLength; + } + + WAVEFORM_DEBUG << "shuffleTiles" << "tileArrayStart" << m_tileArrayStart; +} + +void Waveform::resetTiles(qint64 newStartPos) +{ + WAVEFORM_DEBUG << "resetTiles" << "newStartPos" << newStartPos; + + QVector::iterator i = m_tiles.begin(); + for ( ; i != m_tiles.end(); ++i) + i->painted = false; + + m_tileArrayStart = newStartPos; +} + diff --git a/Source/src/AudioEngine/cusdr_audio_waveform.h b/Source/src/AudioEngine/cusdr_audio_waveform.h new file mode 100644 index 0000000..053837e --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_waveform.h @@ -0,0 +1,237 @@ +/** +* @file cusdr_audio_waveform.h +* @brief cuSDR waveform graphics header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef _CUSDR_WAVEFORM_H +#define _CUSDR_WAVEFORM_H + +#include +#include +#include + +#include "cusdr_settings.h" + +#ifdef LOG_WAVEFORM +# define WAVEFORM_DEBUG qDebug().nospace() << "WaveForm::\t" +#else +# define WAVEFORM_DEBUG nullDebug() +#endif + +#ifdef LOG_PAINT_EVENT +# define WAVEFORM_PAINT_DEBUG qDebug().nospace() << "WaveFormPaint::\t" +#else +# define WAVEFORM_PAINT_DEBUG nullDebug() +#endif + + +QT_FORWARD_DECLARE_CLASS(QByteArray) + +/** + * QObject which draws a section of the audio waveform. + * + * The waveform is rendered on a set of QPixmaps which form a group of tiles + * whose extent covers the widget. As the audio position is updated, these + * tiles are scrolled from left to right; when the left-most tile scrolls + * outside the widget, it is moved to the right end of the tile array and + * painted with the next section of the waveform. + */ + +class Waveform : public QObject { + + Q_OBJECT + +public: + Waveform(QObject *parent = 0); + ~Waveform(); + + void initialize( + const QAudioFormat &format, + qint64 audioBufferSize, + qint64 windowDurationUs, + const QRect &rect); + + void reset(); + + void setAutoUpdatePosition(bool enabled); + +public slots: + void bufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + void audioPositionChanged(QObject *sender, qint64 position); + + QImage* createWaveformImage(const QRect &rect); + +private: + static const int NullIndex = -1; + + void deletePixmaps(); + + /* + * (Re)create all pixmaps, repaint and update the display. + * Triggers an update(); + */ + void createPixmaps(const QSize &newSize); + + /* + * Update window position. + * Triggers an update(). + */ + void setWindowPosition(qint64 position); + + /* + * Base position of tile + */ + qint64 tilePosition(int index) const; + + /* + * Structure which identifies a point within a given + * tile. + */ + struct TilePoint + { + TilePoint(int idx = 0, qint64 pos = 0, qint64 pix = 0) + : index(idx), positionOffset(pos), pixelOffset(pix) + { } + + // Index of tile + int index; + + // Number of bytes from start of tile + qint64 positionOffset; + + // Number of pixels from left of corresponding pixmap + int pixelOffset; + }; + + /* + * Convert position in m_buffer into a tile index and an offset in pixels + * into the corresponding pixmap. + * + * \param position Offset into m_buffer, in bytes + + * If position is outside the tile array, index is NullIndex and + * offset is zero. + */ + TilePoint tilePoint(qint64 position) const; + + /* + * Convert offset in bytes into a tile into an offset in pixels + * within that tile. + */ + int tilePixelOffset(qint64 positionOffset) const; + + /* + * Convert offset in bytes into the window into an offset in pixels + * within the widget rect(). + */ + int windowPixelOffset(qint64 positionOffset, const QRect &rect) const; + + /* + * Paint all tiles which can be painted. + * \return true iff update() was called + */ + bool paintTiles(); + + /* + * Paint the specified tile + * + * \pre Sufficient data is available to completely paint the tile, i.e. + * m_dataLength is greater than the upper bound of the tile. + */ + void paintTile(int index); + + /* + * Move the first n tiles to the end of the array, and mark them as not + * painted. + */ + void shuffleTiles(int n); + + /* + * Reset tile array + */ + void resetTiles(qint64 newStartPos); + +private: + Settings* set; + + QRect m_audioRect; + qint64 m_bufferPosition; + qint64 m_bufferLength; + QByteArray m_buffer; + + qint64 m_audioPosition; + QAudioFormat m_format; + + bool m_active; + + QSize m_pixmapSize; + QVector m_pixmaps; + + struct Tile { + // Pointer into parent m_pixmaps array + QPixmap* pixmap; + + // Flag indicating whether this tile has been painted + bool painted; + }; + + QVector m_tiles; + + // Length of audio data in bytes depicted by each tile + qint64 m_tileLength; + + // Position in bytes of the first tile, relative to m_buffer + qint64 m_tileArrayStart; + + qint64 m_windowPosition; + qint64 m_windowLength; + int m_waveformDisplayWidth; + +signals: + void waveformImageChanged(bool value); +}; + +#endif // _CUSDR_WAVEFORM_H diff --git a/Source/src/AudioEngine/cusdr_audio_wavfile.cpp b/Source/src/AudioEngine/cusdr_audio_wavfile.cpp new file mode 100644 index 0000000..cc5d8b8 --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_wavfile.cpp @@ -0,0 +1,165 @@ +/** +* @file cusdr_audio_wavfile.cpp +* @brief cuSDR audio wav-file class +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +//#define LOG_AUDIO_WAVFILE + +#include +#include +#include +#include "cusdr_audio_utils.h" +#include "cusdr_audio_wavfile.h" + +struct chunk { + + char id[4]; + quint32 size; +}; + +struct RIFFHeader { + + chunk descriptor; // "RIFF" + char type[4]; // "WAVE" +}; + +struct WAVEHeader { + + chunk descriptor; + quint16 audioFormat; + quint16 numChannels; + quint32 sampleRate; + quint32 byteRate; + quint16 blockAlign; + quint16 bitsPerSample; +}; + +struct DATAHeader { + + chunk descriptor; +}; + +struct CombinedHeader { + + RIFFHeader riff; + WAVEHeader wave; +}; + +WavFile::WavFile(QObject *parent) + : QFile(parent) + , m_headerLength(0) +{ +} + +bool WavFile::open(const QString &fileName) { + + close(); + setFileName(fileName); + return QFile::open(QIODevice::ReadOnly) && readHeader(); +} + +const QAudioFormat &WavFile::fileFormat() const { + + return m_fileFormat; +} + +qint64 WavFile::headerLength() const { + + return m_headerLength; +} + +bool WavFile::readHeader() { + + seek(0); + CombinedHeader header; + bool result = read(reinterpret_cast(&header), sizeof(CombinedHeader)) == sizeof(CombinedHeader); + + AUDIO_WAVFILE_DEBUG << "header.id" << header.riff.descriptor.id; + AUDIO_WAVFILE_DEBUG << "header.type" << header.riff.type; + AUDIO_WAVFILE_DEBUG << "header.descriptor.id" << header.wave.descriptor.id; + AUDIO_WAVFILE_DEBUG << "header.audioFormat" << header.wave.audioFormat; + + if (result) { + if ((memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0 + || memcmp(&header.riff.descriptor.id, "RIFX", 4) == 0) + && memcmp(&header.riff.type, "WAVE", 4) == 0 + && memcmp(&header.wave.descriptor.id, "fmt ", 4) == 0 + && (header.wave.audioFormat == 1 || header.wave.audioFormat == 0 || header.wave.audioFormat == 3)) { + + // Read off remaining header information + DATAHeader dataHeader; + + if (qFromLittleEndian(header.wave.descriptor.size) > sizeof(WAVEHeader)) { + // Extended data available + quint16 extraFormatBytes; + if (peek((char*)&extraFormatBytes, sizeof(quint16)) != sizeof(quint16)) + return false; + const qint64 throwAwayBytes = sizeof(quint16) + qFromLittleEndian(extraFormatBytes); + if (read(throwAwayBytes).size() != throwAwayBytes) + return false; + } + + if (read((char*)&dataHeader, sizeof(DATAHeader)) != sizeof(DATAHeader)) + return false; + + // Establish format + if (memcmp(&header.riff.descriptor.id, "RIFF", 4) == 0) + m_fileFormat.setByteOrder(QAudioFormat::LittleEndian); + else + m_fileFormat.setByteOrder(QAudioFormat::BigEndian); + + int bps = qFromLittleEndian(header.wave.bitsPerSample); + m_fileFormat.setChannelCount(qFromLittleEndian(header.wave.numChannels)); + m_fileFormat.setCodec("audio/pcm"); + m_fileFormat.setSampleRate(qFromLittleEndian(header.wave.sampleRate)); + m_fileFormat.setSampleSize(qFromLittleEndian(header.wave.bitsPerSample)); + m_fileFormat.setSampleType(bps == 8 ? QAudioFormat::UnSignedInt : QAudioFormat::SignedInt); + } else { + result = false; + } + } + m_headerLength = pos(); + return result; +} diff --git a/Source/src/AudioEngine/cusdr_audio_wavfile.h b/Source/src/AudioEngine/cusdr_audio_wavfile.h new file mode 100644 index 0000000..4877566 --- /dev/null +++ b/Source/src/AudioEngine/cusdr_audio_wavfile.h @@ -0,0 +1,83 @@ +/** +* @file cusdr_audio_wavfile.h +* @brief cuSDR audio wav file header file +* @author adaptation for cuSDR by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-04-02 +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef _CUSDR_AUDIO_WAVFILE_H +#define _CUSDR_AUDIO_WAVFILE_H + +#include +#include +#include "cusdr_settings.h" + +#ifdef LOG_AUDIO_WAVFILE +# define AUDIO_WAVFILE_DEBUG qDebug().nospace() << "AudioWavFile::\t" +#else +# define AUDIO_WAVFILE_DEBUG nullDebug() +#endif + + +class WavFile : public QFile +{ +public: + WavFile(QObject *parent = 0); + + bool open(const QString &fileName); + const QAudioFormat &fileFormat() const; + qint64 headerLength() const; + +private: + bool readHeader(); + +private: + QAudioFormat m_fileFormat; + qint64 m_headerLength; + +}; + +#endif // _CUSDR_AUDIO_WAVFILE_H + diff --git a/Source/src/AudioEngine/cusdr_fspectrum.cpp b/Source/src/AudioEngine/cusdr_fspectrum.cpp new file mode 100644 index 0000000..73ac7bd --- /dev/null +++ b/Source/src/AudioEngine/cusdr_fspectrum.cpp @@ -0,0 +1,94 @@ +/** +* @file cusdr_fspectrum.cpp +* @brief audio frequency spectrum class for cuSDR +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "cusdr_fspectrum.h" + +FrequencySpectrum::FrequencySpectrum(int numPoints) + : m_elements(numPoints) +{ + +} + +void FrequencySpectrum::reset() { + + iterator i = begin(); + for ( ; i != end(); ++i) + *i = Element(); +} + +int FrequencySpectrum::count() const { + + return m_elements.count(); +} + +FrequencySpectrum::Element& FrequencySpectrum::operator[](int index) { + + return m_elements[index]; +} + +const FrequencySpectrum::Element& FrequencySpectrum::operator[](int index) const { + + return m_elements[index]; +} + +FrequencySpectrum::iterator FrequencySpectrum::begin() { + + return m_elements.begin(); +} + +FrequencySpectrum::iterator FrequencySpectrum::end() { + + return m_elements.end(); +} + +FrequencySpectrum::const_iterator FrequencySpectrum::begin() const { + + return m_elements.begin(); +} + +FrequencySpectrum::const_iterator FrequencySpectrum::end() const { + + return m_elements.end(); +} diff --git a/Source/src/AudioEngine/cusdr_fspectrum.h b/Source/src/AudioEngine/cusdr_fspectrum.h new file mode 100644 index 0000000..00ef638 --- /dev/null +++ b/Source/src/AudioEngine/cusdr_fspectrum.h @@ -0,0 +1,103 @@ +/** +* @file cusdr_fspectrum.h +* @brief audio frequency spectrum header file for cuSDR +*/ + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FREQUENCYSPECTRUM_H +#define FREQUENCYSPECTRUM_H + +#include + +/** + * Represents a frequency spectrum as a series of elements, each of which + * consists of a frequency, an amplitude and a phase. + */ +class FrequencySpectrum { +public: + FrequencySpectrum(int numPoints = 0); + + struct Element { + Element() + : frequency(0.0), amplitude(0.0), phase(0.0), clipped(false) + { } + + /** + * Frequency in Hertz + */ + qreal frequency; + + /** + * Amplitude in range [0.0, 1.0] + */ + qreal amplitude; + + /** + * Phase in range [0.0, 2*PI] + */ + qreal phase; + + /** + * Indicates whether value has been clipped during spectrum analysis + */ + bool clipped; + }; + + typedef QVector::iterator iterator; + typedef QVector::const_iterator const_iterator; + + void reset(); + + int count() const; + Element& operator[](int index); + const Element& operator[](int index) const; + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + +private: + QVector m_elements; + +}; + +#endif // FREQUENCYSPECTRUM_H diff --git a/Source/src/CL/qclbuffer.h b/Source/src/CL/qclbuffer.h new file mode 100644 index 0000000..8e3ea75 --- /dev/null +++ b/Source/src/CL/qclbuffer.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLBUFFER_H +#define QCLBUFFER_H + +#include "qclmemoryobject.h" +#include "qclevent.h" +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLImage2D; +class QCLImage3D; + +class Q_CL_EXPORT QCLBuffer : public QCLMemoryObject +{ +public: + QCLBuffer() {} + QCLBuffer(QCLContext *context, cl_mem id) + : QCLMemoryObject(context, id) {} + QCLBuffer(const QCLBuffer &other) + : QCLMemoryObject() { setId(other.context(), other.memoryId()); } + + QCLBuffer &operator=(const QCLBuffer &other) + { + setId(other.context(), other.memoryId()); + return *this; + } + + bool read(void *data, size_t size); + bool read(size_t offset, void *data, size_t size); + QCLEvent readAsync(size_t offset, void *data, size_t size, + const QCLEventList &after = QCLEventList()); + + bool readRect(const QRect &rect, void *data, + size_t bufferBytesPerLine, size_t hostBytesPerLine); + bool readRect(const size_t origin[3], const size_t size[3], void *data, + size_t bufferBytesPerLine, size_t bufferBytesPerSlice, + size_t hostBytesPerLine, size_t hostBytesPerSlice); + QCLEvent readRectAsync + (const QRect &rect, void *data, + size_t bufferBytesPerLine, size_t hostBytesPerLine, + const QCLEventList &after = QCLEventList()); + QCLEvent readRectAsync + (const size_t origin[3], const size_t size[3], void *data, + size_t bufferBytesPerLine, size_t bufferBytesPerSlice, + size_t hostBytesPerLine, size_t hostBytesPerSlice, + const QCLEventList &after = QCLEventList()); + + bool write(const void *data, size_t size); + bool write(size_t offset, const void *data, size_t size); + QCLEvent writeAsync(size_t offset, const void *data, size_t size, + const QCLEventList &after = QCLEventList()); + + bool writeRect(const QRect &rect, const void *data, + size_t bufferBytesPerLine, size_t hostBytesPerLine); + bool writeRect(const size_t origin[3], const size_t size[3], + const void *data, size_t bufferBytesPerLine, + size_t bufferBytesPerSlice, size_t hostBytesPerLine, + size_t hostBytesPerSlice); + QCLEvent writeRectAsync + (const QRect &rect, const void *data, + size_t bufferBytesPerLine, size_t hostBytesPerLine, + const QCLEventList &after = QCLEventList()); + QCLEvent writeRectAsync + (const size_t origin[3], const size_t size[3], const void *data, + size_t bufferBytesPerLine, size_t bufferBytesPerSlice, + size_t hostBytesPerLine, size_t hostBytesPerSlice, + const QCLEventList &after = QCLEventList()); + + bool copyTo(size_t offset, size_t size, + const QCLBuffer &dest, size_t destOffset); + bool copyTo(size_t offset, const QCLImage2D &dest, const QRect &rect); + bool copyTo(size_t offset, const QCLImage3D &dest, + const size_t origin[3], const size_t size[3]); + + QCLEvent copyToAsync + (size_t offset, size_t size, + const QCLBuffer &dest, size_t destOffset, + const QCLEventList &after = QCLEventList()); + QCLEvent copyToAsync + (size_t offset, const QCLImage2D &dest, const QRect &rect, + const QCLEventList &after = QCLEventList()); + QCLEvent copyToAsync + (size_t offset, const QCLImage3D &dest, + const size_t origin[3], const size_t size[3], + const QCLEventList &after = QCLEventList()); + + bool copyToRect(const QRect &rect, const QCLBuffer &dest, + const QPoint &destPoint, size_t bufferBytesPerLine, + size_t destBytesPerLine); + bool copyToRect(const size_t origin[3], const size_t size[3], + const QCLBuffer &dest, const size_t destOrigin[3], + size_t bufferBytesPerLine, size_t bufferBytesPerSlice, + size_t destBytesPerLine, size_t destBytesPerSlice); + QCLEvent copyToRectAsync + (const QRect &rect, const QCLBuffer &dest, const QPoint &destPoint, + size_t bufferBytesPerLine, size_t destBytesPerLine, + const QCLEventList &after = QCLEventList()); + QCLEvent copyToRectAsync + (const size_t origin[3], const size_t size[3], + const QCLBuffer &dest, const size_t destOrigin[3], + size_t bufferBytesPerLine, size_t bufferBytesPerSlice, + size_t destBytesPerLine, size_t destBytesPerSlice, + const QCLEventList &after = QCLEventList()); + + void *map(size_t offset, size_t size, QCLMemoryObject::Access access); + void *map(QCLMemoryObject::Access access); + QCLEvent mapAsync(void **ptr, size_t offset, size_t size, + QCLMemoryObject::Access access, + const QCLEventList &after = QCLEventList()); + + QCLBuffer createSubBuffer + (size_t offset, size_t size, QCLMemoryObject::Access access); + + QCLBuffer parentBuffer() const; + size_t offset() const; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclcommandqueue.h b/Source/src/CL/qclcommandqueue.h new file mode 100644 index 0000000..813e1a8 --- /dev/null +++ b/Source/src/CL/qclcommandqueue.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLCOMMANDQUEUE_H +#define QCLCOMMANDQUEUE_H + +#include "qclglobal.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; + +class Q_CL_EXPORT QCLCommandQueue +{ +public: + QCLCommandQueue() : m_id(0) {} + QCLCommandQueue(QCLContext *context, cl_command_queue id) + : m_context(context), m_id(id) {} + QCLCommandQueue(const QCLCommandQueue &other); + ~QCLCommandQueue(); + + QCLCommandQueue &operator=(const QCLCommandQueue &other); + + bool isNull() const { return m_id == 0; } + + bool isOutOfOrder() const; + bool isProfilingEnabled() const; + + cl_command_queue queueId() const { return m_id; } + QCLContext *context() const { return m_context; } + + bool operator==(const QCLCommandQueue &other) const; + bool operator!=(const QCLCommandQueue &other) const; + +private: + QCLContext *m_context; + cl_command_queue m_id; +}; + +inline QCLCommandQueue::QCLCommandQueue(const QCLCommandQueue &other) + : m_context(other.m_context), m_id(other.m_id) +{ + if (m_id) + clRetainCommandQueue(m_id); +} + +inline QCLCommandQueue::~QCLCommandQueue() +{ + if (m_id) + clReleaseCommandQueue(m_id); +} + +inline QCLCommandQueue &QCLCommandQueue::operator=(const QCLCommandQueue &other) +{ + m_context = other.m_context; + if (other.m_id) + clRetainCommandQueue(other.m_id); + if (m_id) + clReleaseCommandQueue(m_id); + m_id = other.m_id; + return *this; +} + +inline bool QCLCommandQueue::operator==(const QCLCommandQueue &other) const +{ + return m_id == other.m_id; +} + +inline bool QCLCommandQueue::operator!=(const QCLCommandQueue &other) const +{ + return m_id != other.m_id; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclcontext.h b/Source/src/CL/qclcontext.h new file mode 100644 index 0000000..f6506ec --- /dev/null +++ b/Source/src/CL/qclcontext.h @@ -0,0 +1,202 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLCONTEXT_H +#define QCLCONTEXT_H + +#include "qcldevice.h" +#include "qclcommandqueue.h" +#include "qclbuffer.h" +#include "qclvector.h" +#include "qclimage.h" +#include "qclsampler.h" +#include "qclprogram.h" +#include "qcluserevent.h" +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContextPrivate; +class QCLKernel; +class QCLVectorBase; + +class Q_CL_EXPORT QCLContext +{ +public: + QCLContext(); + virtual ~QCLContext(); + + bool isCreated() const; + + bool create(QCLDevice::DeviceTypes type = QCLDevice::Default); + bool create(const QList &devices); + virtual void release(); + + cl_context contextId() const; + void setContextId(cl_context id); + + QList devices() const; + QCLDevice defaultDevice() const; + + cl_int lastError() const; + void setLastError(cl_int error); + + static QString errorName(cl_int code); + + QCLCommandQueue commandQueue(); + void setCommandQueue(const QCLCommandQueue &queue); + + QCLCommandQueue defaultCommandQueue(); + QCLCommandQueue createCommandQueue + (cl_command_queue_properties properties, + const QCLDevice &device = QCLDevice()); + + QCLBuffer createBufferDevice + (size_t size, QCLMemoryObject::Access access); + QCLBuffer createBufferHost + (void *data, size_t size, QCLMemoryObject::Access access); + QCLBuffer createBufferCopy + (const void *data, size_t size, QCLMemoryObject::Access access); + + template + QCLVector createVector(int size, QCLMemoryObject::Access access = QCLMemoryObject::ReadWrite); + + QCLImage2D createImage2DDevice + (const QCLImageFormat &format, const QSize &size, QCLMemoryObject::Access access); + QCLImage2D createImage2DHost + (const QCLImageFormat &format, void *data, const QSize &size, + QCLMemoryObject::Access access, int bytesPerLine = 0); + QCLImage2D createImage2DHost(QImage *image, QCLMemoryObject::Access access); + QCLImage2D createImage2DCopy + (const QCLImageFormat &format, const void *data, const QSize &size, + QCLMemoryObject::Access access, int bytesPerLine = 0); + QCLImage2D createImage2DCopy + (const QImage &image, QCLMemoryObject::Access access); + + QCLImage3D createImage3DDevice + (const QCLImageFormat &format, int width, int height, int depth, + QCLMemoryObject::Access access); + QCLImage3D createImage3DHost + (const QCLImageFormat &format, void *data, + int width, int height, int depth, QCLMemoryObject::Access access, + int bytesPerLine = 0, int bytesPerSlice = 0); + QCLImage3D createImage3DCopy + (const QCLImageFormat &format, const void *data, + int width, int height, int depth, QCLMemoryObject::Access access, + int bytesPerLine = 0, int bytesPerSlice = 0); + + QCLProgram createProgramFromSourceCode(const QByteArray &sourceCode); + QCLProgram createProgramFromSourceFile(const QString &fileName); + QCLProgram createProgramFromBinaryCode(const QByteArray &binary); + QCLProgram createProgramFromBinaryFile(const QString &fileName); + QCLProgram createProgramFromBinaries + (const QList &devices, const QList &binaries); + + QCLProgram buildProgramFromSourceCode(const QByteArray &sourceCode); + QCLProgram buildProgramFromSourceFile(const QString &fileName); + QCLProgram buildProgramFromBinaryCode(const QByteArray &binary); + QCLProgram buildProgramFromBinaryFile(const QString &fileName); + QCLProgram buildProgramFromBinaries + (const QList &devices, const QList &binaries); + + QList supportedImage2DFormats(cl_mem_flags flags) const; + QList supportedImage3DFormats(cl_mem_flags flags) const; + + QCLSampler createSampler + (bool normalizedCoordinates, QCLSampler::AddressingMode addressingMode, + QCLSampler::FilterMode filterMode); + + QCLUserEvent createUserEvent(); + + void flush(); + void finish(); + + QCLEvent marker(); + + void sync(); + + void barrier(); + void barrier(const QCLEventList &events); + +protected: + void setDefaultDevice(const QCLDevice &device); + +private: + QScopedPointer d_ptr; + + Q_DISABLE_COPY(QCLContext) + Q_DECLARE_PRIVATE(QCLContext) + + cl_command_queue activeQueue(); // For quicker access from friends. + + friend class QCLMemoryObject; + friend class QCLBuffer; + friend class QCLImage2D; + friend class QCLImage3D; + friend class QCLKernel; + friend class QCLCommandQueue; + friend class QCLProgram; + friend class QCLVectorBase; + friend class QCLSampler; + + void reportError(const char *name, cl_int error); +}; + +template +Q_INLINE_TEMPLATE QCLVector QCLContext::createVector + (int size, QCLMemoryObject::Access access) +{ + Q_ASSERT(size >= 1); + return QCLVector(this, size, access); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qcldevice.h b/Source/src/CL/qcldevice.h new file mode 100644 index 0000000..b73d0cd --- /dev/null +++ b/Source/src/CL/qcldevice.h @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLDEVICE_H +#define QCLDEVICE_H + +#include "qclplatform.h" +#include "qclworksize.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class Q_CL_EXPORT QCLDevice +{ +public: + QCLDevice() : m_id(0), m_flags(0) {} + QCLDevice(cl_device_id id) : m_id(id), m_flags(0) {} + + enum DeviceType + { + Default = 0x00000001, + CPU = 0x00000002, + GPU = 0x00000004, + Accelerator = 0x00000008, + All = 0xFFFFFFFF + }; + Q_DECLARE_FLAGS(DeviceTypes, DeviceType) + + bool isNull() const { return m_id == 0; } + + QCLDevice::DeviceTypes deviceType() const; + QCLPlatform platform() const; + uint vendorId() const; + bool isAvailable() const; + + bool hasCompiler() const; + bool hasNativeKernels() const; + bool hasOutOfOrderExecution() const; + bool hasDouble() const; + bool hasHalfFloat() const; + bool hasErrorCorrectingMemory() const; + bool hasUnifiedMemory() const; + + int computeUnits() const; + int clockFrequency() const; + int addressBits() const; + QSysInfo::Endian byteOrder() const; + + QCLWorkSize maximumWorkItemSize() const; + size_t maximumWorkItemsPerGroup() const; + + bool hasImage2D() const; + bool hasImage3D() const; + bool hasWritableImage3D() const; + QSize maximumImage2DSize() const; + QCLWorkSize maximumImage3DSize() const; + int maximumSamplers() const; + int maximumReadImages() const; + int maximumWriteImages() const; + + int preferredCharVectorSize() const; + int preferredShortVectorSize() const; + int preferredIntVectorSize() const; + int preferredLongVectorSize() const; + int preferredFloatVectorSize() const; + int preferredDoubleVectorSize() const; + int preferredHalfFloatVectorSize() const; + + int nativeCharVectorSize() const; + int nativeShortVectorSize() const; + int nativeIntVectorSize() const; + int nativeLongVectorSize() const; + int nativeFloatVectorSize() const; + int nativeDoubleVectorSize() const; + int nativeHalfFloatVectorSize() const; + + enum FloatCapability + { + NotSupported = 0x0000, + Denorm = 0x0001, + InfinityNaN = 0x0002, + RoundNearest = 0x0004, + RoundZero = 0x0008, + RoundInfinity = 0x0010, + FusedMultiplyAdd = 0x0020 + }; + Q_DECLARE_FLAGS(FloatCapabilities, FloatCapability) + + QCLDevice::FloatCapabilities floatCapabilities() const; + QCLDevice::FloatCapabilities doubleCapabilities() const; + QCLDevice::FloatCapabilities halfFloatCapabilities() const; + + quint64 profilingTimerResolution() const; + + enum CacheType + { + NoCache = 0, + ReadOnlyCache = 1, + ReadWriteCache = 2 + }; + + quint64 maximumAllocationSize() const; + quint64 globalMemorySize() const; + QCLDevice::CacheType globalMemoryCacheType() const; + quint64 globalMemoryCacheSize() const; + int globalMemoryCacheLineSize() const; + quint64 localMemorySize() const; + bool isLocalMemorySeparate() const; + quint64 maximumConstantBufferSize() const; + int maximumConstantArguments() const; + + int defaultAlignment() const; + int minimumAlignment() const; + int maximumParameterBytes() const; + + bool isFullProfile() const; + bool isEmbeddedProfile() const; + + QString profile() const; + QString version() const; + QString driverVersion() const; + QString name() const; + QString vendor() const; + QStringList extensions() const; + QString languageVersion() const; + + bool hasExtension(const char *name) const; + + QCLPlatform::VersionFlags versionFlags() const; + + cl_device_id deviceId() const { return m_id; } + + static QList allDevices(); + static QList devices + (QCLDevice::DeviceTypes types, + const QCLPlatform &platform = QCLPlatform()); + + bool operator==(const QCLDevice &other) const; + bool operator!=(const QCLDevice &other) const; + +private: + cl_device_id m_id; + mutable int m_flags; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QCLDevice::DeviceTypes) +Q_DECLARE_OPERATORS_FOR_FLAGS(QCLDevice::FloatCapabilities) + +inline bool QCLDevice::operator==(const QCLDevice &other) const +{ + return m_id == other.m_id; +} + +inline bool QCLDevice::operator!=(const QCLDevice &other) const +{ + return m_id != other.m_id; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CL_EXPORT QDebug operator<<(QDebug, const QCLDevice &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclevent.h b/Source/src/CL/qclevent.h new file mode 100644 index 0000000..78b2651 --- /dev/null +++ b/Source/src/CL/qclevent.h @@ -0,0 +1,230 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLEVENT_H +#define QCLEVENT_H + +#include "qclglobal.h" +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLUserEvent; + +class Q_CL_EXPORT QCLEvent +{ +public: + QCLEvent() : m_id(0) {} + QCLEvent(cl_event id) : m_id(id) {} + QCLEvent(const QCLEvent &other); + ~QCLEvent(); + + QCLEvent &operator=(const QCLEvent &other); + + bool isNull() const { return m_id == 0; } + + cl_event eventId() const { return m_id; } + + bool isQueued() const { return status() == CL_QUEUED; } + bool isSubmitted() const { return status() == CL_SUBMITTED; } + bool isRunning() const { return status() == CL_RUNNING; } + bool isFinished() const { return status() == CL_COMPLETE; } + bool isErrored() const { return status() < 0; } + + cl_int status() const; + cl_command_type commandType() const; + + void waitForFinished(); + + quint64 queueTime() const; + quint64 submitTime() const; + quint64 runTime() const; + quint64 finishTime() const; + + bool operator==(const QCLEvent &other) const; + bool operator!=(const QCLEvent &other) const; + +#if !defined(QT_NO_CONCURRENT) + QFuture toFuture() const; + operator QFuture() const; +#endif + +private: + cl_event m_id; + + friend class QCLUserEvent; +}; + +inline QCLEvent::QCLEvent(const QCLEvent &other) + : m_id(other.m_id) +{ + if (m_id) + clRetainEvent(m_id); +} + +inline QCLEvent::~QCLEvent() +{ + if (m_id) + clReleaseEvent(m_id); +} + +inline QCLEvent &QCLEvent::operator=(const QCLEvent &other) +{ + if (other.m_id) + clRetainEvent(other.m_id); + if (m_id) + clReleaseEvent(m_id); + m_id = other.m_id; + return *this; +} + +class Q_CL_EXPORT QCLEventList +{ +public: + QCLEventList() {} + QCLEventList(const QCLEvent &event); + QCLEventList(const QCLEventList &other); + ~QCLEventList(); + + QCLEventList &operator=(const QCLEventList &other); + + bool isEmpty() const { return m_events.isEmpty(); } + int size() const { return m_events.size(); } + + void append(const QCLEvent &event); + void append(const QCLEventList &other); + void remove(const QCLEvent &event); + + QCLEvent at(int index) const; + bool contains(const QCLEvent &event) const; + + const cl_event *eventData() const; + + QCLEventList &operator+=(const QCLEvent &event); + QCLEventList &operator+=(const QCLEventList &other); + + QCLEventList &operator<<(const QCLEvent &event); + QCLEventList &operator<<(const QCLEventList &other); + + void waitForFinished(); + +#ifndef QT_NO_CONCURRENT + QFuture toFuture() const; + operator QFuture() const; +#endif + +private: + QVector m_events; +}; + +inline bool QCLEvent::operator==(const QCLEvent &other) const +{ + return m_id == other.m_id; +} + +inline bool QCLEvent::operator!=(const QCLEvent &other) const +{ + return m_id != other.m_id; +} + +#ifndef QT_NO_CONCURRENT +inline QCLEvent::operator QFuture() const +{ + return toFuture(); +} +#endif + +inline bool QCLEventList::contains(const QCLEvent &event) const +{ + return m_events.contains(event.eventId()); +} + +inline const cl_event *QCLEventList::eventData() const +{ + return m_events.isEmpty() ? 0 : m_events.constData(); +} + +inline QCLEventList &QCLEventList::operator+=(const QCLEvent &event) +{ + append(event); + return *this; +} + +inline QCLEventList &QCLEventList::operator+=(const QCLEventList &other) +{ + append(other); + return *this; +} + +inline QCLEventList &QCLEventList::operator<<(const QCLEvent &event) +{ + append(event); + return *this; +} + +inline QCLEventList &QCLEventList::operator<<(const QCLEventList &other) +{ + append(other); + return *this; +} + +#ifndef QT_NO_CONCURRENT +inline QCLEventList::operator QFuture() const +{ + return toFuture(); +} +#endif + +#ifndef QT_NO_DEBUG_STREAM +Q_CL_EXPORT QDebug operator<<(QDebug, const QCLEvent &); +Q_CL_EXPORT QDebug operator<<(QDebug, const QCLEventList &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclext_p.h b/Source/src/CL/qclext_p.h new file mode 100644 index 0000000..a50df50 --- /dev/null +++ b/Source/src/CL/qclext_p.h @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLEXT_P_H +#define QCLEXT_P_H + +#include "qclglobal.h" + +// This file provides standard and extension definitions +// that we cannot rely upon being present in the system headers. + +// OpenCL 1.1 +#ifndef CL_MISALIGNED_SUB_BUFFER_OFFSET +#define CL_MISALIGNED_SUB_BUFFER_OFFSET -13 +#endif +#ifndef CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST +#define CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST -14 +#endif +#ifndef CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF +#define CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF 0x1034 +#endif +#ifndef CL_DEVICE_HOST_UNIFIED_MEMORY +#define CL_DEVICE_HOST_UNIFIED_MEMORY 0x1035 +#endif +#ifndef CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR 0x1036 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT 0x1037 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_INT 0x1038 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG 0x1039 +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT 0x103A +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE 0x103B +#define CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF 0x103C +#endif +#ifndef CL_DEVICE_OPENCL_C_VERSION +#define CL_DEVICE_OPENCL_C_VERSION 0x103D +#endif +#ifndef CL_COMMAND_READ_BUFFER_RECT +#define CL_COMMAND_READ_BUFFER_RECT 0x1201 +#endif +#ifndef CL_COMMAND_WRITE_BUFFER_RECT +#define CL_COMMAND_WRITE_BUFFER_RECT 0x1202 +#endif +#ifndef CL_COMMAND_COPY_BUFFER_RECT +#define CL_COMMAND_COPY_BUFFER_RECT 0x1203 +#endif +#ifndef CL_COMMAND_USER +#define CL_COMMAND_USER 0x1204 +#endif +#ifndef CL_MEM_ASSOCIATED_MEMOBJECT +#define CL_MEM_ASSOCIATED_MEMOBJECT 0x1107 +#endif +#ifndef CL_MEM_OFFSET +#define CL_MEM_OFFSET 0x1108 +#endif +#ifndef CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE +#define CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE 0x11B3 +#endif + +// OpenCL-OpenGL sharing. +#ifndef CL_INVALID_CL_SHAREGROUP_REFERENCE_KHR +#define CL_INVALID_CL_SHAREGROUP_REFERENCE_KHR -1000 +#endif + +// cl_khr_fp64 +#ifndef CL_DEVICE_DOUBLE_FP_CONFIG +#define CL_DEVICE_DOUBLE_FP_CONFIG 0x1032 +#endif + +// cl_khr_fp16 +#ifndef CL_DEVICE_HALF_FP_CONFIG +#define CL_DEVICE_HALF_FP_CONFIG 0x1033 +#endif + +// cl_khr_icd +#ifndef CL_PLATFORM_ICD_SUFFIX_KHR +#define CL_PLATFORM_ICD_SUFFIX_KHR 0x0920 +#endif +#ifndef CL_PLATFORM_NOT_FOUND_KHR +#define CL_PLATFORM_NOT_FOUND_KHR -1001 +#endif + +// cl_ext_device_fission +#ifndef CL_DEVICE_PARTITION_FAILED_EXT +#define CL_DEVICE_PARTITION_FAILED_EXT -1057 +#endif +#ifndef CL_INVALID_PARTITION_COUNT_EXT +#define CL_INVALID_PARTITION_COUNT_EXT -1058 +#endif +#ifndef CL_INVALID_PARTITION_NAME_EXT +#define CL_INVALID_PARTITION_NAME_EXT -1059 +#endif + +#endif diff --git a/Source/src/CL/qclglobal.h b/Source/src/CL/qclglobal.h new file mode 100644 index 0000000..59c07ad --- /dev/null +++ b/Source/src/CL/qclglobal.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLGLOBAL_H +#define QCLGLOBAL_H + +#include + +// XXX: Move to qglobal.h eventually. +QT_LICENSED_MODULE(CL) +#if defined(Q_OS_WIN) && defined(QT_MAKEDLL) +# if defined(QT_BUILD_CL_LIB) +# define Q_CL_EXPORT Q_DECL_EXPORT +# else +# define Q_CL_EXPORT Q_DECL_IMPORT +# endif +#elif defined(Q_OS_WIN) && defined(QT_DLL) +# define Q_CL_EXPORT Q_DECL_IMPORT +#endif +#if !defined(Q_CL_EXPORT) +# if defined(QT_SHARED) +# define Q_CL_EXPORT Q_DECL_EXPORT +# else +# define Q_CL_EXPORT +# endif +#endif + +QT_LICENSED_MODULE(CLGL) +#if defined(Q_OS_WIN) && defined(QT_MAKEDLL) +# if defined(QT_BUILD_CLGL_LIB) +# define Q_CLGL_EXPORT Q_DECL_EXPORT +# else +# define Q_CLGL_EXPORT Q_DECL_IMPORT +# endif +#elif defined(Q_OS_WIN) && defined(QT_DLL) +# define Q_CLGL_EXPORT Q_DECL_IMPORT +#endif +#if !defined(Q_CLGL_EXPORT) +# if defined(QT_SHARED) +# define Q_CLGL_EXPORT Q_DECL_EXPORT +# else +# define Q_CLGL_EXPORT +# endif +#endif + +#if defined(__APPLE__) || defined(__MACOSX) +#include +#include +#else +#include +#include +#endif + +#endif diff --git a/Source/src/CL/qclimage.h b/Source/src/CL/qclimage.h new file mode 100644 index 0000000..ab27dd3 --- /dev/null +++ b/Source/src/CL/qclimage.h @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLIMAGE_H +#define QCLIMAGE_H + +#include "qclmemoryobject.h" +#include "qclimageformat.h" +#include "qclevent.h" +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLImage2DPrivate; +class QCLImage3D; +class QCLBuffer; +class QPainter; + +class Q_CL_EXPORT QCLImage2D : public QCLMemoryObject +{ +public: + QCLImage2D() : d_ptr(0) {} + QCLImage2D(QCLContext *context, cl_mem id) + : QCLMemoryObject(context, id), d_ptr(0) {} + QCLImage2D(const QCLImage2D &other); + ~QCLImage2D(); + + QCLImage2D &operator=(const QCLImage2D &other); + + QCLImageFormat format() const; + + int width() const; + int height() const; + + int bytesPerElement() const; + int bytesPerLine() const; + + bool read(void *data, const QRect &rect, int bytesPerLine = 0); + bool read(QImage *image, const QRect &rect = QRect()); + QCLEvent readAsync(void *data, const QRect &rect, + const QCLEventList &after = QCLEventList(), + int bytesPerLine = 0); + + bool write(const void *data, const QRect &rect, int bytesPerLine = 0); + bool write(const QImage &image, const QRect &rect = QRect()); + QCLEvent writeAsync + (const void *data, const QRect &rect, + const QCLEventList &after = QCLEventList(), + int bytesPerLine = 0); + + bool copyTo(const QRect &rect, const QCLImage2D &dest, + const QPoint &destOffset); + bool copyTo(const QRect &rect, const QCLImage3D &dest, + const size_t destOffset[3]); + bool copyTo(const QRect &rect, const QCLBuffer &dest, + size_t destOffset); + QCLEvent copyToAsync + (const QRect &rect, const QCLImage2D &dest, const QPoint &destOffset, + const QCLEventList &after = QCLEventList()); + QCLEvent copyToAsync + (const QRect &rect, const QCLImage3D &dest, const size_t destOffset[3], + const QCLEventList &after = QCLEventList()); + QCLEvent copyToAsync + (const QRect &rect, const QCLBuffer &dest, size_t destOffset, + const QCLEventList &after = QCLEventList()); + + void *map(const QRect &rect, QCLMemoryObject::Access access, + int *bytesPerLine = 0); + QCLEvent mapAsync(void **ptr, const QRect &rect, + QCLMemoryObject::Access access, + const QCLEventList &after = QCLEventList(), + int *bytesPerLine = 0); + + QImage toQImage(bool cached = true); + + void drawImage(QPainter *painter, const QPoint &point, + const QRect &subRect = QRect(), + Qt::ImageConversionFlags flags = Qt::AutoColor); + void drawImage(QPainter *painter, const QRect &targetRect, + const QRect &subRect = QRect(), + Qt::ImageConversionFlags flags = Qt::AutoColor); + +private: + mutable QCLImage2DPrivate *d_ptr; + + Q_DECLARE_PRIVATE(QCLImage2D) + + QCLImage2D(QCLContext *context, cl_mem id, const QCLImageFormat& format); + + friend class QCLContext; +}; + +class Q_CL_EXPORT QCLImage3D : public QCLMemoryObject +{ +public: + QCLImage3D() {} + QCLImage3D(QCLContext *context, cl_mem id) + : QCLMemoryObject(context, id) {} + QCLImage3D(const QCLImage3D &other) + : QCLMemoryObject() { setId(other.context(), other.memoryId()); } + + QCLImage3D &operator=(const QCLImage3D &other) + { + setId(other.context(), other.memoryId()); + return *this; + } + + QCLImageFormat format() const; + + int width() const; + int height() const; + int depth() const; + + int bytesPerElement() const; + int bytesPerLine() const; + int bytesPerSlice() const; + + bool read(void *data, const size_t origin[3], const size_t size[3], + int bytesPerLine = 0, int bytesPerSlice = 0); + QCLEvent readAsync + (void *data, const size_t origin[3], const size_t size[3], + const QCLEventList &after = QCLEventList(), + int bytesPerLine = 0, int bytesPerSlice = 0); + + bool write(const void *data, const size_t origin[3], const size_t size[3], + int bytesPerLine = 0, int bytesPerSlice = 0); + QCLEvent writeAsync + (const void *data, const size_t origin[3], const size_t size[3], + const QCLEventList &after = QCLEventList(), + int bytesPerLine = 0, int bytesPerSlice = 0); + + bool copyTo(const size_t origin[3], const size_t size[3], + const QCLImage3D &dest, const size_t destOffset[3]); + bool copyTo(const size_t origin[3], const QSize &size, + const QCLImage2D &dest, const QPoint &destOffset); + bool copyTo(const size_t origin[3], const size_t size[3], + const QCLBuffer &dest, size_t destOffset); + QCLEvent copyToAsync + (const size_t origin[3], const size_t size[3], + const QCLImage3D &dest, const size_t destOffset[3], + const QCLEventList &after = QCLEventList()); + QCLEvent copyToAsync + (const size_t origin[3], const QSize &size, + const QCLImage2D &dest, const QPoint &destOffset, + const QCLEventList &after = QCLEventList()); + QCLEvent copyToAsync + (const size_t origin[3], const size_t size[3], + const QCLBuffer &dest, size_t destOffset, + const QCLEventList &after = QCLEventList()); + + void *map(const size_t origin[3], const size_t size[3], + QCLMemoryObject::Access access, + int *bytesPerLine = 0, int *bytesPerSlice = 0); + QCLEvent mapAsync + (void **ptr, const size_t origin[3], const size_t size[3], + QCLMemoryObject::Access access, + const QCLEventList &after = QCLEventList(), + int *bytesPerLine = 0, int *bytesPerSlice = 0); +}; + +inline void QCLImage2D::drawImage + (QPainter *painter, const QPoint &point, + const QRect &subRect, Qt::ImageConversionFlags flags) +{ + drawImage(painter, QRect(point.x(), point.y(), -1, -1), subRect, flags); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclimageformat.h b/Source/src/CL/qclimageformat.h new file mode 100644 index 0000000..a6f6ba5 --- /dev/null +++ b/Source/src/CL/qclimageformat.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLIMAGEFORMAT_H +#define QCLIMAGEFORMAT_H + +#include "qclglobal.h" +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; + +class Q_CL_EXPORT QCLImageFormat +{ +public: + enum ChannelOrder + { + Order_R = 0x10B0, + Order_A = 0x10B1, + Order_RG = 0x10B2, + Order_RA = 0x10B3, + Order_RGB = 0x10B4, + Order_RGBA = 0x10B5, + Order_BGRA = 0x10B6, + Order_ARGB = 0x10B7, + Order_Intensity = 0x10B8, + Order_Luminence = 0x10B9, + Order_Rx = 0x10BA, // OpenCL 1.1 + Order_RGx = 0x10BB, // OpenCL 1.1 + Order_RGBx = 0x10BC // OpenCL 1.1 + }; + + enum ChannelType + { + Type_Normalized_Int8 = 0x10D0, + Type_Normalized_Int16 = 0x10D1, + Type_Normalized_UInt8 = 0x10D2, + Type_Normalized_UInt16 = 0x10D3, + Type_Normalized_565 = 0x10D4, + Type_Normalized_555 = 0x10D5, + Type_Normalized_101010 = 0x10D6, + Type_Unnormalized_Int8 = 0x10D7, + Type_Unnormalized_Int16 = 0x10D8, + Type_Unnormalized_Int32 = 0x10D9, + Type_Unnormalized_UInt8 = 0x10DA, + Type_Unnormalized_UInt16 = 0x10DB, + Type_Unnormalized_UInt32 = 0x10DC, + Type_Half_Float = 0x10DD, + Type_Float = 0x10DE + }; + + QCLImageFormat(); + QCLImageFormat(QCLImageFormat::ChannelOrder order, + QCLImageFormat::ChannelType type); + QCLImageFormat(QImage::Format format); + + bool isNull() const; + + QCLImageFormat::ChannelOrder channelOrder() const; + QCLImageFormat::ChannelType channelType() const; + + bool operator==(const QCLImageFormat &other); + bool operator!=(const QCLImageFormat &other); + + QImage::Format toQImageFormat() const { return m_qformat; } + +private: + cl_image_format m_format; + QImage::Format m_qformat; + + friend class QCLContext; +}; + +inline QCLImageFormat::QCLImageFormat() +{ + m_format.image_channel_order = 0; + m_format.image_channel_data_type = 0; + m_qformat = QImage::Format_Invalid; +} + +inline bool QCLImageFormat::isNull() const +{ + return m_format.image_channel_order == 0 && + m_format.image_channel_data_type == 0 && + m_qformat == QImage::Format_Invalid; +} + +inline QCLImageFormat::ChannelOrder QCLImageFormat::channelOrder() const +{ + return QCLImageFormat::ChannelOrder(m_format.image_channel_order); +} + +inline QCLImageFormat::ChannelType QCLImageFormat::channelType() const +{ + return QCLImageFormat::ChannelType(m_format.image_channel_data_type); +} + +inline bool QCLImageFormat::operator==(const QCLImageFormat &other) +{ + return m_format.image_channel_order == + other.m_format.image_channel_order && + m_format.image_channel_data_type == + other.m_format.image_channel_data_type && + m_qformat == other.m_qformat; +} + +inline bool QCLImageFormat::operator!=(const QCLImageFormat &other) +{ + return m_format.image_channel_order != + other.m_format.image_channel_order || + m_format.image_channel_data_type != + other.m_format.image_channel_data_type || + m_qformat != other.m_qformat; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CL_EXPORT QDebug operator<<(QDebug, const QCLImageFormat &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclkernel.h b/Source/src/CL/qclkernel.h new file mode 100644 index 0000000..26f553b --- /dev/null +++ b/Source/src/CL/qclkernel.h @@ -0,0 +1,480 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLKERNEL_H +#define QCLKERNEL_H + +#include "qclglobal.h" +#include "qclevent.h" +#include "qclworksize.h" +#include "qclmemoryobject.h" +#include "qclsampler.h" +#include "qclvector.h" +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; +class QCLProgram; +class QCLVectorBase; +class QCLDevice; +class QMatrix4x4; +class QColor; + +class QCLKernelPrivate; + +class Q_CL_EXPORT QCLKernel +{ +public: + QCLKernel(); + QCLKernel(QCLContext *context, cl_kernel id); + QCLKernel(const QCLKernel &other); + ~QCLKernel(); + + QCLKernel &operator=(const QCLKernel &other); + + bool isNull() const; + + bool operator==(const QCLKernel &other) const; + bool operator!=(const QCLKernel &other) const; + + cl_kernel kernelId() const; + QCLContext *context() const; + + QCLProgram program() const; + QString name() const; + int argCount() const; + + QCLWorkSize declaredWorkGroupSize() const; + QCLWorkSize declaredWorkGroupSize(const QCLDevice &device) const; + + QCLWorkSize globalWorkSize() const; + void setGlobalWorkSize(const QCLWorkSize &size); + void setGlobalWorkSize(size_t width, size_t height); + void setGlobalWorkSize(size_t width, size_t height, size_t depth); + + void setRoundedGlobalWorkSize(const QCLWorkSize &size); + void setRoundedGlobalWorkSize(size_t width, size_t height); + void setRoundedGlobalWorkSize(size_t width, size_t height, size_t depth); + + QCLWorkSize localWorkSize() const; + void setLocalWorkSize(const QCLWorkSize &size); + void setLocalWorkSize(size_t width, size_t height); + void setLocalWorkSize(size_t width, size_t height, size_t depth); + + QCLWorkSize bestLocalWorkSizeImage2D() const; + QCLWorkSize bestLocalWorkSizeImage3D() const; + + size_t preferredWorkSizeMultiple() const; + + void setArg(int index, cl_int value); + void setArg(int index, cl_uint value); + void setArg(int index, cl_long value); + void setArg(int index, cl_ulong value); + void setArg(int index, float value); + void setArg(int index, const QVector2D &value); + void setArg(int index, const QVector3D &value); + void setArg(int index, const QVector4D &value); + void setArg(int index, const QColor &value); + void setArg(int index, Qt::GlobalColor value); + void setArg(int index, const QPoint &value); + void setArg(int index, const QPointF &value); + void setArg(int index, const QMatrix4x4 &value); + void setArg(int index, const QCLMemoryObject &value); +#if defined(qdoc) + void setArg(int index, const QCLVector &value); +#else + void setArg(int index, const QCLVectorBase &value); +#endif + void setArg(int index, const QCLSampler &value); + void setArg(int index, const void *data, size_t size); + + QCLEvent run(); + QCLEvent run(const QCLEventList &after); + + inline QCLEvent operator()() { return run(); } + + template + inline QCLEvent operator()(const T1 &arg1) + { + setArg(0, arg1); + return run(); + } + + template + inline QCLEvent operator()(const T1 &arg1, const T2 &arg2) + { + setArg(0, arg1); + setArg(1, arg2); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, + const T5 &arg5) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + setArg(4, arg5); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, + const T5 &arg5, const T6 &arg6) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + setArg(4, arg5); + setArg(5, arg6); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, + const T5 &arg5, const T6 &arg6, const T7 &arg7) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + setArg(4, arg5); + setArg(5, arg6); + setArg(6, arg7); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, + const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + setArg(4, arg5); + setArg(5, arg6); + setArg(6, arg7); + setArg(7, arg8); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, + const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, + const T9 &arg9) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + setArg(4, arg5); + setArg(5, arg6); + setArg(6, arg7); + setArg(7, arg8); + setArg(8, arg9); + return run(); + } + + template + inline QCLEvent operator() + (const T1 &arg1, const T2 &arg2, const T3 &arg3, const T4 &arg4, + const T5 &arg5, const T6 &arg6, const T7 &arg7, const T8 &arg8, + const T9 &arg9, const T10 &arg10) + { + setArg(0, arg1); + setArg(1, arg2); + setArg(2, arg3); + setArg(3, arg4); + setArg(4, arg5); + setArg(5, arg6); + setArg(6, arg7); + setArg(7, arg8); + setArg(8, arg9); + setArg(9, arg10); + return run(); + } + +#ifndef QT_NO_CONCURRENT + QFuture runInThread(); +#endif + +private: + QScopedPointer d_ptr; + cl_kernel m_kernelId; + + Q_DECLARE_PRIVATE(QCLKernel) +}; + +inline void QCLKernel::setGlobalWorkSize(size_t width, size_t height) +{ + setGlobalWorkSize(QCLWorkSize(width, height)); +} + +inline void QCLKernel::setGlobalWorkSize(size_t width, size_t height, size_t depth) +{ + setGlobalWorkSize(QCLWorkSize(width, height, depth)); +} + +inline void QCLKernel::setRoundedGlobalWorkSize(const QCLWorkSize &size) +{ + setGlobalWorkSize(size.roundTo(localWorkSize())); +} + +inline void QCLKernel::setRoundedGlobalWorkSize(size_t width, size_t height) +{ + setRoundedGlobalWorkSize(QCLWorkSize(width, height)); +} + +inline void QCLKernel::setRoundedGlobalWorkSize(size_t width, size_t height, size_t depth) +{ + setRoundedGlobalWorkSize(QCLWorkSize(width, height, depth)); +} + +inline void QCLKernel::setLocalWorkSize(size_t width, size_t height) +{ + setLocalWorkSize(QCLWorkSize(width, height)); +} + +inline void QCLKernel::setLocalWorkSize(size_t width, size_t height, size_t depth) +{ + setLocalWorkSize(QCLWorkSize(width, height, depth)); +} + +inline void QCLKernel::setArg(int index, cl_int value) +{ + clSetKernelArg(m_kernelId, index, sizeof(value), &value); +} + +inline void QCLKernel::setArg(int index, cl_uint value) +{ + clSetKernelArg(m_kernelId, index, sizeof(value), &value); +} + +inline void QCLKernel::setArg(int index, cl_long value) +{ + clSetKernelArg(m_kernelId, index, sizeof(value), &value); +} + +inline void QCLKernel::setArg(int index, cl_ulong value) +{ + clSetKernelArg(m_kernelId, index, sizeof(value), &value); +} + +inline void QCLKernel::setArg(int index, float value) +{ + clSetKernelArg(m_kernelId, index, sizeof(value), &value); +} + +inline void QCLKernel::setArg(int index, const QVector2D &value) +{ + if (sizeof(value) == (sizeof(float) * 2)) { + clSetKernelArg(m_kernelId, index, sizeof(value), &value); + } else { + float values[2] = {(float)value.x(), (float)value.y()}; + clSetKernelArg(m_kernelId, index, sizeof(values), values); + } +} + +inline void QCLKernel::setArg(int index, const QVector3D &value) +{ + float values[4] = {(float)value.x(), (float)value.y(), (float)value.z(), 1.0f}; + clSetKernelArg(m_kernelId, index, sizeof(values), values); +} + +inline void QCLKernel::setArg(int index, const QVector4D &value) +{ + if (sizeof(value) == (sizeof(float) * 4)) { + clSetKernelArg(m_kernelId, index, sizeof(value), &value); + } else { + float values[4] = {(float)value.x(), (float)value.y(), (float)value.z(), (float)value.w()}; + clSetKernelArg(m_kernelId, index, sizeof(values), values); + } +} + +inline void QCLKernel::setArg(int index, const QPoint &value) +{ + cl_int values[2] = {value.x(), value.y()}; + clSetKernelArg(m_kernelId, index, sizeof(values), values); +} + +inline void QCLKernel::setArg(int index, const QPointF &value) +{ + if (sizeof(value) == (sizeof(float) * 2)) { + clSetKernelArg(m_kernelId, index, sizeof(value), &value); + } else { + float values[2] = {(float)value.x(), (float)value.y()}; + clSetKernelArg(m_kernelId, index, sizeof(values), values); + } +} + +inline void QCLKernel::setArg(int index, const QCLMemoryObject &value) +{ + cl_mem id = value.memoryId(); + clSetKernelArg(m_kernelId, index, sizeof(id), &id); +} + +inline void QCLKernel::setArg(int index, const QCLVectorBase &value) +{ + cl_mem id = value.kernelArg(); + clSetKernelArg(m_kernelId, index, sizeof(id), &id); +} + +inline void QCLKernel::setArg(int index, const QCLSampler &value) +{ + cl_sampler id = value.samplerId(); + clSetKernelArg(m_kernelId, index, sizeof(id), &id); +} + +inline void QCLKernel::setArg(int index, const void *data, size_t size) +{ + clSetKernelArg(m_kernelId, index, size, data); +} + +#ifndef QT_NO_CONCURRENT + +// Convenience function definitions that make it possible to say +// QtConcurrent::run(kernel, ...) and have it do the right thing. +namespace QtConcurrent +{ + +inline QFuture run(QCLKernel &kernel) +{ + return kernel.runInThread(); +} +template +inline QFuture run(QCLKernel &kernel, const Arg1 &arg1) +{ + kernel.setArg(0, arg1); + return kernel.runInThread(); +} +template +inline QFuture run(QCLKernel &kernel, const Arg1 &arg1, const Arg2 &arg2) +{ + kernel.setArg(0, arg1); + kernel.setArg(1, arg2); + return kernel.runInThread(); +} +template +inline QFuture run(QCLKernel &kernel, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3) +{ + kernel.setArg(0, arg1); + kernel.setArg(1, arg2); + kernel.setArg(2, arg3); + return kernel.runInThread(); +} +template +inline QFuture run(QCLKernel &kernel, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4) +{ + kernel.setArg(0, arg1); + kernel.setArg(1, arg2); + kernel.setArg(2, arg3); + kernel.setArg(3, arg4); + return kernel.runInThread(); +} +template +inline QFuture run(QCLKernel &kernel, const Arg1 &arg1, const Arg2 &arg2, const Arg3 &arg3, const Arg4 &arg4, const Arg5 &arg5) +{ + kernel.setArg(0, arg1); + kernel.setArg(1, arg2); + kernel.setArg(2, arg3); + kernel.setArg(3, arg4); + kernel.setArg(4, arg5); + return kernel.runInThread(); +} + +} // namespace QtConcurrent + +#endif // QT_NO_CONCURRENT + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclmemoryobject.h b/Source/src/CL/qclmemoryobject.h new file mode 100644 index 0000000..7011da2 --- /dev/null +++ b/Source/src/CL/qclmemoryobject.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLMEMORYOBJECT_H +#define QCLMEMORYOBJECT_H + +#include "qclevent.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; + +class Q_CL_EXPORT QCLMemoryObject +{ +protected: + QCLMemoryObject(QCLContext *context = 0) : m_context(context), m_id(0) {} + QCLMemoryObject(QCLContext *context, cl_mem id) + : m_context(context), m_id(id) {} + ~QCLMemoryObject(); + +public: + enum Access + { + ReadWrite = 0x0001, + WriteOnly = 0x0002, + ReadOnly = 0x0004 + }; + + bool isNull() const { return m_id == 0; } + + cl_mem memoryId() const { return m_id; } + QCLContext *context() const { return m_context; } + + QCLMemoryObject::Access access() const; + cl_mem_flags flags() const; + void *hostPointer() const; + size_t size() const; + + void unmap(void *ptr); + QCLEvent unmapAsync + (void *ptr, const QCLEventList &after = QCLEventList()); + + bool operator==(const QCLMemoryObject &other) const; + bool operator!=(const QCLMemoryObject &other) const; + +protected: + void setId(QCLContext *context, cl_mem id); + +private: + QCLContext *m_context; + cl_mem m_id; + + Q_DISABLE_COPY(QCLMemoryObject) +}; + +inline QCLMemoryObject::~QCLMemoryObject() +{ + if (m_id) + clReleaseMemObject(m_id); +} + +inline bool QCLMemoryObject::operator==(const QCLMemoryObject &other) const +{ + return m_id == other.m_id; +} + +inline bool QCLMemoryObject::operator!=(const QCLMemoryObject &other) const +{ + return m_id != other.m_id; +} + +inline void QCLMemoryObject::setId(QCLContext *context, cl_mem id) +{ + m_context = context; + if (id) + clRetainMemObject(id); + if (m_id) + clReleaseMemObject(m_id); + m_id = id; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclplatform.h b/Source/src/CL/qclplatform.h new file mode 100644 index 0000000..1de70c0 --- /dev/null +++ b/Source/src/CL/qclplatform.h @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLPLATFORM_H +#define QCLPLATFORM_H + +#include "qclglobal.h" +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class Q_CL_EXPORT QCLPlatform +{ +public: + QCLPlatform() : m_id(0), m_flags(0) {} + QCLPlatform(cl_platform_id id) : m_id(id), m_flags(0) {} + + bool isNull() const { return m_id == 0; } + + bool isFullProfile() const; + bool isEmbeddedProfile() const; + + QString profile() const; + QString version() const; + QString name() const; + QString vendor() const; + QString extensionSuffix() const; + QStringList extensions() const; + + bool hasExtension(const char *name) const; + + enum VersionFlag + { + Version_1_0 = 0x0001, + Version_1_1 = 0x0002 + }; + Q_DECLARE_FLAGS(VersionFlags, VersionFlag) + + QCLPlatform::VersionFlags versionFlags() const; + + cl_platform_id platformId() const { return m_id; } + + static QList platforms(); + + bool operator==(const QCLPlatform &other) const; + bool operator!=(const QCLPlatform &other) const; + +private: + cl_platform_id m_id; + mutable int m_flags; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QCLPlatform::VersionFlags) + +inline bool QCLPlatform::operator==(const QCLPlatform &other) const +{ + return m_id == other.m_id; +} + +inline bool QCLPlatform::operator!=(const QCLPlatform &other) const +{ + return m_id != other.m_id; +} + +#ifndef QT_NO_DEBUG_STREAM +Q_CL_EXPORT QDebug operator<<(QDebug, const QCLPlatform &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclprogram.h b/Source/src/CL/qclprogram.h new file mode 100644 index 0000000..9bd2e06 --- /dev/null +++ b/Source/src/CL/qclprogram.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLPROGRAM_H +#define QCLPROGRAM_H + +#include "qcldevice.h" +#include "qclkernel.h" +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; + +class Q_CL_EXPORT QCLProgram +{ +public: + QCLProgram() : m_context(0), m_id(0) {} + QCLProgram(QCLContext *context, cl_program id) + : m_context(context), m_id(id) {} + QCLProgram(const QCLProgram &other); + ~QCLProgram(); + + QCLProgram &operator=(const QCLProgram &other); + + bool isNull() const { return m_id == 0; } + + cl_program programId() const { return m_id; } + QCLContext *context() const { return m_context; } + + bool build(const QString &options = QString()); + bool build(const QList &devices, const QString &options = QString()); + + QString log() const; + + QList devices() const; + QByteArray sourceCode() const; + QList binaries() const; + + QCLKernel createKernel(const char *name) const; + QCLKernel createKernel(const QByteArray &name) const; + QCLKernel createKernel(const QString &name) const; + + QList createKernels() const; + + static void unloadCompiler(); + + bool operator==(const QCLProgram &other) const; + bool operator!=(const QCLProgram &other) const; + +private: + QCLContext *m_context; + cl_program m_id; +}; + +inline bool QCLProgram::operator==(const QCLProgram &other) const +{ + return m_id == other.m_id; +} + +inline QCLProgram::QCLProgram(const QCLProgram &other) + : m_context(other.m_context), m_id(other.m_id) +{ + if (m_id) + clRetainProgram(m_id); +} + +inline QCLProgram::~QCLProgram() +{ + if (m_id) + clReleaseProgram(m_id); +} + +inline QCLProgram &QCLProgram::operator=(const QCLProgram &other) +{ + m_context = other.m_context; + if (other.m_id) + clRetainProgram(other.m_id); + if (m_id) + clReleaseProgram(m_id); + m_id = other.m_id; + return *this; +} + +inline bool QCLProgram::operator!=(const QCLProgram &other) const +{ + return m_id != other.m_id; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclsampler.h b/Source/src/CL/qclsampler.h new file mode 100644 index 0000000..7e597a8 --- /dev/null +++ b/Source/src/CL/qclsampler.h @@ -0,0 +1,137 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLSAMPLER_H +#define QCLSAMPLER_H + +#include "qclglobal.h" +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLSamplerPrivate; +class QCLContext; + +class Q_CL_EXPORT QCLSampler +{ +public: + QCLSampler() : m_context(0), m_id(0) {} + QCLSampler(QCLContext *context, cl_sampler id) + : m_context(context), m_id(id) {} + QCLSampler(const QCLSampler &other); + ~QCLSampler(); + + QCLSampler &operator=(const QCLSampler &other); + + enum AddressingMode + { + None = 0x1130, // CL_ADDRESS_NONE + ClampToEdge = 0x1131, // CL_ADDRESS_CLAMP_TO_EDGE + Clamp = 0x1132, // CL_ADDRESS_CLAMP + Repeat = 0x1133 // CL_ADDRESS_REPEAT + }; + + enum FilterMode + { + Nearest = 0x1140, // CL_FILTER_NEAREST + Linear = 0x1141 // CL_FILTER_LINEAR + }; + + bool isNull() const { return m_id == 0; } + + bool normalizedCoordinates() const; + QCLSampler::AddressingMode addressingMode() const; + QCLSampler::FilterMode filterMode() const; + + cl_sampler samplerId() const { return m_id; } + QCLContext *context() const { return m_context; } + + bool operator==(const QCLSampler &other) const; + bool operator!=(const QCLSampler &other) const; + +private: + QCLContext *m_context; + cl_sampler m_id; +}; + +inline QCLSampler::QCLSampler(const QCLSampler &other) + : m_context(other.m_context), m_id(other.m_id) +{ + if (m_id) + clRetainSampler(m_id); +} + +inline QCLSampler::~QCLSampler() +{ + if (m_id) + clReleaseSampler(m_id); +} + +inline QCLSampler &QCLSampler::operator=(const QCLSampler &other) +{ + m_context = other.m_context; + if (other.m_id) + clRetainSampler(other.m_id); + if (m_id) + clReleaseSampler(m_id); + m_id = other.m_id; + return *this; +} + +inline bool QCLSampler::operator==(const QCLSampler &other) const +{ + return m_id == other.m_id; +} + +inline bool QCLSampler::operator!=(const QCLSampler &other) const +{ + return m_id != other.m_id; +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qcluserevent.h b/Source/src/CL/qcluserevent.h new file mode 100644 index 0000000..73d7b58 --- /dev/null +++ b/Source/src/CL/qcluserevent.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLUSEREVENT_H +#define QCLUSEREVENT_H + +#include "qclevent.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; + +class Q_CL_EXPORT QCLUserEvent : public QCLEvent +{ +public: + QCLUserEvent() : QCLEvent() {} + QCLUserEvent(cl_event id); + QCLUserEvent(const QCLEvent &other); + + QCLUserEvent &operator=(const QCLEvent &other); + + void setFinished(); + void setStatus(cl_int status); + +private: + void validateEvent(); + + // Used by QCLContext::createUserEvent() to avoid + // the overhead of validateEvent(). + QCLUserEvent(cl_event id, bool dummy) + : QCLEvent(id) { Q_UNUSED(dummy); } + + friend class QCLContext; +}; + +inline void QCLUserEvent::setFinished() +{ + setStatus(CL_COMPLETE); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclvector.h b/Source/src/CL/qclvector.h new file mode 100644 index 0000000..1864e85 --- /dev/null +++ b/Source/src/CL/qclvector.h @@ -0,0 +1,228 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLVECTOR_H +#define QCLVECTOR_H + +#include "qclbuffer.h" +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLContext; +class QCLKernel; +class QCLVectorBasePrivate; + +class Q_CL_EXPORT QCLVectorBase +{ +protected: + QCLVectorBase(size_t elemSize); + QCLVectorBase(size_t elemSize, const QCLVectorBase &other); + ~QCLVectorBase(); + + QCLVectorBasePrivate *d_ptr; + size_t m_elemSize; + size_t m_size; + mutable void *m_mapped; + + void assign(const QCLVectorBase &other); + + void create(QCLContext *context, int size, QCLMemoryObject::Access access); + void release(); + + void map(); + void unmap() const; + + void read(void *data, int count, int offset); + void write(const void *data, int count, int offset); + + cl_mem memoryId() const; + QCLContext *context() const; + + cl_mem kernelArg() const; + + friend class QCLKernel; +}; + +template +class QCLVector : public QCLVectorBase +{ +public: + QCLVector(); + QCLVector(const QCLVector &other); + ~QCLVector(); + + QCLVector &operator=(const QCLVector &other); + + bool isNull() const; + + void release(); + + inline bool isEmpty() const { return m_size == 0; } + inline int size() const { return m_size; } + + T &operator[](int index); + const T &operator[](int index) const; + + void read(T *data, int count, int offset = 0); + void write(const T *data, int count, int offset = 0); + void write(const QVector &data, int offset = 0); + + QCLContext *context() const; + QCLBuffer toBuffer() const; + +private: + QCLVector(QCLContext *context, int size, QCLMemoryObject::Access access); + + friend class QCLContext; +}; + +template +Q_INLINE_TEMPLATE QCLVector::QCLVector() + : QCLVectorBase(sizeof(T)) {} + +template +Q_INLINE_TEMPLATE QCLVector::QCLVector + (QCLContext *context, int size, QCLMemoryObject::Access access) + : QCLVectorBase(sizeof(T)) +{ + QCLVectorBase::create(context, size, access); +} + +template +Q_INLINE_TEMPLATE QCLVector::QCLVector(const QCLVector &other) + : QCLVectorBase(sizeof(T), other) +{ +} + +template +Q_INLINE_TEMPLATE QCLVector::~QCLVector() {} + +template +QCLVector &QCLVector::operator=(const QCLVector &other) +{ + assign(other); + return *this; +} + +template +Q_INLINE_TEMPLATE bool QCLVector::isNull() const +{ + return d_ptr == 0; +} + +template +Q_INLINE_TEMPLATE void QCLVector::release() +{ + QCLVectorBase::release(); +} + +template +Q_INLINE_TEMPLATE T &QCLVector::operator[](int index) +{ + Q_ASSERT_X(index >= 0 && index < int(m_size), "QCLVector::operator[]", + "index out of range"); + if (!m_mapped) + map(); + return (reinterpret_cast(m_mapped))[index]; +} + +template +Q_INLINE_TEMPLATE const T &QCLVector::operator[](int index) const +{ + Q_ASSERT_X(index >= 0 && index < int(m_size), "QCLVector::operator[]", + "index out of range"); + if (!m_mapped) + const_cast *>(this)->map(); + return (reinterpret_cast(m_mapped))[index]; +} + +template +Q_INLINE_TEMPLATE void QCLVector::write + (const T *data, int count, int offset) +{ + Q_ASSERT(count >= 0 && offset >= 0 && (offset + count) <= int(m_size)); + QCLVectorBase::write(data, count * sizeof(T), offset * sizeof(T)); +} + +template +Q_INLINE_TEMPLATE void QCLVector::read + (T *data, int count, int offset) +{ + Q_ASSERT(count >= 0 && offset >= 0 && (offset + count) <= int(m_size)); + QCLVectorBase::read(data, count * sizeof(T), offset * sizeof(T)); +} + +template +Q_INLINE_TEMPLATE void QCLVector::write + (const QVector &data, int offset) +{ + write(data.constData(), data.size(), offset); +} + +template +Q_INLINE_TEMPLATE QCLContext *QCLVector::context() const +{ + return QCLVectorBase::context(); +} + +template +Q_INLINE_TEMPLATE QCLBuffer QCLVector::toBuffer() const +{ + cl_mem id = QCLVectorBase::memoryId(); + if (id) { + clRetainMemObject(id); + return QCLBuffer(context(), id); + } else { + return QCLBuffer(); + } +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/CL/qclworksize.h b/Source/src/CL/qclworksize.h new file mode 100644 index 0000000..d13bfd5 --- /dev/null +++ b/Source/src/CL/qclworksize.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenCL module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCLWORKSIZE_H +#define QCLWORKSIZE_H + +#include "qclglobal.h" +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(CL) + +class QCLDevice; + +class Q_CL_EXPORT QCLWorkSize +{ +public: + QCLWorkSize() + : m_dim(1) { m_sizes[0] = 1; m_sizes[1] = 1; m_sizes[2] = 1; } + QCLWorkSize(size_t size) + : m_dim(1) { m_sizes[0] = size; m_sizes[1] = 1; m_sizes[2] = 1; } + QCLWorkSize(size_t width, size_t height) + : m_dim(2) { m_sizes[0] = width; m_sizes[1] = height; m_sizes[2] = 1; } + QCLWorkSize(const QSize &size) + : m_dim(2) { m_sizes[0] = size.width(); m_sizes[1] = size.height(); m_sizes[2] = 1; } + QCLWorkSize(size_t width, size_t height, size_t depth) + : m_dim(3) + { m_sizes[0] = width; m_sizes[1] = height; m_sizes[2] = depth; } + + size_t dimensions() const { return m_dim; } + size_t width() const { return m_sizes[0]; } + size_t height() const { return m_sizes[1]; } + size_t depth() const { return m_sizes[2]; } + + const size_t *sizes() const { return m_sizes; } + + bool operator==(const QCLWorkSize &other) const; + bool operator!=(const QCLWorkSize &other) const; + + QCLWorkSize toLocalWorkSize + (const QCLWorkSize &maxWorkItemSize, size_t maxItemsPerGroup) const; + QCLWorkSize toLocalWorkSize(const QCLDevice &device) const; + + QCLWorkSize roundTo(const QCLWorkSize &size) const; + + QString toString() const; + static QCLWorkSize fromString(const QString &str); + +private: + size_t m_dim; + size_t m_sizes[3]; +}; + +Q_DECLARE_TYPEINFO(QCLWorkSize, Q_MOVABLE_TYPE); + +inline bool QCLWorkSize::operator==(const QCLWorkSize &other) const +{ + return m_dim == other.m_dim && + m_sizes[0] == other.m_sizes[0] && + m_sizes[1] == other.m_sizes[1] && + m_sizes[2] == other.m_sizes[2]; +} + +inline bool QCLWorkSize::operator!=(const QCLWorkSize &other) const +{ + return m_dim != other.m_dim || + m_sizes[0] != other.m_sizes[0] || + m_sizes[1] != other.m_sizes[1] || + m_sizes[2] != other.m_sizes[2]; +} + +#ifndef QT_NO_DATASTREAM +Q_CL_EXPORT QDataStream &operator<<(QDataStream &, const QCLWorkSize &); +Q_CL_EXPORT QDataStream &operator>>(QDataStream &, QCLWorkSize &); +#endif + +#ifndef QT_NO_DEBUG_STREAM +Q_CL_EXPORT QDebug operator<<(QDebug, const QCLWorkSize &); +#endif + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif diff --git a/Source/src/DataEngine/cusdr_audioReceiver.cpp b/Source/src/DataEngine/cusdr_audioReceiver.cpp new file mode 100644 index 0000000..e1bbeaf --- /dev/null +++ b/Source/src/DataEngine/cusdr_audioReceiver.cpp @@ -0,0 +1,116 @@ +/** +* @file audioReceiver.cpp +* @brief audio receiver class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-10-02 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_AUDIO_RECEIVER + +#include "cusdr_audioReceiver.h" + + +AudioReceiver::AudioReceiver(THPSDRParameter *ioData) + : QObject() + , set(Settings::instance()) + , io(ioData) + , m_client(0) +{ +} + +AudioReceiver::~AudioReceiver() { + +} + +void AudioReceiver::displayAudioRcvrSocketError(QAbstractSocket::SocketError error) { + + AUDIO_RECEIVER << "audio client socket error:" << error; +} + +void AudioReceiver::initClient() { + + quint16 port = (quint16) (set->getAudioPort() + (io->audio_rx * 2)); + + QUdpSocket *socket = new QUdpSocket(); + socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); + + if (socket->bind(port, QUdpSocket::ReuseAddressHint | QUdpSocket::ShareAddress)) { + + CHECKED_CONNECT( + socket, + SIGNAL(error(QAbstractSocket::SocketError)), + this, + SLOT(displayAudioRcvrSocketError(QAbstractSocket::SocketError))); + + CHECKED_CONNECT( + socket, + SIGNAL(readyRead()), + this, + SLOT(readPendingAudioRcvrData())); + + clientConnections.append(socket); + + AUDIO_RECEIVER << "client socket binding successful."; + m_message = tr("[server]: listening for rx %1 audio on port %2."); + emit messageEvent(m_message.arg(io->audio_rx).arg(port)); + + //m_dataEngine->clientConnected = true; + // need to implement connection in dataEngine !!!! + emit clientConnectedEvent(true); + //rcveIQ_toggle = false; + } + else { + + m_message = tr("[server]: bind socket failed for socket on port %1."); + emit messageEvent(m_message.arg(port)); + } +} + +void AudioReceiver::readPendingAudioRcvrData() { + + QUdpSocket *socket = qobject_cast(sender()); + + while (socket->hasPendingDatagrams()) { + + m_datagram.resize(socket->pendingDatagramSize()); + + if (socket->readDatagram(m_datagram.data(), m_datagram.size()) < 0) { + + AUDIO_RECEIVER << "read client" << m_client << "socket failed."; + if (io->rcveIQ_toggle) { // toggles the rcveIQ signal + + emit rcveIQEvent(this, 2); + io->rcveIQ_toggle = false; + } + } + else { + + io->au_queue.enqueue(m_datagram); + + if (!io->rcveIQ_toggle) { // toggles the rcveIQ signal + + emit rcveIQEvent(this, 1); + io->rcveIQ_toggle = true; + } + } + } +} diff --git a/Source/src/DataEngine/cusdr_audioReceiver.h b/Source/src/DataEngine/cusdr_audioReceiver.h new file mode 100644 index 0000000..4d6f8f5 --- /dev/null +++ b/Source/src/DataEngine/cusdr_audioReceiver.h @@ -0,0 +1,87 @@ +/** +* @file audioReceiver.h +* @brief audio receiver header file +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-10-02 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_AUDIORECEIVER_H +#define _CUSDR_AUDIORECEIVER_H + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_settings.h" + +#ifdef LOG_AUDIO_RECEIVER +# define AUDIO_RECEIVER qDebug().nospace() << "AudioReceiver::\t" +#else +# define AUDIO_RECEIVER nullDebug() +#endif + + + +class AudioReceiver : public QObject { + + Q_OBJECT + +public: + AudioReceiver(THPSDRParameter *ioData = 0); + ~AudioReceiver(); + + //int id; + +public slots: + void initClient(); + +private: + Settings* set; + QMutex m_mutex; + + QList clientConnections; + QString m_message; + QByteArray m_datagram; + + THPSDRParameter *io; + + int m_client; + +private slots: + void displayAudioRcvrSocketError(QAbstractSocket::SocketError error); + void readPendingAudioRcvrData(); + +signals: + void messageEvent(QString message); + void rcveIQEvent(QObject *sender, int value); + void outputBufferEvent(unsigned char* outbuffer); + void clientConnectedEvent(bool value); + void newData(); + void newAudioData(); +}; + +#endif // _CUSDR_AUDIORECEIVER_H diff --git a/Source/src/DataEngine/cusdr_chirpProcessor.cpp b/Source/src/DataEngine/cusdr_chirpProcessor.cpp new file mode 100644 index 0000000..ed84a0d --- /dev/null +++ b/Source/src/DataEngine/cusdr_chirpProcessor.cpp @@ -0,0 +1,576 @@ +/** +* @file cusdr_chirpProcessor.cpp +* @brief chirp data processor class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-09-22 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_CHIRP_PROCESSOR + +#include "cusdr_chirpProcessor.h" + +ChirpProcessor::ChirpProcessor(THPSDRParameter *ioData) + : QObject() + , set(Settings::instance()) + , io(ioData) + , m_stopped(false) + , m_specMax(0.0f) + , m_specMin(0.0f) + , m_sampleRate(set->getSampleRate()) + , m_downRate(set->getChirpDownSampleRate()) + , m_specAvgLength(1) + , m_filterLowerFrequency((float)set->getChirpFilterLowerFrequency()) + , m_filterUpperFrequency((float)set->getChirpFilterUpperFrequency()) + , m_switch(false) + , m_showChirpFFT(false) + , m_chirpBufferLength(set->getChirpBufferLength()) + , m_chirpSidebandFactor(1.0f) +{ + /*m_QCPXin = initQCPX(BUFFERSIZE); + m_temp0 = initQCPX(BUFFERSIZE); + m_temp2 = initQCPX(BUFFERSIZE/m_downRate); + + m_temp1 = initQCPX(FULL_BUFFERSIZE); + m_temp3 = initQCPX(FULL_BUFFERSIZE);*/ + + /* + m_cpxIn = mallocCPX(BUFFERSIZE); + m_tmp0 = mallocCPX(BUFFERSIZE); + m_tmp2 = mallocCPX(BUFFERSIZE/m_downRate); + + m_cpxInFilt = mallocCPX(FULL_BUFFERSIZE); + m_cpxRxFFT = mallocCPX(FULL_BUFFERSIZE); + m_tmp1 = mallocCPX(FULL_BUFFERSIZE); + m_tmp3 = mallocCPX(FULL_BUFFERSIZE); + m_cpxChirpIn = mallocCPX(FULL_BUFFERSIZE); + m_cpxChirpOut = mallocCPX(FULL_BUFFERSIZE); + m_cpxChirpTmp = mallocCPX(FULL_BUFFERSIZE); + m_cpxOut = mallocCPX(FULL_BUFFERSIZE); + */ + m_cpxIn.resize(BUFFERSIZE); + m_tmp0.resize(BUFFERSIZE); + m_tmp2.resize(BUFFERSIZE/m_downRate); + + m_cpxInFilt.resize(FULL_BUFFERSIZE); + m_cpxRxFFT.resize(FULL_BUFFERSIZE); + m_tmp1.resize(FULL_BUFFERSIZE); + m_tmp3.resize(FULL_BUFFERSIZE); + m_cpxChirpIn.resize(FULL_BUFFERSIZE); + m_cpxChirpOut.resize(FULL_BUFFERSIZE); + m_cpxChirpTmp.resize(FULL_BUFFERSIZE); + m_cpxOut.resize(FULL_BUFFERSIZE); + + + /* + memset(m_cpxIn, 0, BUFFERSIZE * sizeof(CPX)); + memset(m_tmp0, 0, BUFFERSIZE * sizeof(CPX)); + memset(m_tmp2, 0, (BUFFERSIZE/4) * sizeof(CPX)); + + memset(m_cpxInFilt, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_cpxRxFFT, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_tmp1, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_tmp3, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_cpxOut, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_cpxChirpIn, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_cpxChirpOut, 0, FULL_BUFFERSIZE * sizeof(CPX)); + memset(m_cpxChirpTmp, 0, FULL_BUFFERSIZE * sizeof(CPX)); + */ + + // FFTs by fftw + m_chirpFFT = new QFFT(FULL_BUFFERSIZE); + m_matchedFFT = new QFFT(FULL_BUFFERSIZE); + + // FIR band pass filter + //m_filter = new QFilter(this, FULL_BUFFERSIZE, 2); + // 2 = FIR Bandpass, 5 = Bartlett window + m_filter = new QFilter(this, BUFFERSIZE, 2, 2); + + // set the BPF + m_filter->setFilter(500.0f, 2500.0f); + m_filter->setStreamMode(true); + + setupConnections(); +} + +ChirpProcessor::~ChirpProcessor() { + + while (average_queue.length() > 0) + average_queue.dequeue(); + + /* + freeCPX(m_cpxIn); + freeCPX(m_cpxOut); + freeCPX(m_cpxInFilt); + freeCPX(m_cpxRxFFT); + freeCPX(m_cpxChirpIn); + freeCPX(m_cpxChirpOut); + freeCPX(m_tmp0); + freeCPX(m_tmp1); + */ + + /* + delete m_cpxIn; + delete m_cpxOut; + delete m_cpxInFilt; + delete m_cpxRxFFT; + delete m_cpxChirpIn; + delete m_cpxChirpOut; + delete m_tmp0; + delete m_tmp1; + */ + + delete m_chirpFFT; + delete m_matchedFFT; +} + +void ChirpProcessor::stop() { + + m_stopped = true; +} + +void ChirpProcessor::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(samplingRateChanged(QObject *, int))); + + CHECKED_CONNECT_OPT( + set, + SIGNAL(chirpFilterLowerFrequencyChanged(int)), + this, + SLOT(setFilterLowerFrequency(int)), + Qt::DirectConnection); + + CHECKED_CONNECT_OPT( + set, + SIGNAL(chirpFilterUpperFrequencyChanged(int)), + this, + SLOT(setFilterUpperFrequency(int)), + Qt::DirectConnection); + + CHECKED_CONNECT_OPT( + set, + SIGNAL(chirpAvgLengthChanged(int)), + this, + SLOT(setDistSpectrumAvgLength(int)), + Qt::DirectConnection); + + CHECKED_CONNECT_OPT( + set, + SIGNAL(chirpFFTShowChanged(bool)), + this, + SLOT(setChirpFFTShow(bool)), + Qt::DirectConnection); + + CHECKED_CONNECT_OPT( + set, + SIGNAL(chirpSidebandChanged(bool)), + this, + SLOT(setChirpSideband(bool)), + Qt::DirectConnection); +} + +int ChirpProcessor::setSpectrumBufferSize(int size) { + + int i = 1; + while (i < size) i *= 2; + + return i; +} + +void ChirpProcessor::processChirpData() { + + forever { + + //matchedFilter(io->chirp_queue.dequeue()); + matchedFilterFIRFilter(io->chirp_queue.dequeue()); + + m_mutex.lock(); + if (m_stopped) { + m_stopped = false; + m_mutex.unlock(); + break; + } + m_mutex.unlock(); + } +} + +void ChirpProcessor::matchedFilterFIRFilter(QList data) { + + int dataLength = data.length(); + int dataIdx = 0; + int buffer = 0; + int newsize = (int)(BUFFERSIZE / m_downRate); + + CHIRP_PROCESSOR_DEBUG << "start matched filter - samples:" << dataLength; + + // filtering to 2kHz by constant-overlap-add (COLA) + while (dataIdx < dataLength) { + + dataIdx = 2 * buffer * BUFFERSIZE; + for (int i = 0; i < 2 * BUFFERSIZE; i += 2) { + + if (dataIdx + i + 1 < dataLength) { + + m_cpxIn[i/2].re = data.at(dataIdx + i); + m_cpxIn[i/2].im = data.at(dataIdx + i + 1); + } + else { + + dataIdx = dataLength; + break; + } + } + + // BPF 2.5 kHz + m_filter->ProcessFilter(m_cpxIn, m_tmp0, BUFFERSIZE); + + // decimate by 4 + decimate(m_tmp0, m_tmp2, BUFFERSIZE, m_downRate); + + for (int i = 0; i < newsize; i++) { + + m_cpxInFilt[buffer * newsize + i].re = m_tmp2[i].re; + m_cpxInFilt[buffer * newsize + i].im = m_tmp2[i].im; + } + buffer++; + } + + // Due to the COLA method the filter output gets shifet by BUFFERSIZE/2 bytes. + // In order to have a buffer in full chirp length, we save the last newsize/2 bytes + // (due to decimation by downrate) and add it to the beginning of the newbuffer. + for (int i = 0; i < FULL_BUFFERSIZE - newsize/2; i++) { + + if (i < newsize/2) { + + m_cpxInFilt[i].re = m_tmp3[i].re; + m_cpxInFilt[i].im = m_tmp3[i].im; + } + else { + + m_cpxInFilt[i].re = m_cpxInFilt[i + newsize/2].re; + m_cpxInFilt[i].im = m_cpxInFilt[i + newsize/2].im; + } + + } + + // save the last buffer + for (int i = 0; i < newsize/2; i++) { + + m_tmp3[i].re = m_tmp2[i].re; + m_tmp3[i].im = m_tmp2[i].im; + } + + // map rx signal to the frequency domain + m_matchedFFT->DoFFTWForward(m_cpxInFilt, m_cpxRxFFT, FULL_BUFFERSIZE); + + // multiply the chirp signal with the complex conjugate of the received signal + for (int i = 0; i < FULL_BUFFERSIZE; i++) { + + // f * ~g + m_tmp1[i].re = (m_cpxChirpOut[i].re * m_cpxRxFFT[i].re) + (m_cpxChirpOut[i].im * m_cpxRxFFT[i].im); + m_tmp1[i].im = (m_cpxChirpOut[i].im * m_cpxRxFFT[i].re) - (m_cpxChirpOut[i].re * m_cpxRxFFT[i].im); + + // ~f * g + //m_tmp1[i].re = (m_cpxRxFFT[i].re * m_cpxChirpOut[i].re) + (m_cpxRxFFT[i].im * m_cpxChirpOut[i].im); + //m_tmp1[i].im = (m_cpxRxFFT[i].im * m_cpxChirpOut[i].re) - (m_cpxRxFFT[i].re * m_cpxChirpOut[i].im); + + // f * g + //m_tmp1[i].re = (m_cpxChirpOut[i].re * m_cpxRxFFT[i].re) - (m_cpxChirpOut[i].im * m_cpxRxFFT[i].im); + //m_tmp1[i].im = (m_cpxChirpOut[i].re * m_cpxRxFFT[i].im) + (m_cpxChirpOut[i].im * m_cpxRxFFT[i].re); + } + + // map back to time domain + m_matchedFFT->DoFFTWInverse(m_tmp1, m_cpxOut, FULL_BUFFERSIZE); + + float max = -1000; + float min = 1000; + float mean = 0.0f; + float oneOverNorm = 1.0f / FULL_BUFFERSIZE; + + for (int i = 0; i < FULL_BUFFERSIZE; i++) { + + if (!m_showChirpFFT) { + + m_spectrumBufferFull[i] = (float)(10.0 * log10(MagCPX(ScaleCPX(m_cpxOut[i], oneOverNorm)) + 1.5E-45)); + + if (m_spectrumBufferFull[i] > max) max = m_spectrumBufferFull[i]; + if (m_spectrumBufferFull[i] < min) min = m_spectrumBufferFull[i]; + mean += m_spectrumBufferFull[i]; + } + else { + //m_spectrumBufferFull[i] = (float)(10.0 * log10(SqrMagCPX(m_tmp1[i]) + 1.5E-45)); + //m_spectrumBufferFull[i] = (float)(10.0 * log10(SqrMagCPX(ScaleCPX(m_tmp1[i], oneOverNorm)) + 1.5E-45)); + m_spectrumBufferFull[i] = (float)(10.0 * log10(MagCPX(m_cpxRxFFT[i]) + 1.5E-45)); + //m_spectrumBufferFull[i] = (float)(10.0 * log10(SqrMagCPX(m_cpxChirpOut[i]) + 1.5E-45) + 50.0f); + //m_spectrumBufferFull[i] = (float)(10.0 * log10(SqrMagCPX(SubCPX(m_cpxChirpOut[i], m_cpxRxFFT[i])) + 1.5E-45) + 50.0f); + //m_spectrumBufferFull[i] = (float)(10.0 * log10(MagCPX(m_cpxInFilt[i]) + 1.5E-45)); + //m_spectrumBufferFull[i] = (float)(10.0 * log10(MagCPX(m_cpxIn[i]) + 1.5E-45)); + } + } + + mean *= 1.0f/FULL_BUFFERSIZE; + CHIRP_PROCESSOR_DEBUG << "dist min" << min << "max" << max << "mean" << mean; + CHIRP_PROCESSOR_DEBUG << "dist delta" << max - mean; + + // we take the first half of the matched filter output to display + memcpy(m_spectrumBuffer, m_spectrumBufferFull, (FULL_BUFFERSIZE/2) * sizeof(float)); + + // we take the full length for the frequency spectrum, + // because we want to see positive as well as negative spectras + if (m_showChirpFFT) { + + int topsize = FULL_BUFFERSIZE - 1; + + // reorder the RX FFT buffer + for (int i = 0; i < FULL_BUFFERSIZE/2; i++) { + + m_fftSpectrumBuffer[topsize - i] = m_spectrumBufferFull[i + FULL_BUFFERSIZE/2]; + m_fftSpectrumBuffer[FULL_BUFFERSIZE/2 - i] = m_spectrumBufferFull[i]; + } + } + setSpectras(m_spectrumBuffer, m_fftSpectrumBuffer); +} + +void ChirpProcessor::setSpectras(const float *distance, const float *chirpfft) { + + if (m_showChirpFFT) + set->setChirpSpectrumBuffer(m_sampleRate/m_downRate, FULL_BUFFERSIZE, chirpfft); + + else { + if (m_specAvgLength > 1) + //spectrumAveraging(FULL_BUFFERSIZE, distance); + spectrumAveraging(FULL_BUFFERSIZE/2, distance); + else + //set->setChirpSpectrumBuffer(m_sampleRate/m_downRate, FULL_BUFFERSIZE, distance); + set->setChirpSpectrumBuffer(m_sampleRate/m_downRate, FULL_BUFFERSIZE/2, distance); + } +} + +void ChirpProcessor::spectrumAveraging(qint64 length, const float *buffer) { + + QVector m_specBuf(length); + + m_mutex.lock(); + + memcpy( + (float *) m_specBuf.data(), + (float *) &buffer[0], + length * sizeof(float)); + + average_queue.enqueue(m_specBuf); + + float specMax = 0.0f; + float specMin = 0.0f; + float specMean = 0.0f; + if (average_queue.size() <= m_specAvgLength) { + + for (int i = 0; i < length; i++) { + + m_tmpBuf[i] += average_queue.last().data()[i]; + m_outBuf[i] = m_tmpBuf[i] * (1.0f/average_queue.size()); + specMean += m_outBuf[i]; + + if (m_outBuf[i] > specMax) specMax = m_outBuf[i]; + if (m_outBuf[i] < specMin) specMin = m_outBuf[i]; + } + + m_mutex.unlock(); + + specMean *= 1.0f/FULL_BUFFERSIZE; + CHIRP_PROCESSOR_DEBUG << "distance spectrum averaging size" << average_queue.size(); + CHIRP_PROCESSOR_DEBUG << "specMin =" << specMin << "specMax =" << specMax; + CHIRP_PROCESSOR_DEBUG << "distance spectrum mean value" << specMean; + set->setChirpSpectrumBuffer(m_sampleRate, FULL_BUFFERSIZE, m_outBuf); + return; + } + + for (int i = 0; i < length; i++) { + + m_tmpBuf[i] -= average_queue.first().at(i); + m_tmpBuf[i] += average_queue.last().at(i); + m_outBuf[i] = m_tmpBuf[i] * m_scale; + specMean += m_outBuf[i]; + } + + //set->setChirpSpectrumBuffer(m_sampleRate, FULL_BUFFERSIZE, m_outBuf); + set->setChirpSpectrumBuffer(m_sampleRate, FULL_BUFFERSIZE/2, m_outBuf); + average_queue.dequeue(); + + m_mutex.unlock(); +} + +void ChirpProcessor::generateLocalChirp() { + + const int sampleRate = m_sampleRate / m_downRate; + + //memset(m_cpxChirpIn, 0, FULL_BUFFERSIZE * sizeof(CPX)); + //memset(m_cpxChirpOut, 0, FULL_BUFFERSIZE * sizeof(CPX)); + m_cpxChirpIn.resize(FULL_BUFFERSIZE); + m_cpxChirpOut.resize(FULL_BUFFERSIZE); + + + qreal time = set->getChirpBufferDurationUs() / 1.0E6; + qint64 length = (qint64)(sampleRate * time); + + qreal a = ONEPI * (set->getUpperChirpFreq() - set->getLowerChirpFreq()) / time; + qreal b = TWOPI * set->getLowerChirpFreq(); + + for (int i = 0; i < length; i++) { + + // forward chirp + qreal t = (qreal)(1.0f * i/length); + // backward chirp + //qreal t = (qreal)(1.0f * (length-i)/length); + + // complex chirp signal + m_cpxChirpIn[i].re = qSin(a * t * t + b * t); + m_cpxChirpIn[i].im = qCos(a * t * t + b * t); + + //m_cpxChirpTmp[i].re = qSin(a * t * t + b * t); + //m_cpxChirpTmp[i].im = qCos(a * t * t + b * t); + + //m_cpxChirpIn[i].re = qCos(a * t * t + b * t); + //m_cpxChirpIn[i].im = qSin(a * t * t + b * t); + + //m_cpxChirpIn[i].re = qSin(a * t * t + b * t); + //m_cpxChirpIn[i].im = -qCos(a * t * t + b * t); + } + + //m_specBufferSize = setSpectrumBufferSize(length); + + // BPF 2.5 kHz + //m_filter->ProcessFilter(m_cpxChirpTmp, m_cpxChirpIn, FULL_BUFFERSIZE); + + // transform chirp signal to frequency domain + m_chirpFFT->DoFFTWForward(m_cpxChirpIn, m_cpxChirpOut, FULL_BUFFERSIZE); + + float dur = set->getChirpBufferDurationUs() / 1000.0f; + + CHIRP_PROCESSOR_DEBUG << "chirp buffer changed:"; + CHIRP_PROCESSOR_DEBUG << " bufferLength" << length; + //CHIRP_PROCESSOR_DEBUG << " spectrum buffer size" << m_specBufferSize; + CHIRP_PROCESSOR_DEBUG << " start frequency (Hz)" << set->getLowerChirpFreq(); + CHIRP_PROCESSOR_DEBUG << " end frequency (Hz)" << set->getUpperChirpFreq(); + CHIRP_PROCESSOR_DEBUG << " duration (ms)" << dur; +} + +//void ChirpProcessor::decimate(CPX *in, CPX *out, int size, int downrate) { +void ChirpProcessor::decimate(const CPX &in, CPX &out, int size, int downrate) { + + int newsize = size / downrate; + + //memset(out, 0, newsize * sizeof(CPX)); + out.resize(newsize); + + for (int j = 0; j < newsize; j++) { + for (int k = 0; k < downrate; k++) { + + if (j * downrate + k < size) { + + /*out[j].re += m_tmpDec[j * downrate + k].re; + out[j].im += m_tmpDec[j * downrate + k].im;*/ + out[j].re += in[j * downrate + k].re; + out[j].im += in[j * downrate + k].im; + } + } + } +} + +//void ChirpProcessor::decimate(QList data, CPX *out, int downrate) { +void ChirpProcessor::decimate(const QList &data, CPX &out, int downrate) { + + //memset(out, 0, 16 * BUFFER_SIZE * sizeof(CPX)); + out.resize(16 * BUFFER_SIZE); + + for (int j = 0; j < data.length()/4; j += 2) { + for (int k = 0; k < downrate; k++) { + + if (j * downrate + 2*k < data.length()) { + + out[j/2].re += data.at(j * downrate + 2*k); + out[j/2].im += data.at(j * downrate + 2*k + 1); + } + } + } +} + +void ChirpProcessor::samplingRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; +} + +void ChirpProcessor::setDistSpectrumAvgLength(int value) { + + m_mutex.lock(); + + //for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) m_tmpBuf[i] = 0.0f; + memset(m_tmpBuf, 0, FULL_BUFFERSIZE * sizeof(float)); + + while (!average_queue.isEmpty()) + average_queue.dequeue(); + + m_specAvgLength = value; + + if (m_specAvgLength > 0) + m_scale = 1.0f / m_specAvgLength; + else + m_scale = 1.0f; + + m_mutex.unlock(); +} + +void ChirpProcessor::setChirpFFTShow(bool value) { + + m_showChirpFFT = value; + +} + +void ChirpProcessor::setChirpSideband(bool value) { + + if (value) + m_chirpSidebandFactor = 1.0f; + else + m_chirpSidebandFactor = -1.0f; + + generateLocalChirp(); +} + +void ChirpProcessor::setFilterLowerFrequency(int value) { + + if ((int)m_filterLowerFrequency == value) return; + m_filterLowerFrequency = 1.0f * value; + + m_filter->setFilter(m_filterLowerFrequency, m_filterUpperFrequency); +} + +void ChirpProcessor::setFilterUpperFrequency(int value) { + + if ((int)m_filterUpperFrequency == value) return; + m_filterUpperFrequency = 1.0f * value; + + m_filter->setFilter(m_filterLowerFrequency, m_filterUpperFrequency); +} diff --git a/Source/src/DataEngine/cusdr_chirpProcessor.h b/Source/src/DataEngine/cusdr_chirpProcessor.h new file mode 100644 index 0000000..26fefc6 --- /dev/null +++ b/Source/src/DataEngine/cusdr_chirpProcessor.h @@ -0,0 +1,145 @@ +/** +* @file cusdr_chirpProcessor.h +* @brief chirp processor header file +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-09-22 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_CHIRPPROCESSOR_H +#define _CUSDR_CHIRPPROCESSOR_H + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_settings.h" +#include "QtDSP/qtdsp_qComplex.h" +#include "QtDSP/qtdsp_filter.h" +#include "QtDSP/qtdsp_fft.h" + +#ifdef LOG_CHIRP_PROCESSOR +# define CHIRP_PROCESSOR_DEBUG qDebug().nospace() << "ChirpProcessor::\t" +#else +# define CHIRP_PROCESSOR_DEBUG nullDebug() +#endif + + +#define FULL_BUFFERSIZE 16384//65536 +#define HALF_BUFFERSIZE 32768 +#define BUFFERSIZE 2048 + +class ChirpProcessor : public QObject { + + Q_OBJECT + +public: + ChirpProcessor(THPSDRParameter *ioData = 0); + ~ChirpProcessor(); + +public slots: + void stop(); + void processChirpData(); + void generateLocalChirp(); + +private slots: + void matchedFilterFIRFilter(QList data); + void samplingRateChanged(QObject *sender, int value); + void setSpectras(const float *distance, const float *chirpfft); + void setDistSpectrumAvgLength(int value); + void setChirpFFTShow(bool value); + void setChirpSideband(bool value); + void setFilterLowerFrequency(int value); + void setFilterUpperFrequency(int value); + +private: + Settings *set; + + QMutex m_mutex; + QString m_message; + + QFFT *m_chirpFFT; + QFFT *m_matchedFFT; + QFilter *m_filter; + + CPX m_tmp0; + CPX m_tmp1; + CPX m_tmp2; + CPX m_tmp3; + CPX m_tmpDec; + + CPX m_cpxRxFFT; + CPX m_cpxChirpIn; + CPX m_cpxChirpTmp; + CPX m_cpxChirpOut; + CPX m_cpxIn; + CPX m_cpxInFilt; + CPX m_cpxOut; + + THPSDRParameter *io; + + QQueue > average_queue; + + float m_tmpBuf[FULL_BUFFERSIZE]; + float m_outBuf[FULL_BUFFERSIZE]; + float m_spectrumBuffer[FULL_BUFFERSIZE]; + float m_fftSpectrumBuffer[FULL_BUFFERSIZE]; + float m_spectrumBufferFull[FULL_BUFFERSIZE]; + float *m_window; + + volatile bool m_stopped; + + float m_specMax; + float m_specMin; + float m_scale; + + int m_sampleRate; + int m_downSampleRate; + int m_downRate; + int m_specBufferSize; + int m_specAvgLength; + float m_filterLowerFrequency; + float m_filterUpperFrequency; + + bool m_switch; + bool m_showChirpFFT; + + + qint64 m_chirpBufferLength; + qreal m_chirpSidebandFactor; + + void setupConnections(); + void decimate(const CPX &in, CPX &out, int size, int downrate); + void decimate(const QList &data, CPX &out, int downrate); + void spectrumAveraging(qint64 length, const float *buffer); + + int setSpectrumBufferSize(int size); + +signals: + void messageEvent(QString message); +}; + +#endif // _CUSDR_CHIRPPROCESSOR_H diff --git a/Source/src/DataEngine/cusdr_dataEngine.cpp b/Source/src/DataEngine/cusdr_dataEngine.cpp new file mode 100644 index 0000000..9f01da2 --- /dev/null +++ b/Source/src/DataEngine/cusdr_dataEngine.cpp @@ -0,0 +1,3761 @@ +/** +* @file cusdr_dataEngine.cpp +* @brief cuSDR data engine class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-02 +*/ + +/* + * + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * using original C code by John Melton, G0ORX/N6LYT and Dave McQuate, WA8YWQ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#define TESTING + +#define LOG_DATA_ENGINE +// use DATA_ENGINE_DEBUG +#define LOG_DATA_PROCESSOR +// use DATA_PROCESSOR_DEBUG +#define LOG_AUDIO_PROCESSOR +// use AUDIO_PROCESSOR +#define LOG_WIDEBAND_PROCESSOR +// use WIDEBAND_PROCESSOR_DEBUG + +#include "cusdr_dataEngine.h" + +/*! + \class DataEngine + \brief The DataEngine class implements the main SDR functionality. +*/ +/*! + \brief Implements interfaces to the HPSDR hardware and various Server and DSP functionality. + - set up HW interfaces to Metis or other resp. + - initializes Metis. + - set up parameters for HPSDR hardware. + - implements the data receiver thread. + - implements the data processor thread. + - implements the wide band data processor thread. + - implements the audio receiver thread. + - implements the audio processor thread. + - implements the interface to the Chirp WSPR decoding functionality. +*/ +DataEngine::DataEngine(QObject *parent) + : QObject(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_meterType(SIGNAL_STRENGTH) + , m_restart(false) + , m_networkDeviceRunning(false) + , m_soundFileLoaded(false) + , m_chirpInititalized(false) + , m_discoveryThreadRunning(false) + , m_dataIOThreadRunning(false) + , m_chirpDataProcThreadRunning(false) + , m_dataProcThreadRunning(false) + , m_audioRcvrThreadRunning(false) + , m_audioInProcThreadRunning(false) + , m_audioOutProcThreadRunning(false) + , m_frequencyChange(false) + //, m_wbSpectrumAveraging(set->getSpectrumAveraging()) + //, m_wbSpectrumAveraging(true) + , m_hamBandChanged(true) + , m_chirpThreadStopped(true) + , m_hpsdrDevices(0) + , m_configure(10) + , m_timeout(5000) + , m_remainingTime(0) + , m_RxFrequencyChange(0) + , m_forwardPower(0) + , m_rxSamples(0) + , m_chirpSamples(0) + , m_spectrumSize(set->getSpectrumSize()) + , m_sendState(0) + , m_sMeterCalibrationOffset(0.0f)//(35.0f) +{ + qRegisterMetaType(); + + this->setObjectName(QString::fromUtf8("dataEngine")); + + m_clientConnected = false; + + //currentRx = 0; + m_discoverer = 0; + m_dataIO = 0; + m_dataProcessor = 0; + m_wbDataProcessor = 0; + m_audioReceiver = 0; + m_audioOutProcessor = 0; + m_chirpProcessor = 0; + //m_wbAverager = 0; + + set->setMercuryVersion(0); + set->setPenelopeVersion(0); + set->setPennyLaneVersion(0); + set->setMetisVersion(0); + set->setHermesVersion(0); + + io.metisFW = 0; + io.hermesFW = 0; + io.mercuryFW = 0; + + //m_audioBuffer.resize(0); + //m_audiobuf.resize(IO_BUFFER_SIZE); + + initAudioEngine(); + setupConnections(); + + // test + /*audioringbuffer.reserve(3); + + audioringbuffer.append(1); + audioringbuffer.append(2); + audioringbuffer.append(3); + + for (int i = 0; i < audioringbuffer.size(); ++i) { + qDebug() << audioringbuffer.at(i); + } + + audioringbuffer.append(4); + audioringbuffer.append(5); + + for (int i = 0; i < audioringbuffer.size(); ++i) { + qDebug() << audioringbuffer.at(i); + }*/ + + m_message = "audio sample = %1"; + m_counter = 0; +} + +DataEngine::~DataEngine() { +} + +void DataEngine::initAudioEngine() { + m_audioEngine = new AudioEngine(); + //m_audioEngine->setSystemState(QSDR::NoError, m_hwInterface, m_serverMode, m_dataEngineState); +} + +void DataEngine::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(rxListChanged(QList)), + this, + SLOT(rxListChanged(QList))); + + CHECKED_CONNECT( + set, + SIGNAL(numberOfRXChanged(QObject *, int)), + this, + SLOT(setNumberOfRx(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *,int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(hamBandChanged(QObject *, int, bool, HamBand)), + this, + SLOT(setHamBand(QObject *, int, bool, HamBand))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(setSampleRate(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(setMercuryAttenuator(QObject *, HamBand, int))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(mercuryAttenuatorsChanged(QObject *, QList)), +// this, +// SLOT(setMercuryAttenuators(QObject *, QList))); + + CHECKED_CONNECT( + set, + SIGNAL(ditherChanged(QObject *, int)), + this, + SLOT(setDither(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(randomChanged(QObject *, int)), + this, + SLOT(setRandom(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(src10MhzChanged(QObject *, int)), + this, + SLOT(set10MhzSource(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(src122_88MhzChanged(QObject *, int)), + this, + SLOT(set122_88MhzSource(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(micSourceChanged(QObject *, int)), + this, + SLOT(setMicSource(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(classChanged(QObject *, int)), + this, + SLOT(setMercuryClass(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(timingChanged(QObject *, int)), + this, + SLOT(setMercuryTiming(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(clientDisconnectedEvent(int)), + this, + SLOT(setClientDisconnected(int))); + + CHECKED_CONNECT( + set, + SIGNAL(clientNoConnectedChanged(QObject*, int)), + this, + SLOT(setClientConnected(QObject*, int))); + + CHECKED_CONNECT( + set, + SIGNAL(rxConnectedStatusChanged(QObject*, int, bool)), + this, + SLOT(setRxConnectedStatus(QObject*, int, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(audioRxChanged(QObject*, int)), + this, + SLOT(setAudioReceiver(QObject*, int))); + + CHECKED_CONNECT( + set, + SIGNAL(framesPerSecondChanged(QObject*, int, int)), + this, + SLOT(setFramesPerSecond(QObject*, int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(searchMetisSignal()), + this, + SLOT(searchHpsdrNetworkDevices())); + + /*CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingChanged(QObject*, int, bool)), + this, + SLOT(setWbSpectrumAveraging(QObject*, int, bool)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(networkDeviceNumberChanged(int)), + this, + SLOT(setHPSDRDeviceNumber(int))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(alexConfigurationChanged(const QList &)), +// this, +// SLOT(setAlexConfiguration(const QList &))); + + CHECKED_CONNECT( + set, + SIGNAL(alexConfigurationChanged(quint16)), + this, + SLOT(setAlexConfiguration(quint16))); + + CHECKED_CONNECT( + set, + SIGNAL(alexStateChanged(HamBand, const QList &)), + this, + SLOT(setAlexStates(HamBand, const QList &))); + + CHECKED_CONNECT( + set, + SIGNAL(pennyOCEnabledChanged(bool)), + this, + SLOT(setPennyOCEnabled(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(rxJ6PinsChanged(const QList &)), + this, + SLOT(setRxJ6Pins(const QList &))); + + CHECKED_CONNECT( + set, + SIGNAL(txJ6PinsChanged(const QList &)), + this, + SLOT(setTxJ6Pins(const QList &))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(formatChanged(QObject *, const QAudioFormat )), + set, + SLOT(setAudioFormat(QObject *, const QAudioFormat ))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(formatChanged(QObject *, const QAudioFormat )), + this, + SLOT(setAudioFileFormat(QObject *, const QAudioFormat ))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(playPositionChanged(QObject *, qint64)), + set, + SLOT(setAudioPosition(QObject *, qint64))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(playPositionChanged(QObject *, qint64)), + this, + SLOT(setAudioFilePosition(QObject *, qint64))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(bufferChanged(QObject *, qint64, qint64, const QByteArray)), + set, + SLOT(setAudioBuffer(QObject *, qint64, qint64, const QByteArray))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(bufferChanged(QObject *, qint64, qint64, const QByteArray)), + this, + SLOT(setAudioFileBuffer(QObject *, qint64, qint64, const QByteArray))); + + CHECKED_CONNECT( + m_audioEngine, + SIGNAL(audiofileBufferChanged(const QList)), + this, + SLOT(setAudioFileBuffer(const QList))); +} + +//******************************************************** +// start/stop data engine +bool DataEngine::startDataEngineWithoutConnection() { + + DATA_ENGINE_DEBUG << "no HPSDR-HW interface"; + + if (io.inputBuffer.length() > 0) { + + initReceivers(1); + if (!m_dataIO) createDataIO(); + if (!m_dataProcessor) createDataProcessor(); + + // data receiver thread + if (!startDataIO(QThread::NormalPriority)) { + + setSystemState(QSDR::DataReceiverThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } + + switch (m_serverMode) { + + case QSDR::SDRMode: + case QSDR::ChirpWSPR: + case QSDR::NoServerMode: + case QSDR::DemoMode: + return false; + + case QSDR::ChirpWSPRFile: + + if (!m_chirpInititalized) createChirpDataProcessor(); + + m_chirpProcessor->generateLocalChirp(); + + if (!startChirpDataProcessor(QThread::NormalPriority)) { + + setSystemState(QSDR::ChirpDataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } + + m_chirpDspEngine = new QDSPEngine(this, 0, 2*BUFFER_SIZE); + + cpxIn.resize(2*BUFFER_SIZE); + cpxOut.resize(2*BUFFER_SIZE); + + RX.at(0)->setConnectedStatus(true); + set->setRxList(RX); + + m_rxSamples = 0; + m_chirpSamples = 0; + + break; + } + + // IQ data processing thread + if (!startDataProcessor(QThread::NormalPriority)) { + + setSystemState(QSDR::DataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } + setSystemState(QSDR::NoError, m_hwInterface, m_serverMode, QSDR::DataEngineUp); + return true; + } + else { + + DATA_ENGINE_DEBUG << "no data available - data file loaded?"; + return false; + } +} + +bool DataEngine::findHPSDRDevices() { + + if (!m_discoverer) createDiscoverer(); + + // HPSDR network IO thread + if (!startDiscoverer(QThread::NormalPriority)) { + + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "HPSDR device discovery thread could not be started."; + io.networkIOMutex.unlock(); + return false; + } + + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "HPSDR network device detection...please wait."; + set->setSystemMessage("HPSDR network device detection...please wait", 0); + io.devicefound.wait(&io.networkIOMutex); + + m_hpsdrDevices = set->getHpsdrNetworkDevices(); + if (m_hpsdrDevices == 0) { + + io.networkIOMutex.unlock(); + stopDiscoverer(); + DATA_ENGINE_DEBUG << "no device found. HPSDR hardware powered? Network connection established?"; + set->setSystemMessage("no device found. HPSDR hardware powered? Network connection established?", 10000); + + setSystemState(QSDR::HwIOError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + } + else { + + emit clearSystemMessageEvent(); + if (m_hpsdrDevices > 1) + set->showNetworkIODialog(); + + QList metisList = set->getMetisCardsList(); + DATA_ENGINE_DEBUG << "found " << metisList.count() << " network device(s)"; + + for (int i = 0; i < metisList.count(); i++) { + + DATA_ENGINE_DEBUG << "Device " + << i << " @ " + << qPrintable(metisList.at(i).ip_address.toString()) + //<< " [" << qPrintable((char *) &metisList.at(i).mac_address) << "]"; + << " [" << metisList.at(i).mac_address << "]"; + } + + io.hpsdrDeviceIPAddress = set->getCurrentMetisCard().ip_address; + io.hpsdrDeviceName = set->getCurrentMetisCard().boardName; + DATA_ENGINE_DEBUG << "using HPSDR network device at " << qPrintable(io.hpsdrDeviceIPAddress.toString()); + + //Sleep(100); + SleeperThread::msleep(100); + + // stop the discovery thread + io.networkIOMutex.unlock(); + stopDiscoverer(); + + if (getFirmwareVersions()) return true; + return false; + } + + return false; +} + +bool DataEngine::getFirmwareVersions() { + + m_fwCount = 0; + + // init receivers + int rcvrs = set->getNumberOfReceivers(); + + QString str = "Initializing %1 receiver(s)...please wait"; + set->setSystemMessage(str.arg(set->getNumberOfReceivers()), rcvrs * 500); + + if (!initReceivers(rcvrs)) return false; + + + if (!m_dataIO) createDataIO(); + + if (!m_dataProcessor) createDataProcessor(); + + switch (m_serverMode) { + + case QSDR::SDRMode: + + for (int i = 0; i < set->getNumberOfReceivers(); i++) { + + RX.at(i)->setConnectedStatus(true); + } + setTimeStamp(this, false); + break; + + default: + + DATA_ENGINE_DEBUG << "no valid server mode"; + setSystemState(QSDR::ServerModeError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + + return false; + } + + set->setRxList(RX); + connectDSPSlots(); + + for (int i = 0; i < set->getNumberOfReceivers(); i++) + RX.at(i)->setAudioVolume(this, i, 0.0f); + + // IQ data processing thread + if (!startDataProcessor(QThread::NormalPriority)) { + + DATA_ENGINE_DEBUG << "data processor thread could not be started."; + return false; + } + + // data IO thread + if (!startDataIO(QThread::NormalPriority)) {// ::NormalPriority)) { + + DATA_ENGINE_DEBUG << "data IO thread could not be started."; + return false; + } + + //setSampleRate(this, set->getSampleRate()); + SleeperThread::msleep(100); + + // pre-conditioning + for (int i = 0; i < io.receivers; i++) + m_dataIO->sendInitFramesToNetworkDevice(i); + + if (m_serverMode == QSDR::SDRMode) + m_dataIO->networkDeviceStartStop(0x01); // 0x01 for starting Metis without wide band data + + m_networkDeviceRunning = true; + setSystemState(QSDR::NoError, m_hwInterface, m_serverMode, QSDR::DataEngineUp); + SleeperThread::msleep(300); + + io.metisFW = set->getMetisVersion(); + io.mercuryFW = set->getMercuryVersion(); + io.penelopeFW = set->getPenelopeVersion(); + io.pennylaneFW = set->getPennyLaneVersion(); + io.hermesFW = set->getHermesVersion(); + + // if we have 4096 * 16 bit = 8 * 1024 raw consecutive ADC samples, m_wbBuffers = 8 + // we have 16384 * 16 bit = 32 * 1024 raw consecutive ADC samples, m_wbBuffers = 32 + int wbBuffers = 0; + if (io.mercuryFW > 32 || io.hermesFW > 11) + wbBuffers = BIGWIDEBANDSIZE / 512; + else + wbBuffers = SMALLWIDEBANDSIZE / 512; + + set->setWidebandBuffers(this, wbBuffers); + + if (set->getFirmwareVersionCheck()) + return checkFirmwareVersions(); + else + return true; +} + +// credits go to George Byrkit, K9TRV: the older FW checkings are shamelessly taken from the KISS Konsole! +bool DataEngine::checkFirmwareVersions() { + + if (io.metisFW != 0 && io.hpsdrDeviceName == "Hermes") { + + stop(); + + QString msg = "Metis selected, but Hermes found!"; + set->showWarningDialog(msg); + return false; + } + + if (io.hermesFW != 0 && io.hpsdrDeviceName == "Metis") { + + stop(); + + QString msg = "Hermes selected, but Metis found!"; + set->showWarningDialog(msg); + return false; + } + + if (io.penelopeFW == 0 && (set->getPenelopePresence() || set->getPennyLanePresence())) { + + stop(); + + QString msg = "Penelope or Pennylane selected, but firmware version = 0 !"; + set->showWarningDialog(msg); + return false; + } + + if (io.mercuryFW < 27 && set->getNumberOfReceivers() > 4 && io.hpsdrDeviceName == "Metis") { + + stop(); + + QString msg = "Mercury FW must be V2.7 or higher!"; + set->showWarningDialog(msg); + return false; + } + + if (io.hpsdrDeviceName == "Metis") { + + QString msg; + switch (io.metisFW) { + + case 13: + if (((set->getPenelopePresence() || set->getPennyLanePresence()) && + (io.penelopeFW == 13 || io.pennylaneFW == 13)) || + io.mercuryFW != 29) + { + stop(); + + msg = "Penny[Lane] FW Version V1.3 and Mercury FW V2.7 requires Metis FW V1.3!"; + set->showWarningDialog(msg); + return false; + } + break; + + case 14: + if (((set->getPenelopePresence() || set->getPennyLanePresence()) && + (io.penelopeFW == 14 || io.pennylaneFW == 14)) || + io.mercuryFW != 29) + { + stop(); + + msg = "Penny[Lane] FW Version V1.4 and Mercury FW V2.7 requires Metis FW V1.4!"; + set->showWarningDialog(msg); + return false; + } + break; + + case 15: + + if (((set->getPenelopePresence() || set->getPennyLanePresence()) && + (io.penelopeFW == 15 || io.pennylaneFW == 15)) || + io.mercuryFW != 30) + { + stop(); + + msg = "Penny[Lane] FW Version V1.5 and Mercury FW V3.0 requires Metis FW V1.5!"; + set->showWarningDialog(msg); + return false; + } + break; + + case 16: + + if (((set->getPenelopePresence() || set->getPennyLanePresence()) && + (io.penelopeFW == 16 || io.pennylaneFW == 16)) || + io.mercuryFW != 31) + { + stop(); + + msg = "Penny[Lane] FW Version V1.6 and Mercury FW V3.1 requires Metis FW V1.6!"; + set->showWarningDialog(msg); + return false; + } + break; + + case 17: + case 18: + + if (((set->getPenelopePresence() || set->getPennyLanePresence()) && + (io.penelopeFW == 17 || io.pennylaneFW == 17)) || + io.mercuryFW != 32) + { + stop(); + + msg = "Penny[Lane] FW Version V1.7 and Mercury FW V3.2 requires Metis FW V1.7 or V1.8!"; + set->showWarningDialog(msg); + return false; + } + break; + + case 19: + case 20: + + stop(); + + msg = "Metis FW V1.9 or V2.0 have some problems - please upgrade to Metis V2.1!"; + set->showWarningDialog(msg); + return false; + break; + + case 21: + + if ((set->getPenelopePresence() && io.penelopeFW != 17) || + (set->getPennyLanePresence() && io.pennylaneFW != 17)|| + io.mercuryFW != 33) + { + stop(); + + msg = "Penny[Lane] FW Version V1.7 and Mercury FW V3.3 required for Metis FW V2.1!"; + set->showWarningDialog(msg); + return false; + } + break; + +// case 22: +// +// if ((set->getPenelopePresence() && m_penelopeFW != 17) || +// (set->getPennyLanePresence() && m_pennylaneFW != 17)|| +// m_mercuryFW != 33) +// { +// stop(); +// +// msg = "Penny[Lane] FW Version V1.7 and Mercury FW V3.3 required for Metis FW >= V2.1!"; +// set->showWarningDialog(msg); +// return false; +// } +// break; + + case 26: + + if ((set->getPenelopePresence() && io.penelopeFW != 18) || + (set->getPennyLanePresence() && io.pennylaneFW != 18)|| + io.mercuryFW != 34) + { + stop(); + + msg = "Penny[Lane] FW Version V1.8 and Mercury FW V3.4 required for Metis FW V2.6!"; + set->showWarningDialog(msg); + return false; + } + break; + + default: + + //stop(); + + msg = "Not a standard Metis FW version !"; + set->showWarningDialog(msg); + //return false; + return true; + } + } + + if (io.mercuryFW < 33 && set->getNumberOfReceivers() > 4 && io.hpsdrDeviceName == "Metis") { + + stop(); + + QString msg = "Mercury FW < V3.3 has only 4 receivers!"; + set->showWarningDialog(msg); + return false; + } + + if (io.hermesFW < 18 && set->getNumberOfReceivers() > 2 && io.hpsdrDeviceName == "Hermes") { + + stop(); + + QString msg = "Hermes FW < V1.8 has only 2 receivers!"; + set->showWarningDialog(msg); + return false; + } + + return true; +} + +bool DataEngine::start() { + + m_fwCount = 0; + m_sendState = 0; + + int rcvrs = set->getNumberOfReceivers(); + if (!initReceivers(rcvrs)) return false; + + if (!m_dataIO) createDataIO(); + + if (!m_dataProcessor) createDataProcessor(); + + if (m_serverMode == QSDR::SDRMode && !m_wbDataProcessor) + createWideBandDataProcessor(); + + if ((m_serverMode == QSDR::ChirpWSPR) && !m_chirpProcessor) + createChirpDataProcessor(); + + switch (m_serverMode) { + + //case QSDR::ExternalDSP: + + /* + //CHECKED_CONNECT( + // set, + // SIGNAL(frequencyChanged(QObject*, bool, int, long)), + // this, + // SLOT(setFrequency(QObject*, bool, int, long))); + + //if (!m_audioProcessorRunning) { + + // //if (!m_audioProcessor) createAudioProcessor(); + // if (!m_audioReceiver) createAudioReceiver(); + + // m_audioInProcThread->start(); + // if (m_audioInProcThread->isRunning()) { + // + // m_audioInProcThreadRunning = true; + // DATA_ENGINE_DEBUG << "Audio processor process started."; + // } + // else { + + // m_audioInProcThreadRunning = false; + // setSystemState( + // QSDR::AudioThreadError, + // m_hwInterface, + // m_serverMode, + // QSDR::DataEngineDown); + // return false; + // } + // + // io.audio_rx = 0; + // io.clientList.append(0); + + // m_audioProcessorRunning = true; + // setSystemState( + // QSDR::NoError, + // m_hwInterface, + // m_serverMode, + // QSDR::DataEngineUp); + //} + */ + //return false; + + case QSDR::SDRMode: + + setTimeStamp(this, false); + break; + + case QSDR::ChirpWSPR: + //case QSDR::ChirpWSPRFile: + + // turn time stamping on + setTimeStamp(this, true); + + if (!startChirpDataProcessor(QThread::NormalPriority)) { + + DATA_ENGINE_DEBUG << "data processor thread could not be started."; + return false; + } + + //RX.at(0)->setConnectedStatus(true); + + CHECKED_CONNECT( + set, + SIGNAL(ctrFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setFrequency(QObject *, int, int, long))); + + break; + + default: + + DATA_ENGINE_DEBUG << "no valid server mode"; + + setSystemState(QSDR::ServerModeError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } // end switch (m_serverMode) + + set->setRxList(RX); + connectDSPSlots(); + + for (int i = 0; i < rcvrs; i++) { + + RX.at(i)->setConnectedStatus(true); + RX.at(i)->setAudioVolume(this, i, RX.at(i)->getAudioVolume()); + setFrequency(this, true, i, set->getCtrFrequencies().at(i)); + + //CHECKED_CONNECT( + // RX.at(i), + // SIGNAL(outputBufferSignal(int, const CPX &)), + // this, //m_dataProcessor, + // SLOT(setOutputBuffer(int, const CPX &))); + + CHECKED_CONNECT( + RX.at(i), + SIGNAL(outputBufferSignal(int, const CPX &)), + m_dataProcessor, + SLOT(setOutputBuffer(int, const CPX &))); + + m_dspThreadList.at(i)->start(QThread::NormalPriority);//QThread::TimeCriticalPriority); + + if (m_dspThreadList.at(i)->isRunning()) { + + //m_dataProcThreadRunning = true; + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "receiver processor thread started for Rx " << i; + io.networkIOMutex.unlock(); + } + else { + + //m_dataProcThreadRunning = false; + //setSystemState(QSDR::DataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } + } + + if (m_serverMode != QSDR::ChirpWSPR && !startWideBandDataProcessor(QThread::NormalPriority)) { + + DATA_ENGINE_DEBUG << "wide band data processor thread could not be started."; + return false; + } + + // data IO thread +// if (!startDataIO(QThread::HighPriority)) {// ::NormalPriority)) { +// +// DATA_ENGINE_DEBUG << "data receiver thread could not be started."; +// return false; +// } + + // IQ data processing thread + if (!startDataProcessor(QThread::NormalPriority)) { + + DATA_ENGINE_DEBUG << "data processor thread could not be started."; + return false; + } + + // data IO thread + if (!startDataIO(QThread::NormalPriority)) {// ::NormalPriority::HighPriority)) { + + DATA_ENGINE_DEBUG << "data IO thread could not be started."; + return false; + } + + // start Sync,ADC and S-Meter timers + //m_SyncChangedTime.start(); + //m_ADCChangedTime.start(); + //m_smeterTime.start(); + + // start the "frames-per-second" timer for all receivers + for (int i = 0; i < rcvrs; i++) + RX.at(i)->highResTimer->start(); + + // just give them a little time.. + SleeperThread::msleep(100); + + // pre-conditioning + for (int i = 0; i < io.receivers; i++) + m_dataIO->sendInitFramesToNetworkDevice(i); + + if (m_serverMode == QSDR::SDRMode && set->getWidebandData()) + m_dataIO->networkDeviceStartStop(0x03); // 0x03 for starting the device with wide band data + else + m_dataIO->networkDeviceStartStop(0x01); // 0x01 for starting the device without wide band data + + m_networkDeviceRunning = true; + + setSystemState(QSDR::NoError, m_hwInterface, m_serverMode, QSDR::DataEngineUp); + set->setSystemMessage("System running", 4000); + + DATA_ENGINE_DEBUG << "Data Engine thread: " << this->thread(); + + return true; +} + +void DataEngine::stop() { + + if (m_dataEngineState == QSDR::DataEngineUp) { + + switch (m_hwInterface) { + + case QSDR::Metis: + case QSDR::Hermes: + + // turn time stamping off + setTimeStamp(this, false); + + // stop the device + m_dataIO->networkDeviceStartStop(0); + m_networkDeviceRunning = false; + DATA_ENGINE_DEBUG << "HPSDR device stopped"; + + // stop the threads + //SleeperThread::msleep(100); + stopDataIO(); + SleeperThread::msleep(100); + stopDataProcessor(); + //stopChirpDataProcessor(); + if (m_wbDataProcessor) + stopWideBandDataProcessor(); + + // clear device list + SleeperThread::msleep(100); + set->clearMetisCardList(); + DATA_ENGINE_DEBUG << "device cards list cleared."; + break; + + case QSDR::NoInterfaceMode: + + stopDataIO(); + + DATA_ENGINE_DEBUG << "data queue count: " << io.data_queue.count(); + DATA_ENGINE_DEBUG << "chirp queue count: " << io.chirp_queue.count(); + + stopDataProcessor(); + stopChirpDataProcessor(); + } + + while (!io.au_queue.isEmpty()) + io.au_queue.dequeue(); + + // clear receiver thread list + foreach (QThread* thread, m_dspThreadList) { + + thread->quit(); + thread->wait(); + } + qDeleteAll(m_dspThreadList.begin(), m_dspThreadList.end()); + m_dspThreadList.clear(); + + // clear receiver list + foreach (Receiver *rx, RX) { + + rx->stop(); + rx->setConnectedStatus(false); + disconnectDSPSlots(); + + disconnect( + rx, + SIGNAL(spectrumBufferChanged(int, const qVectorFloat&)), + set, + SLOT(setSpectrumBuffer(int, const qVectorFloat&))); + + disconnect( + rx, + SIGNAL(sMeterValueChanged(int, float)), + set, + SLOT(setSMeterValue(int, float))); + + /*disconnect( + rx, + SIGNAL(outputBufferSignal(int, const CPX &)), + this, + SLOT(setOutputBuffer(int, const CPX &)));*/ + + /*disconnect( + rx, + SIGNAL(outputBufferSignal(int, const CPX &)), + m_dataProcessor, + SLOT(setOutputBuffer(int, const CPX &)));*/ + + //rx->deleteDSPInterface(); + //DATA_ENGINE_DEBUG << "DSP core deleted."; + } + qDeleteAll(RX.begin(), RX.end()); + RX.clear(); + set->setRxList(RX); + DATA_ENGINE_DEBUG << "receiver threads deleted, receivers deleted, receiver & thread list cleared."; + set->setSystemMessage("Data engine shut down.", 4000); + + setSystemState(QSDR::NoError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + } + + m_rxSamples = 0; + m_chirpSamples = 0; + m_restart = true; + m_found = 0; + m_hpsdrDevices = 0; + + set->setMercuryVersion(0); + set->setPenelopeVersion(0); + set->setMetisVersion(0); + set->setHermesVersion(0); + + //set->setPeakHold(false); + //set->resetWidebandSpectrumBuffer(); + + /*disconnect( + set, + SIGNAL(ctrFrequencyChanged(QObject*, int, int, long)), + this, + SLOT(setFrequency(QObject*, int, int, long)));*/ + + DATA_ENGINE_DEBUG << "shut down done."; +} + +bool DataEngine::initDataEngine() { + +#ifdef TESTING + qDebug() << "************************** TESTING MODUS ***********************************"; + return start(); +#endif + + if (m_hwInterface == QSDR::NoInterfaceMode) { + + return startDataEngineWithoutConnection(); + } + else { + + if (findHPSDRDevices()) { + + if (io.mercuryFW > 0 || io.hermesFW > 0) { + + stop(); + DATA_ENGINE_DEBUG << "got firmware versions:"; + DATA_ENGINE_DEBUG << " Metis firmware: " << io.metisFW; + DATA_ENGINE_DEBUG << " Mercury firmware: " << io.mercuryFW; + DATA_ENGINE_DEBUG << " Penelope firmware: " << io.penelopeFW; + DATA_ENGINE_DEBUG << " Pennylane firmware: " << io.pennylaneFW; + DATA_ENGINE_DEBUG << " Hermes firmware: " << io.hermesFW; + DATA_ENGINE_DEBUG << "stopping and restarting data engine."; + + return start(); + } + else { + + DATA_ENGINE_DEBUG << "did not get firmware versions!"; + setSystemState(QSDR::FirmwareError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + } + } + } + return false; +} + +bool DataEngine::initReceivers(int rcvrs) { + + for (int i = 0; i < rcvrs; i++) { + + Receiver *rx = new Receiver(i); + + // init the DSP core + DATA_ENGINE_DEBUG << "trying to init a DSP core for rx " << i; + + if (rx->initDSPInterface()) { + + DATA_ENGINE_DEBUG << "init DSP core for rx " << i << " successful !"; + + rx->setConnectedStatus(false); + rx->setServerMode(m_serverMode); + + // create dsp thread + QThreadEx* thread = new QThreadEx(); + rx->moveToThread(thread); + + //CHECKED_CONNECT(this, SIGNAL(doDSP()), rx, SLOT(dspProcessing())); + + CHECKED_CONNECT( + rx, + SIGNAL(spectrumBufferChanged(int, const qVectorFloat&)), + set, + SLOT(setSpectrumBuffer(int, const qVectorFloat&))); + + CHECKED_CONNECT( + rx, + SIGNAL(sMeterValueChanged(int, float)), + set, + SLOT(setSMeterValue(int, float))); + + /*CHECKED_CONNECT( + rx, + SIGNAL(outputBufferSignal(int, const CPX &)), + m_dataProcessor, + SLOT(setOutputBuffer(int, const CPX &)));*/ + + m_dspThreadList.append(thread); + RX.append(rx); + } + else { + + return false; + } + } + + set->setRxList(RX); + + m_txFrame = 0; + + io.currentReceiver = 0; + io.receivers = rcvrs; + + io.timing = 0; + m_configure = io.receivers + 1; + + // init cc Rc parameters + io.ccRx.devices.mercuryFWVersion = 0; + io.ccRx.devices.penelopeFWVersion = 0; + io.ccRx.devices.pennylaneFWVersion = 0; + io.ccRx.devices.hermesFWVersion = 0; + io.ccRx.devices.metisFWVersion = 0; + + io.ccRx.ptt = false; + io.ccRx.dash = false; + io.ccRx.dot = false; + io.ccRx.lt2208 = false; + io.ccRx.ain1 = 0; + io.ccRx.ain2 = 0; + io.ccRx.ain3 = 0; + io.ccRx.ain4 = 0; + io.ccRx.ain5 = 0; + io.ccRx.ain6 = 0; + io.ccRx.hermesI01 = false; + io.ccRx.hermesI02 = false; + io.ccRx.hermesI03 = false; + io.ccRx.hermesI04 = false; + io.ccRx.mercury1_LT2208 = false; + io.ccRx.mercury2_LT2208 = false; + io.ccRx.mercury3_LT2208 = false; + io.ccRx.mercury4_LT2208 = false; + + // init cc Tx parameters + io.ccTx.currentBand = RX.at(0)->getHamBand(); + io.ccTx.mercuryAttenuators = RX.at(0)->getMercuryAttenuators(); + io.ccTx.mercuryAttenuator = RX.at(0)->getMercuryAttenuators().at(io.ccTx.currentBand); + io.ccTx.dither = set->getMercuryDither(); + io.ccTx.random = set->getMercuryRandom(); + io.ccTx.duplex = 1; + io.ccTx.mox = false; + io.ccTx.ptt = false; + io.ccTx.alexStates = set->getAlexStates(); + io.ccTx.vnaMode = false; + io.ccTx.alexConfig = set->getAlexConfig(); + io.ccTx.timeStamp = 0; + io.ccTx.commonMercuryFrequencies = 0; + io.ccTx.pennyOCenabled = set->getPennyOCEnabled(); + io.ccTx.rxJ6pinList = set->getRxJ6Pins(); + io.ccTx.txJ6pinList = set->getTxJ6Pins(); + + setAlexConfiguration(io.ccTx.alexConfig); + + io.rxClass = set->getRxClass(); + io.mic_gain = 0.26F; + io.rx_freq_change = -1; + io.tx_freq_change = -1; + io.clients = 0; + io.sendIQ_toggle = true; + io.rcveIQ_toggle = false; + io.alexForwardVolts = 0.0; + io.alexReverseVolts = 0.0; + io.alexForwardPower = 0.0; + io.alexReversePower = 0.0; + io.penelopeForwardVolts = 0.0; + io.penelopeForwardPower = 0.0; + io.ain3Volts = 0.0; + io.ain4Volts = 0.0; + io.supplyVolts = 0.0f; + + + //***************************** + // C&C bytes + for (int i = 0; i < 5; i++) { + + io.control_in[i] = 0x00; + io.control_out[i] = 0x00; + } + + // C0 + // 0 0 0 0 0 0 0 0 + // | + // +------------ MOX (1 = active, 0 = inactive) + + io.control_out[0] |= MOX_DISABLED; + + // set C1 + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + +------------ Speed (00 = 48kHz, 01 = 96kHz, 10 = 192kHz) + // | | | | + +---------------- 10MHz Ref. (00 = Atlas/Excalibur, 01 = Penelope, 10 = Mercury)* + // | | | +-------------------- 122.88MHz source (0 = Penelope, 1 = Mercury)* + // | + +---------------------- Config (00 = nil, 01 = Penelope, 10 = Mercury, 11 = both)* + // +-------------------------- Mic source (0 = Janus, 1 = Penelope)* + + // Bits 1,0 + setSampleRate(this, set->getSampleRate()); + + // Bits 7,..,2 + setHPSDRConfig(); + + io.control_out[1] &= 0x03; // 0 0 0 0 0 0 1 1 + io.control_out[1] |= io.ccTx.clockByte; + + // set C2 + // + // 0 0 0 0 0 0 0 0 + // | | | + // | | +------------ Mode (1 = Class E, 0 = All other modes) + // +---------- +-------------- Open Collector Outputs on Penelope or Hermes (bit 6..bit 0) + + io.control_out[2] = io.control_out[2] & 0xFE; // 1 1 1 1 1 1 1 0 + io.control_out[2] = io.control_out[2] | io.rxClass; + + // set C3 + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + +------------ Alex Attenuator (00 = 0dB, 01 = 10dB, 10 = 20dB, 11 = 30dB) + // | | | | | +---------------- Preamp On/Off (0 = Off, 1 = On) + // | | | | +------------------ LT2208 Dither (0 = Off, 1 = On) + // | | | + ------------------- LT2208 Random (0= Off, 1 = On) + // | + + --------------------- Alex Rx Antenna (00 = none, 01 = Rx1, 10 = Rx2, 11 = XV) + // + ------------------------- Alex Rx out (0 = off, 1 = on). Set if Alex Rx Antenna > 00. + + io.control_out[3] = io.control_out[3] & 0xFB; // 1 1 1 1 1 0 1 1 + io.control_out[3] = io.control_out[3] | (io.ccTx.mercuryAttenuator << 2); + + io.control_out[3] = io.control_out[3] & 0xF7; // 1 1 1 1 0 1 1 1 + io.control_out[3] = io.control_out[3] | (io.ccTx.dither << 3); + + io.control_out[3] = io.control_out[3] & 0xEF; // 1 1 1 0 1 1 1 1 + io.control_out[3] = io.control_out[3] | (io.ccTx.random << 4); + + // set C4 + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + + ----------- Alex Tx relay (00 = Tx1, 01= Tx2, 10 = Tx3) + // | | | | | + --------------- Duplex (0 = off, 1 = on) + // | | + + +------------------ Number of Receivers (000 = 1, 111 = 8) + // | +------------------------ Time stamp - 1PPS on LSB of Mic data (0 = off, 1 = on) + // +-------------------------- Common Mercury Frequency (0 = independent frequencies to Mercury + // Boards, 1 = same frequency to all Mercury boards) + + //io.control_out[4] &= 0xC7; // 1 1 0 0 0 1 1 1 + io.control_out[4] = (io.ccTx.duplex << 2) | ((io.receivers - 1) << 3); + + return true; +} + +void DataEngine::setHPSDRConfig() { + + io.ccTx.clockByte = 0x0; + + // C1 + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + +------------ Speed (00 = 48kHz, 01 = 96kHz, 10 = 192kHz) + // | | | | + +---------------- 10MHz Ref. (00 = Atlas/Excalibur, 01 = Penelope, 10 = Mercury)* + // | | | +-------------------- 122.88MHz source (0 = Penelope, 1 = Mercury)* + // | + +---------------------- Config (00 = nil, 01 = Penelope, 10 = Mercury, 11 = both)* + // +-------------------------- Mic source (0 = Janus, 1 = Penelope)* + // + // * Ignored by Hermes + + if ( + (set->getPenelopePresence() || set->getPennyLanePresence()) && + ((set->get10MHzSource() == 0) || set->getExcaliburPresence()) + ) + { + + io.ccTx.clockByte = MIC_SOURCE_PENELOPE | MERCURY_PRESENT | PENELOPE_PRESENT | MERCURY_122_88MHZ_SOURCE | ATLAS_10MHZ_SOURCE; + } + else if ((set->getPenelopePresence() || set->getPennyLanePresence()) && (set->get10MHzSource() == 1)) { + + io.ccTx.clockByte = MIC_SOURCE_PENELOPE | MERCURY_PRESENT | PENELOPE_PRESENT | MERCURY_122_88MHZ_SOURCE | PENELOPE_10MHZ_SOURCE; + } + else if ((set->getPenelopePresence() || set->getPennyLanePresence()) && (set->get10MHzSource() == 2)) { + + io.ccTx.clockByte = MIC_SOURCE_PENELOPE | MERCURY_PRESENT | PENELOPE_PRESENT | MERCURY_122_88MHZ_SOURCE | MERCURY_10MHZ_SOURCE; + } + else if ((set->get10MHzSource() == 0) || set->getExcaliburPresence()) { + + io.ccTx.clockByte = MERCURY_PRESENT | MERCURY_122_88MHZ_SOURCE | ATLAS_10MHZ_SOURCE; + } + else { + + io.ccTx.clockByte = MERCURY_PRESENT | MERCURY_122_88MHZ_SOURCE | MERCURY_10MHZ_SOURCE; + } +} + +void DataEngine::connectDSPSlots() { + + CHECKED_CONNECT( + set, + SIGNAL(ctrFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setFrequency(QObject *, int, int, long))); +} + +void DataEngine::disconnectDSPSlots() { + + disconnect( + set, + SIGNAL(ctrFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setFrequency(QObject *, int, int, long))); +} + +//******************************************************** +// create, start/stop HPSDR device network IO + +void DataEngine::createDiscoverer() { + + m_discoverer = new Discoverer(&io); + + m_discoveryThread = new QThreadEx(); + m_discoverer->moveToThread(m_discoveryThread); + + m_discoverer->connect( + m_discoveryThread, + SIGNAL(started()), + SLOT(initHPSDRDevice())); +} + +bool DataEngine::startDiscoverer(QThread::Priority prio) { + + m_discoveryThread->start(prio); + + if (m_discoveryThread->isRunning()) { + + m_discoveryThreadRunning = true; + io.networkIOMutex.lock(); + qDebug() << ""; + DATA_ENGINE_DEBUG << "HPSDR device discovery thread started."; + io.networkIOMutex.unlock(); + + return true; + } + else { + + m_discoveryThreadRunning = false; + return false; + } +} + +void DataEngine::stopDiscoverer() { + + if (m_discoveryThread->isRunning()) { + + m_discoveryThread->quit(); + m_discoveryThread->wait(1000); + delete m_discoveryThread; + delete m_discoverer; + m_discoverer = 0; + + m_discoveryThreadRunning = false; + + DATA_ENGINE_DEBUG << "HPSDR discovery thread stopped and deleted."; + } + else + DATA_ENGINE_DEBUG << "HPSDR discovery thread wasn't started."; +} + +//******************************************************** +// create, start/stop data receiver + +void DataEngine::createDataIO() { + + m_dataIO = new DataIO(&io); + + switch (m_serverMode) { + + //case QSDR::ExternalDSP: + // break; + + //case QSDR::InternalDSP: + case QSDR::SDRMode: + + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "configured for " + << qPrintable(QString::number(set->getNumberOfReceivers())) + << " receiver(s) at " + << qPrintable(QString::number(set->getSampleRate()/1000)) + << " kHz sample rate"; + io.networkIOMutex.unlock(); +// sendMessage( +// m_message.arg( +// QString::number(set->getNumberOfReceivers()), +// QString::number(set->getSampleRate()/1000))); + break; + + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + break; + + case QSDR::NoServerMode: + case QSDR::DemoMode: + break; + } + + m_dataIOThread = new QThreadEx(); + m_dataIO->moveToThread(m_dataIOThread); + + switch (m_hwInterface) { + + case QSDR::NoInterfaceMode: + + m_dataIO->connect( + m_dataIOThread, + SIGNAL(started()), + SLOT(readData())); + break; + + case QSDR::Metis: + case QSDR::Hermes: + + m_dataIO->connect( + m_dataIOThread, + SIGNAL(started()), + SLOT(initDataReceiverSocket())); + break; + } +} + +bool DataEngine::startDataIO(QThread::Priority prio) { + + m_dataIOThread->start(prio); + + if (m_dataIOThread->isRunning()) { + + m_dataIOThreadRunning = true; + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "data IO thread started."; + io.networkIOMutex.unlock(); + + return true; + } + else { + + m_dataIOThreadRunning = false; + setSystemState(QSDR::DataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } +} + +void DataEngine::stopDataIO() { + + if (m_dataIOThread->isRunning()) { + + m_dataIO->stop(); + m_dataIOThread->quit(); + + while (!m_dataIOThread->isFinished()) { + + DATA_ENGINE_DEBUG << "data IO thread not yet finished..."; + if (m_dataIOThread->wait(100)) break; + } + m_dataIOThreadRunning = false; + + delete m_dataIOThread; + delete m_dataIO; + m_dataIO = 0; + + if (m_serverMode == QSDR::ChirpWSPRFile) { + + while (!io.chirp_queue.isEmpty()) + io.chirp_queue.dequeue(); + } + + DATA_ENGINE_DEBUG << "data IO thread deleted."; + } + else + DATA_ENGINE_DEBUG << "data IO thread wasn't started."; +} + +//******************************************************** +// create, start/stop data processor + +void DataEngine::createDataProcessor() { + + m_dataProcessor = new DataProcessor(this, m_serverMode, m_hwInterface); + sendSocket = new QUdpSocket(); + + CHECKED_CONNECT( + sendSocket, + SIGNAL(error(QAbstractSocket::SocketError)), + m_dataProcessor, + SLOT(displayDataProcessorSocketError(QAbstractSocket::SocketError))); + + switch (m_serverMode) { + + // The signal iqDataReady is generated by the function + // processInputBuffer when a block of input data are + // decoded. + + case QSDR::SDRMode: + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + + /*connect( + this, + SIGNAL(iqDataReady(int)), + SLOT(dttSPDspProcessing(int)), + Qt::DirectConnection);*/ + + break; + + case QSDR::NoServerMode: + case QSDR::DemoMode: + break; + + /* + case QSDR::ExternalDSP: + + CHECKED_CONNECT_OPT( + this, + SIGNAL(iqDataReady(int)), + m_dataProcessor, + SLOT(externalDspProcessing(int)), + Qt::DirectConnection); + + break; + + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + break; + */ + } + + m_dataProcThread = new QThreadEx(); + m_dataProcessor->moveToThread(m_dataProcThread); + sendSocket->moveToThread(m_dataProcThread); + + switch (m_hwInterface) { + + case QSDR::NoInterfaceMode: + m_dataProcessor->connect( + m_dataProcThread, + SIGNAL(started()), + SLOT(processData())); + break; + + case QSDR::Metis: + case QSDR::Hermes: + m_dataProcessor->connect( + m_dataProcThread, + SIGNAL(started()), + SLOT(processDeviceData())); + + break; + } + + //m_dataProcessor->connect(m_dataProcThread, SIGNAL(started()), SLOT(initDataProcessorSocket())); +} + +bool DataEngine::startDataProcessor(QThread::Priority prio) { + + m_dataProcThread->start(prio); + + if (m_dataProcThread->isRunning()) { + + m_dataProcThreadRunning = true; + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "data processor thread started."; + io.networkIOMutex.unlock(); + + return true; + } + else { + + m_dataProcThreadRunning = false; + setSystemState(QSDR::DataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } +} + +void DataEngine::stopDataProcessor() { + + if (m_dataProcThread->isRunning()) { + + m_dataProcessor->stop(); + + if (m_serverMode == QSDR::SDRMode || m_serverMode == QSDR::ChirpWSPR) { + + if (io.iq_queue.isEmpty()) { + io.iq_queue.enqueue(QByteArray(BUFFER_SIZE, 0x0)); + //io.iq_queue.enqueue(QByteArray(2*BUFFER_SIZE, 0x0)); + } + } + else if (m_serverMode == QSDR::ChirpWSPRFile) { + + if (io.data_queue.isEmpty()) { + + QList buf; + for (int i = 0; i < 128; i++) buf << 0.0f; + io.data_queue.enqueue(buf); + } + } + + m_dataProcThread->quit(); + m_dataProcThread->wait(); + delete m_dataProcThread; + delete m_dataProcessor; + m_dataProcessor = 0; + + if (m_serverMode == QSDR::SDRMode || m_serverMode == QSDR::ChirpWSPR) { + + while (!io.iq_queue.isEmpty()) + io.iq_queue.dequeue(); + + DATA_ENGINE_DEBUG << "iq_queue empty."; + } + else if (m_serverMode == QSDR::ChirpWSPRFile) { + + while (!io.data_queue.isEmpty()) + io.data_queue.dequeue(); + + DATA_ENGINE_DEBUG << "data_queue empty."; + chirpData.clear(); + } + + m_dataProcThreadRunning = false; + + DATA_ENGINE_DEBUG << "data processor thread deleted."; + } + else + DATA_ENGINE_DEBUG << "data processor thread wasn't started."; +} + +//******************************************************** +// create, start/stop audio out processor + +void DataEngine::createAudioOutProcessor() { + + m_audioOutProcessor = new AudioOutProcessor(this, m_serverMode); + + switch (m_serverMode) { + + //case QSDR::ExternalDSP: + // break; + + case QSDR::SDRMode: + + /*connect( + this, + SIGNAL(iqDataReady(int)), + SLOT(dttSPDspProcessing(int)), + Qt::DirectConnection);*/ + + break; + + case QSDR::NoServerMode: + case QSDR::DemoMode: + break; + + default: + break; + } + + m_audioOutProcThread = new QThreadEx(); + m_audioOutProcessor->moveToThread(m_audioOutProcThread); + + switch (m_hwInterface) { + + case QSDR::NoInterfaceMode: + /*m_audioOutProcessor->connect( + m_audioOutProcThread, + SIGNAL(started()), + SLOT(processData()));*/ + break; + + case QSDR::Metis: + case QSDR::Hermes: + /*m_audioOutProcessor->connect( + m_audioOutProcThread, + SIGNAL(started()), + SLOT(processDeviceData()));*/ + break; + } +} + +void DataEngine::startAudioOutProcessor(QThread::Priority prio) { + + Q_UNUSED (prio) +} + +void DataEngine::stopAudioOutProcessor() { +} + +//******************************************************** +// create, start/stop winde band data processor + +void DataEngine::createWideBandDataProcessor() { + + int size; + + if (io.mercuryFW > 32 || io.hermesFW > 11) + size = BIGWIDEBANDSIZE; + else + size = SMALLWIDEBANDSIZE; + + m_wbDataProcessor = new WideBandDataProcessor(&io, m_serverMode, size); + + m_wbDataProcThread = new QThreadEx(); + m_wbDataProcessor->moveToThread(m_wbDataProcThread); + m_wbDataProcessor->connect( + m_wbDataProcThread, + SIGNAL(started()), + SLOT(processWideBandData())); + + CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingChanged(QObject*, int, bool)), + m_wbDataProcessor, + SLOT(setWbSpectrumAveraging(QObject*, int, bool))); + + CHECKED_CONNECT( + m_wbDataProcessor, + SIGNAL(wbSpectrumBufferChanged(const qVectorFloat&)), + set, + SLOT(setWidebandSpectrumBuffer(const qVectorFloat&))); +} + +bool DataEngine::startWideBandDataProcessor(QThread::Priority prio) { + + m_wbDataProcThread->start(prio);//(QThread::TimeCriticalPriority);//(QThread::HighPriority);//(QThread::LowPriority); + + if (m_wbDataProcThread->isRunning()) { + + m_wbDataRcvrThreadRunning = true; + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "wide band data processor thread started."; + io.networkIOMutex.unlock(); + + return true; + } + else { + + m_wbDataRcvrThreadRunning = false; + setSystemState(QSDR::WideBandDataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } +} + +void DataEngine::stopWideBandDataProcessor() { + + if (m_wbDataProcThread->isRunning()) { + + m_wbDataProcessor->stop(); + if (io.wb_queue.isEmpty()) + io.wb_queue.enqueue(m_datagram); + + m_wbDataProcThread->quit(); + m_wbDataProcThread->wait(); + delete m_wbDataProcThread; + delete m_wbDataProcessor; + m_wbDataProcessor = 0; + + m_wbDataRcvrThreadRunning = false; + + DATA_ENGINE_DEBUG << "wide band data processor thread deleted."; + } + else + DATA_ENGINE_DEBUG << "wide band data processor thread wasn't started."; +} + +//******************************************************** +// create, start/stop chirp processor +void DataEngine::createChirpDataProcessor() { + + m_chirpProcessor = new ChirpProcessor(&io); + DATA_ENGINE_DEBUG << "chirp decoder initialized"; + + CHECKED_CONNECT_OPT( + m_audioEngine, + SIGNAL(chirpSignalChanged()), + m_chirpProcessor, + SLOT(generateLocalChirp()), + Qt::DirectConnection); + + m_audioEngine->reset(); + if (m_audioEngine->generateSweptTone()) + DATA_ENGINE_DEBUG << "audio chirp signal initialized"; + else + DATA_ENGINE_DEBUG << "audio chirp signal initialization failed"; + + + m_chirpDataProcThread = new QThreadEx(); + m_chirpProcessor->moveToThread(m_chirpDataProcThread); + m_chirpProcessor->connect( + m_chirpDataProcThread, + SIGNAL(started()), + m_chirpProcessor, + SLOT(processChirpData())); + + m_chirpInititalized = true; +} + +bool DataEngine::startChirpDataProcessor(QThread::Priority prio) { + + m_chirpDataProcThread->start(prio);//(QThread::TimeCriticalPriority);//(QThread::HighPriority);//(QThread::LowPriority); + + if (m_chirpDataProcThread->isRunning()) { + + m_chirpDataProcThreadRunning = true; + io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "chirp data processor thread started."; + io.networkIOMutex.unlock(); + + return true; + } + else { + + m_chirpDataProcThreadRunning = false; + setSystemState(QSDR::DataProcessThreadError, m_hwInterface, m_serverMode, QSDR::DataEngineDown); + return false; + } +} + +void DataEngine::stopChirpDataProcessor() { + + if (m_chirpInititalized) { + + m_chirpProcessor->stop(); + if (io.chirp_queue.isEmpty()) { + + QList buf; + for (int i = 0; i < 128; i++) buf << 0.0f; + io.chirp_queue.enqueue(buf); + } + + m_chirpDataProcThread->quit(); + m_chirpDataProcThread->wait(); + delete m_chirpDataProcThread; + delete m_chirpProcessor; + m_chirpProcessor = 0; + + if (m_hwInterface == QSDR::NoInterfaceMode) { + + //freeCPX(io.cpxIn); + //freeCPX(io.cpxOut); + delete m_chirpDspEngine; + + while (!io.chirp_queue.isEmpty()) + io.chirp_queue.dequeue(); + + DATA_ENGINE_DEBUG << "io.cpxIn, io.cpxOut, fft deleted, io.chirp_queue empty."; + } + + m_chirpInititalized = false; + + DATA_ENGINE_DEBUG << "chirp data processor thread deleted."; + } + else + DATA_ENGINE_DEBUG << "chirp data processor thread wasn't started."; +} + +//******************************************************** +// create, start/stop audio receiver + +void DataEngine::createAudioReceiver() { + + m_audioReceiver = new AudioReceiver(&io); + + CHECKED_CONNECT( + m_audioReceiver, + SIGNAL(rcveIQEvent(QObject *, int)), + this, + SLOT(setRcveIQSignal(QObject *, int))); + + CHECKED_CONNECT( + m_audioReceiver, + SIGNAL(clientConnectedEvent(bool)), + this, + SLOT(setClientConnected(bool))); + + + m_AudioRcvrThread = new QThreadEx(); + m_audioReceiver->moveToThread(m_AudioRcvrThread); + + m_audioReceiver->connect( + m_AudioRcvrThread, + SIGNAL(started()), + SLOT(initClient())); +} + + +void DataEngine::processFileBuffer(const QList buffer) { + + + int topsize = 2*BUFFER_SIZE - 1; + //float specMax = -100.0f; + //float specMin = 0.0f; + + Q_ASSERT(buffer.length() == 128); + + for (int i = 0; i < 64; i++) { + + cpxIn[i + m_rxSamples].re = buffer.at(2*i); + cpxIn[i + m_rxSamples].im = buffer.at(2*i+1); + + chirpData << buffer.at(2*i); + chirpData << buffer.at(2*i+1); + + m_chirpSamples++; + if (m_chirpSamples == io.samplerate) { + + io.chirp_queue.enqueue(chirpData); + chirpData.clear(); + m_chirpSamples = 0; + } + } + m_rxSamples += 64; + + if (m_rxSamples == 2*BUFFER_SIZE) { + + m_chirpDspEngine->fft->DoFFTWForward(cpxIn, cpxOut, 2*BUFFER_SIZE); + + // reorder the spectrum buffer + for (int i = 0; i < BUFFER_SIZE; i++) { + + m_spectrumBuffer[topsize - i] = + (float)(10.0 * log10(MagCPX(cpxOut[i+BUFFER_SIZE]) + 1.5E-45)); + m_spectrumBuffer[BUFFER_SIZE - i] = + (float)(10.0 * log10(MagCPX(cpxOut[i]) + 1.5E-45)); + } + + /*float specMean = 0.0f; + for (int i = BUFFER_SIZE+20; i < BUFFER_SIZE+105; i++) { + + specMean += m_spectrumBuffer[i]; + if (m_spectrumBuffer[i] > specMax) specMax = m_spectrumBuffer[i]; + if (m_spectrumBuffer[i] < specMin) specMin = m_spectrumBuffer[i]; + }*/ + //specMean *= 1.0f/BUFFER_SIZE; + //DATA_PROCESSOR_DEBUG << "pan min" << specMin << "max" << specMax << "mean" << specMean; + + SleeperThread::usleep(42667); + + //emit spectrumBufferChanged(m_spectrumBuffer); + //set->setSpectrumBuffer(m_spectrumBuffer); + //set->setSpectrumBuffer(0, m_spectrumBuffer); + + m_rxSamples = 0; + } +} + + +//***************************************************************************** +// + +void DataEngine::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + io.mutex.lock(); + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; + + io.mutex.unlock(); +} + +void DataEngine::setSystemState( + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode statemode, + QSDR::_DataEngineState enginestate) +{ + io.networkIOMutex.lock(); + set->setSystemState(this, err, hwmode, statemode, enginestate); + io.networkIOMutex.unlock(); +} + +float DataEngine::getFilterSizeCalibrationOffset() { + + //int size=1024; // dspBufferSize + float i = log10((qreal) BUFFER_SIZE); + return 3.0f*(11.0f - i); +} + +void DataEngine::searchHpsdrNetworkDevices() { + + if (!m_discoverer) createDiscoverer(); + + // HPSDR network IO thread + if (!startDiscoverer(QThread::NormalPriority)) { + + DATA_ENGINE_DEBUG << "HPSDR network discovery thread could not be started."; + return; + } + + io.networkIOMutex.lock(); + io.devicefound.wait(&io.networkIOMutex); + + //m_discoverer->findHPSDRDevices(); + + // stop the discovery thread + io.networkIOMutex.unlock(); + stopDiscoverer(); +} + +void DataEngine::setHPSDRDeviceNumber(int value) { + + m_hpsdrDevices = value; +} + +void DataEngine::rxListChanged(QList list) { + + io.mutex.lock(); + RX = list; + io.mutex.unlock(); +} + +void DataEngine::setCurrentReceiver(QObject *sender, int rx) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.currentReceiver = rx; + io.mutex.unlock(); +} + +void DataEngine::setFramesPerSecond(QObject *sender, int rx, int value) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + Q_UNUSED(value) + + /*io.mutex.lock(); + if (m_fpsList.length() > 0) + m_fpsList[rx] = (int)(1000000.0/value); + io.mutex.unlock();*/ +} + +void DataEngine::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + io.mutex.lock(); + switch (value) { + + case 48000: + io.samplerate = value; + io.speed = 0; + io.outputMultiplier = 1; + break; + + case 96000: + io.samplerate = value; + io.speed = 1; + io.outputMultiplier = 2; + break; + + case 192000: + io.samplerate = value; + io.speed = 2; + io.outputMultiplier = 4; + break; + + case 384000: + io.samplerate = value; + io.speed = 3; + io.outputMultiplier = 8; + break; + + default: + DATA_ENGINE_DEBUG << "invalid sample rate !\n"; + stop(); + break; + } + + io.mutex.unlock(); + + emit outMultiplierEvent(io.outputMultiplier); +} + +void DataEngine::setMercuryAttenuator(QObject *sender, HamBand band, int value) { + + Q_UNUSED(sender) + Q_UNUSED(band) + + io.mutex.lock(); + io.ccTx.mercuryAttenuator = value; + io.mutex.unlock(); +} + +void DataEngine::setMercuryAttenuators(QObject *sender, QList attn) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.ccTx.mercuryAttenuators = attn; + io.mutex.unlock(); +} + +void DataEngine::setDither(QObject *sender, int value) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.ccTx.dither = value; + io.mutex.unlock(); +} + +void DataEngine::setRandom(QObject *sender, int value) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.ccTx.random = value; + io.mutex.unlock(); +} + +void DataEngine::set10MhzSource(QObject *sender, int source) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.control_out[1] = io.control_out[1] & 0xF3; + io.control_out[1] = io.control_out[1] | (source << 2); + io.mutex.unlock(); +} + +void DataEngine::set122_88MhzSource(QObject *sender, int source) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.control_out[1] = io.control_out[1] & 0xEF; + io.control_out[1] = io.control_out[1] | (source << 4); + io.mutex.unlock(); +} + +void DataEngine::setMicSource(QObject *sender, int source) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.control_out[1] = io.control_out[1] & 0x7F; + io.control_out[1] = io.control_out[1] | (source << 7); + io.mutex.unlock(); +} + +void DataEngine::setMercuryClass(QObject *sender, int value) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.rxClass = value; + io.mutex.unlock(); +} + +void DataEngine::setMercuryTiming(QObject *sender, int value) { + + Q_UNUSED(sender) + + io.mutex.lock(); + io.timing = value; + io.mutex.unlock(); +} + +void DataEngine::setAlexConfiguration(quint16 conf) { + + io.mutex.lock(); + io.ccTx.alexConfig = conf; + DATA_ENGINE_DEBUG << "Alex Configuration = " << io.ccTx.alexConfig; + io.mutex.unlock(); +} + +void DataEngine::setAlexStates(HamBand band, const QList &states) { + + Q_UNUSED (band) + + io.mutex.lock(); + io.ccTx.alexStates = states; + DATA_ENGINE_DEBUG << "Alex States = " << io.ccTx.alexStates; + io.mutex.unlock(); +} + +void DataEngine::setPennyOCEnabled(bool value) { + + io.mutex.lock(); + io.ccTx.pennyOCenabled = value; + io.mutex.unlock(); +} + +void DataEngine::setRxJ6Pins(const QList &list) { + + io.mutex.lock(); + io.ccTx.rxJ6pinList = list; + io.mutex.unlock(); + +} + +void DataEngine::setTxJ6Pins(const QList &list) { + + io.mutex.lock(); + io.ccTx.txJ6pinList = list; + io.mutex.unlock(); +} + +void DataEngine::setRcveIQSignal(QObject *sender, int value) { + + emit rcveIQEvent(sender, value); +} + +void DataEngine::setPenelopeVersion(QObject *sender, int version) { + + emit penelopeVersionInfoEvent(sender, version); +} + +void DataEngine::setHwIOVersion(QObject *sender, int version) { + + emit hwIOVersionInfoEvent(sender, version); +} + +void DataEngine::setNumberOfRx(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (io.receivers == value) return; + + io.mutex.lock(); + io.receivers = value; + io.mutex.unlock(); + //io.control_out[4] &= 0xc7; + //io.control_out[4] |= (value - 1) << 3; + + DATA_ENGINE_DEBUG << "number of receivers set to " << QString::number(value); +} + +void DataEngine::setTimeStamp(QObject *sender, bool value) { + + Q_UNUSED(sender) + + if (io.timeStamp == value) return; + + io.mutex.lock(); + io.timeStamp = value; + io.mutex.unlock(); + //io.control_out[4] &= 0xc7; + io.control_out[4] |= value << 6; + + if (value) + DATA_ENGINE_DEBUG << "set time stamp on"; + else + DATA_ENGINE_DEBUG << "set time stamp off"; +} + +void DataEngine::setRxSocketState(int rx, const char* prop, QString str) { + + RX[rx]->setProperty(prop, str); + set->setRxList(RX); +} + +void DataEngine::setRxPeerAddress(int rx, QHostAddress address) { + + RX[rx]->setPeerAddress(address); + set->setRxList(RX); +} + +void DataEngine::setRx(int rx) { + + io.mutex.lock(); + RX[rx]->setReceiver(rx); + set->setRxList(RX); + io.mutex.unlock(); +} + +void DataEngine::setRxClient(int rx, int client) { + + io.mutex.lock(); + RX[rx]->setClient(client); + set->setRxList(RX); + io.mutex.unlock(); +} + +void DataEngine::setClientConnected(QObject* sender, int rx) { + + Q_UNUSED(sender) + + if (!io.clientList.contains(rx)) { + + io.clientList.append(rx); + io.audio_rx = rx; + + m_AudioRcvrThread->quit(); + m_AudioRcvrThread->wait(); + m_AudioRcvrThread->start(); + } + else { + + io.sendIQ_toggle = true; + io.rcveIQ_toggle = false; + m_AudioRcvrThread->start(); + } +} + +void DataEngine::setClientConnected(bool value) { + + m_clientConnected = value; +} + +void DataEngine::setClientDisconnected(int client) { + + Q_UNUSED(client) + /*if (m_clientConnected) { + + m_AudioRcvrThread->quit(); + m_AudioRcvrThread->wait(); + if (!m_AudioRcvrThread->isRunning()) + DATA_ENGINE_DEBUG << "audio receiver thread stopped."; + + m_clientConnected = false; + } + sync_toggle = true; + adc_toggle = false;*/ +} + +//void DataEngine::setAudioInProcessorRunning(bool value) { +// +// //m_audioInProcessorRunning = value; +//} + +void DataEngine::setAudioReceiver(QObject *sender, int rx) { + + Q_UNUSED(sender) + + io.mutex.lock(); + emit audioRxEvent(rx); + io.mutex.unlock(); +} + +void DataEngine::setIQPort(int rx, int port) { + + io.mutex.lock(); + RX[rx]->setIQPort(port); + set->setRxList(RX); + io.mutex.unlock(); +} + +void DataEngine::setRxConnectedStatus(QObject* sender, int rx, bool value) { + + Q_UNUSED(sender) + + io.mutex.lock(); + RX[rx]->setConnectedStatus(value); + set->setRxList(RX); + io.mutex.unlock(); +} + +void DataEngine::setHamBand(QObject *sender, int rx, bool byBtn, HamBand band) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + Q_UNUSED(byBtn) + + io.mutex.lock(); + io.ccTx.currentBand = band; + io.mutex.unlock(); +} + +void DataEngine::setFrequency(QObject* sender, int mode, int rx, long frequency) { + + Q_UNUSED (sender) + Q_UNUSED (mode) + + //RX[rx]->setFrequency(frequency); + RX[rx]->setCtrFrequency(frequency); + io.rx_freq_change = rx; + io.tx_freq_change = rx; +} + +void DataEngine::loadWavFile(const QString &fileName) { + + if (m_audioEngine->loadFile(fileName)) + m_soundFileLoaded = true; + else + m_soundFileLoaded = false; +} + +void DataEngine::suspend() { + + m_audioEngine->suspend(); +} + +void DataEngine::startPlayback() { + + m_audioEngine->startPlayback(); +} + +void DataEngine::showSettingsDialog() { + + m_audioEngine->showSettingsDialog(); +} + +void DataEngine::setAudioFileFormat(QObject *sender, const QAudioFormat &format) { + + Q_UNUSED (sender) + Q_UNUSED (format) +} + +void DataEngine::setAudioFilePosition(QObject *sender, qint64 position) { + + Q_UNUSED (sender) + Q_UNUSED (position) +} + +void DataEngine::setAudioFileBuffer(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer) { + + Q_UNUSED (sender) + + m_audioFileBufferPosition = position; + m_audioFileBufferLength = length; + m_audioFileBuffer = buffer; + + //DATA_ENGINE_DEBUG << "audio file length" << m_audioFileBufferLength; +} + +void DataEngine::setAudioFileBuffer(const QList &buffer) { + + io.inputBuffer = buffer; + + /*for (int i = 0; i < buffer.length(); i++) { + + DATA_ENGINE_DEBUG << "i" << i << "audioBuffer" << io.inputBuffer.at(i); + }*/ +} + +// ********************************************************************* +// Data processor + +DataProcessor::DataProcessor( + DataEngine *de, + QSDR::_ServerMode serverMode, + QSDR::_HWInterfaceMode hwMode) + : QObject() + , de(de) + , set(Settings::instance()) + , m_dataProcessorSocket(0) + , m_serverMode(serverMode) + , m_hwInterface(hwMode) + , m_socketConnected(false) + , m_setNetworkDeviceHeader(true) + , m_chirpGateBit(true) + , m_chirpBit(false) + , m_chirpStart(false) + , m_bytes(0) + , m_offset(0) + , m_length(0) + , m_rxSamples(0) + , m_chirpSamples(0) + , m_chirpStartSample(0) + , m_idx(IO_HEADER_SIZE) + , m_sendState(0) + , m_stopped(false) +{ + m_IQSequence = 0L; + m_sequenceHi = 0L; + + m_IQDatagram.resize(0); + + m_SyncChangedTime.start(); + m_ADCChangedTime.start(); + + m_fwCount = 0; + + m_sendSequence = 0L; + m_oldSendSequence = 0L; + + m_deviceSendDataSignature.resize(4); + m_deviceSendDataSignature[0] = (char)0xEF; + m_deviceSendDataSignature[1] = (char)0xFE; + m_deviceSendDataSignature[2] = (char)0x01; + m_deviceSendDataSignature[3] = (char)0x02; + + //socket = new QUdpSocket(); + m_deviceAddress = set->getCurrentMetisCard().ip_address; +} + +DataProcessor::~DataProcessor() { +} + +void DataProcessor::stop() { + + m_stopped = true; +} + +void DataProcessor::initDataProcessorSocket() { + + m_dataProcessorSocket = new QUdpSocket(); + + /*m_dataProcessorSocket->bind(QHostAddress(set->getHPSDRDeviceLocalAddr()), + 23000, + QUdpSocket::ReuseAddressHint | QUdpSocket::ShareAddress); + + int newBufferSize = 64 * 1024; + + if (::setsockopt(m_dataProcessorSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&newBufferSize, sizeof(newBufferSize)) == -1) { + + DATA_ENGINE_DEBUG << "initDataProcessorSocket error setting m_dataProcessorSocket buffer size."; + }*/ + + //m_dataProcessorSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1); + //m_dataProcessorSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1); + + CHECKED_CONNECT( + m_dataProcessorSocket, + SIGNAL(error(QAbstractSocket::SocketError)), + this, + SLOT(displayDataProcessorSocketError(QAbstractSocket::SocketError))); +} + +void DataProcessor::displayDataProcessorSocketError(QAbstractSocket::SocketError error) { + + DATA_PROCESSOR_DEBUG << "data processor socket error: " << error; +} + +void DataProcessor::processDeviceData() { + + //if (m_serverMode == QSDR::ExternalDSP) + // initDataProcessorSocket(); + + DATA_PROCESSOR_DEBUG << "Data Processor thread: " << this->thread(); + forever { + + //m_dataEngine->processInputBuffer(m_dataEngine->io.iq_queue.dequeue()); + QByteArray buf = de->io.iq_queue.dequeue(); + //de->processInputBuffer(buf.left(BUFFER_SIZE/2)); + //de->processInputBuffer(buf.right(BUFFER_SIZE/2)); + + processInputBuffer(buf.left(BUFFER_SIZE/2)); + processInputBuffer(buf.right(BUFFER_SIZE/2)); + + if (de->io.iq_queue.isFull()) { + DATA_PROCESSOR_DEBUG << "IQ queue full!"; + } + + QMutexLocker locker(&m_mutex); + if (m_stopped) { + m_stopped = false; + break; + } + } + +// if (m_serverMode == QSDR::ExternalDSP) { +// +// disconnect(this); +// m_dataProcessorSocket->close(); +// delete m_dataProcessorSocket; +// m_dataProcessorSocket = NULL; +// +// m_socketConnected = false; +// } +} + +void DataProcessor::processData() { + + forever { + + de->processFileBuffer(de->io.data_queue.dequeue()); + + m_mutex.lock(); + if (m_stopped) { + m_stopped = false; + m_mutex.unlock(); + break; + } + m_mutex.unlock(); + } +} + +void DataProcessor::externalDspProcessing(int rx) { + + // keep UDP packets < 512 bytes + // 8 bytes sequency number, 2 bytes offset, 2 bytes length, 500 bytes data + + if (!m_socketConnected) { + + m_dataProcessorSocket->connectToHost(de->RX[rx]->getPeerAddress(), de->RX[rx]->getIQPort()); + +#if defined(Q_OS_WIN32) + //int newBufferSize = 64 * 1024; + int newBufferSize = 16 * 1024; + + if (::setsockopt(m_dataProcessorSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&newBufferSize, sizeof(newBufferSize)) == -1) { + + DATA_PROCESSOR_DEBUG << "externalDspProcessing error setting m_dataProcessorSocket buffer size."; + } +#endif + + m_socketConnected = true; + } + +#ifndef __linux__ + m_sequenceHi = 0L; +#endif + + /*QUdpSocket socket; + CHECKED_CONNECT(&socket, + SIGNAL(error(QAbstractSocket::SocketError)), + this, + SLOT(displayDataProcessorSocketError(QAbstractSocket::SocketError)));*/ + + m_offset = 0; + //m_IQDatagram.append(reinterpret_cast(&m_dataEngine->rxList[rx]->input_buffer), sizeof(m_dataEngine->rxList[rx]->input_buffer)); + m_IQDatagram.append(reinterpret_cast(&de->RX[rx]->inBuf), sizeof(de->RX[rx]->inBuf)); + + m_IQDatagram.append(reinterpret_cast(&de->RX[rx]->inBuf), sizeof(de->RX[rx]->inBuf)); + + while (m_offset < m_IQDatagram.size()) { + + m_length = m_IQDatagram.size() - m_offset; + + if (m_length > 500) + m_length = 500; + + QByteArray datagram; + datagram += QByteArray(reinterpret_cast(&m_IQSequence), sizeof(m_IQSequence)); + datagram += QByteArray(reinterpret_cast(&m_sequenceHi), sizeof(m_sequenceHi)); + datagram += QByteArray(reinterpret_cast(&m_offset), sizeof(m_offset)); + datagram += QByteArray(reinterpret_cast(&m_length), sizeof(m_length)); + datagram += m_IQDatagram.mid(m_offset, m_length); + + if (m_dataProcessorSocket->write(datagram) < 0) + /*if (m_dataProcessorSocket->writeDatagram(datagram, + m_dataEngine->rxList[rx]->getPeerAddress(), + m_dataEngine->rxList[rx]->getIQPort()) < 0)*/ + //if (socket.writeDatagram(datagram, + // m_dataEngine->rxList[rx]->getPeerAddress(), + // m_dataEngine->rxList[rx]->getIQPort()) < 0) + { + if (!de->io.sendIQ_toggle) { // toggles the sendIQ signal + + de->set->setSendIQ(2); + de->io.sendIQ_toggle = true; + } + + DATA_ENGINE_DEBUG << "externalDspProcessing error sending data to client:" + << m_dataProcessorSocket->errorString(); + } + else { + + //socket.flush(); + if (de->io.sendIQ_toggle) { // toggles the sendIQ signal + + de->set->setSendIQ(1); + de->io.sendIQ_toggle = false; + } + } + m_offset += m_length; + } + m_IQDatagram.resize(0); + m_IQSequence++; +} + +void DataProcessor::externalDspProcessingBig(int rx) { + + m_IQDatagram.append(reinterpret_cast(&de->RX[rx]->in), sizeof(de->RX[rx]->in)); + + if (m_dataProcessorSocket->writeDatagram(m_IQDatagram.data(), + m_IQDatagram.size(), + de->RX[rx]->getPeerAddress(), + de->RX[rx]->getIQPort()) < 0) + + { + if (!de->io.sendIQ_toggle) { // toggles the sendIQ signal + + de->set->setSendIQ(2); + de->io.sendIQ_toggle = true; + } + + DATA_PROCESSOR_DEBUG << "error sending data to client:" << m_dataProcessorSocket->errorString(); + } + else { + + m_dataProcessorSocket->flush(); + if (de->io.sendIQ_toggle) { // toggles the sendIQ signal + + de->set->setSendIQ(1); + de->io.sendIQ_toggle = false; + } + } + m_IQDatagram.resize(0); +} + +void DataProcessor::processInputBuffer(const QByteArray &buffer) { + + //DATA_PROCESSOR_DEBUG << "processInputBuffer: " << this->thread(); + int s = 0; + + if (buffer.at(s++) == SYNC && buffer.at(s++) == SYNC && buffer.at(s++) == SYNC) + { + // extract C&C bytes + decodeCCBytes(buffer.mid(3, 5)); + s += 5; + + switch (de->io.receivers) + { + case 1: m_maxSamples = 512-0; break; + case 2: m_maxSamples = 512-0; break; + case 3: m_maxSamples = 512-4; break; + case 4: m_maxSamples = 512-10; break; + case 5: m_maxSamples = 512-24; break; + case 6: m_maxSamples = 512-10; break; + case 7: m_maxSamples = 512-20; break; + case 8: m_maxSamples = 512-4; break; + } + + // extract the samples + while (s < m_maxSamples) + { + // extract each of the receivers + for (int r = 0; r < de->io.receivers; r++) + { + m_leftSample = (int)(( signed char) buffer.at(s++)) << 16; + m_leftSample += (int)((unsigned char) buffer.at(s++)) << 8; + m_leftSample += (int)((unsigned char) buffer.at(s++)); + m_rightSample = (int)(( signed char) buffer.at(s++)) << 16; + m_rightSample += (int)((unsigned char) buffer.at(s++)) << 8; + m_rightSample += (int)((unsigned char) buffer.at(s++)); + + m_lsample = (float)(m_leftSample / 8388607.0f); + m_rsample = (float)(m_rightSample / 8388607.0f); + + /*if (m_serverMode == QSDR::ChirpWSPR && + m_chirpInititalized && + m_chirpSamples < io.samplerate) + { + chirpData << m_lsample; + chirpData << m_rsample; + }*/ + + if (de->RX.at(r)->qtdsp) { + + de->RX[r]->inBuf[m_rxSamples].re = m_lsample; // 24 bit sample + de->RX[r]->inBuf[m_rxSamples].im = m_rsample; // 24 bit sample + } + } + + m_micSample = (int)((signed char) buffer.at(s++)) << 8; + + // extract chirp signal time stamp + //m_chirpBit = (buffer.at(s) & 0x01);// == 0x01; + + m_micSample += (int)((unsigned char) buffer.at(s++)); + m_micSample_float = (float) m_micSample / 32767.0f * de->io.mic_gain; // 16 bit sample + + // add to buffer + de->io.mic_left_buffer[m_rxSamples] = m_micSample_float; + de->io.mic_right_buffer[m_rxSamples] = 0.0f; + + ////m_chirpSamples++; + + //if (m_serverMode == QSDR::ChirpWSPR && m_chirpInititalized) + //{ + // if (m_chirpBit) + // { + // if (m_chirpGateBit) + // { + // // we've found the rising edge of the GPS 1PPS signal, so we set the samples + // // counter back to zero in order to have a simple and precise synchronisation + // // with the local chirp. + // io.networkIOMutex.lock(); + // DATA_ENGINE_DEBUG << "GPS 1 PPS"; + // io.networkIOMutex.unlock(); + + // // remove the last sample (real and imag) and enqueue the buffer + // chirpData.removeLast(); + // chirpData.removeLast(); + // io.chirp_queue.enqueue(chirpData); + + // // empty the buffer and add the last sample, which is the starting point of the chirp + // m_chirpSamples = 0; + // chirpData.clear(); + + // chirpData << m_lsample; + // chirpData << m_rsample; + + // m_chirpStart = true; + // m_chirpStartSample = m_rxSamples; + // m_chirpGateBit = false; + // } + // } + // else + // m_chirpGateBit = true; + //} + m_rxSamples++; + m_chirpSamples++; + + // when we have enough rx samples we start the DSP processing. + if (m_rxSamples == BUFFER_SIZE) { + + for (int r = 0; r < de->io.receivers; r++) { + + if (de->RX.at(r)->qtdsp) { + + QMetaObject::invokeMethod(de->RX.at(r), "dspProcessing", Qt::DirectConnection);// Qt::QueuedConnection); + } + } + m_rxSamples = 0; + } + } + } + else { + + if (m_SyncChangedTime.elapsed() > 10) { + + set->setProtocolSync(2); + m_SyncChangedTime.restart(); + } + } +} + +void DataProcessor::decodeCCBytes(const QByteArray &buffer) { + + de->io.ccRx.ptt = (bool)((buffer.at(0) & 0x01) == 0x01); + de->io.ccRx.dash = (bool)((buffer.at(0) & 0x02) == 0x02); + de->io.ccRx.dot = (bool)((buffer.at(0) & 0x04) == 0x04); + de->io.ccRx.lt2208 = (bool)((buffer.at(1) & 0x01) == 0x01); + + de->io.ccRx.roundRobin = (uchar)(buffer.at(0) >> 3); + + switch (de->io.ccRx.roundRobin) // cycle through C0 + { + case 0: + + if (de->io.ccRx.lt2208) // check ADC signal + { + if (m_ADCChangedTime.elapsed() > 50) + { + set->setADCOverflow(2); + m_ADCChangedTime.restart(); + } + } + + //qDebug() << "CC: " << io.ccRx.roundRobin; + if (m_hwInterface == QSDR::Hermes) + { + de->io.ccRx.hermesI01 = (bool)((buffer.at(1) & 0x02) == 0x02); + de->io.ccRx.hermesI02 = (bool)((buffer.at(1) & 0x04) == 0x04); + de->io.ccRx.hermesI03 = (bool)((buffer.at(1) & 0x08) == 0x08); + de->io.ccRx.hermesI04 = (bool)((buffer.at(1) & 0x10) == 0x10); + //qDebug() << "Hermes IO 1: " << io.ccRx.hermesI01 + // << "2: " << io.ccRx.hermesI02 + // << "3: " << io.ccRx.hermesI03 + // << "4: " << io.ccRx.hermesI04; + } + + if (m_fwCount < 100) + { + if (m_hwInterface == QSDR::Metis) + { + if (de->io.ccRx.devices.mercuryFWVersion != buffer.at(2)) + { + de->io.ccRx.devices.mercuryFWVersion = buffer.at(2); + set->setMercuryVersion(de->io.ccRx.devices.mercuryFWVersion); + de->io.networkIOMutex.lock(); + DATA_PROCESSOR_DEBUG << "Mercury firmware version: " << qPrintable(QString::number(buffer.at(2))); + de->io.networkIOMutex.unlock(); + } + + if (de->io.ccRx.devices.penelopeFWVersion != buffer.at(3)) + { + de->io.ccRx.devices.penelopeFWVersion = buffer.at(3); + de->io.ccRx.devices.pennylaneFWVersion = buffer.at(3); + set->setPenelopeVersion(de->io.ccRx.devices.penelopeFWVersion); + set->setPennyLaneVersion(de->io.ccRx.devices.penelopeFWVersion); + de->io.networkIOMutex.lock(); + DATA_PROCESSOR_DEBUG << "Penelope/Pennylane firmware version: " << qPrintable(QString::number(buffer.at(3))); + de->io.networkIOMutex.unlock(); + } + + if (de->io.ccRx.devices.metisFWVersion != buffer.at(4)) + { + de->io.ccRx.devices.metisFWVersion = buffer.at(4); + set->setMetisVersion(de->io.ccRx.devices.metisFWVersion); + de->io.networkIOMutex.lock(); + DATA_PROCESSOR_DEBUG << "Metis firmware version: " << qPrintable(QString::number(buffer.at(4))); + de->io.networkIOMutex.unlock(); + } + } + else if (set->getHWInterface() == QSDR::Hermes) { + + if (de->io.ccRx.devices.hermesFWVersion != buffer.at(4)) { + + de->io.ccRx.devices.hermesFWVersion = buffer.at(4); + set->setHermesVersion(de->io.ccRx.devices.hermesFWVersion); + de->io.networkIOMutex.lock(); + DATA_ENGINE_DEBUG << "Hermes firmware version: " << qPrintable(QString::number(buffer.at(4))); + de->io.networkIOMutex.unlock(); + } + } + m_fwCount++; + } + break; + + case 1: + + //qDebug() << "CC: " << io.ccRx.roundRobin; + // forward power + if (set->getPenelopePresence() || (m_hwInterface == QSDR::Hermes)) { // || set->getPennyLanePresence() + + de->io.ccRx.ain5 = (quint16)((quint16)(buffer.at(1) << 8) + (quint16)buffer.at(2)); + + de->io.penelopeForwardVolts = (qreal)(3.3 * (qreal)de->io.ccRx.ain5 / 4095.0); + de->io.penelopeForwardPower = (qreal)(de->io.penelopeForwardVolts * de->io.penelopeForwardVolts / 0.09); + } + //qDebug() << "penelopeForwardVolts: " << io.penelopeForwardVolts << "penelopeForwardPower" << io.penelopeForwardPower; + + if (set->getAlexPresence()) { //|| set->getApolloPresence()) { + + de->io.ccRx.ain1 = (quint16)((quint16)(buffer.at(3) << 8) + (quint16)buffer.at(4)); + + de->io.alexForwardVolts = (qreal)(3.3 * (qreal)de->io.ccRx.ain1 / 4095.0); + de->io.alexForwardPower = (qreal)(de->io.alexForwardVolts * de->io.alexForwardVolts / 0.09); + } + //qDebug() << "alexForwardVolts: " << io.alexForwardVolts << "alexForwardPower" << io.alexForwardPower; + break; + + case 2: + + //qDebug() << "CC: " << io.ccRx.roundRobin; + // reverse power + if (set->getAlexPresence()) { //|| set->getApolloPresence()) { + + de->io.ccRx.ain2 = (quint16)((quint16)(buffer.at(1) << 8) + (quint16)buffer.at(2)); + + de->io.alexReverseVolts = (qreal)(3.3 * (qreal)de->io.ccRx.ain2 / 4095.0); + de->io.alexReversePower = (qreal)(de->io.alexReverseVolts * de->io.alexReverseVolts / 0.09); + } + //qDebug() << "alexReverseVolts: " << io.alexReverseVolts << "alexReversePower" << io.alexReversePower; + + if (set->getPenelopePresence() || (m_hwInterface == QSDR::Hermes)) { // || set->getPennyLanePresence() { + + de->io.ccRx.ain3 = (quint16)((quint16)(buffer.at(3) << 8) + (quint16)buffer.at(4)); + de->io.ain3Volts = (qreal)(3.3 * (double)de->io.ccRx.ain3 / 4095.0); + } + //qDebug() << "ain3Volts: " << io.ain3Volts; + break; + + case 3: + + //qDebug() << "CC: " << io.ccRx.roundRobin; + + if (set->getPenelopePresence() || (m_hwInterface == QSDR::Hermes)) { // || set->getPennyLanePresence() { + + de->io.ccRx.ain4 = (quint16)((quint16)(buffer.at(1) << 8) + (quint16)buffer.at(2)); + de->io.ccRx.ain6 = (quint16)((quint16)(buffer.at(3) << 8) + (quint16)buffer.at(4)); + + de->io.ain4Volts = (qreal)(3.3 * (qreal)de->io.ccRx.ain4 / 4095.0); + + if (set->getHWInterface() == QSDR::Hermes) // read supply volts applied to board + de->io.supplyVolts = (qreal)((qreal)de->io.ccRx.ain6 / 186.0f); + } + //qDebug() << "ain4Volts: " << io.ain4Volts << "supplyVolts" << io.supplyVolts; + break; + + //case 4: + + // more than 1 Mercury module (currently not usable) + //qDebug() << "CC: " << io.ccRx.roundRobin; + //switch (io.receivers) { + + // case 1: + // io.ccRx.mercury1_LT2208 = (bool)((buffer.at(1) & 0x02) == 0x02); + // //qDebug() << "mercury1_LT2208: " << io.ccRx.mercury1_LT2208; + // break; + + // case 2: + // io.ccRx.mercury1_LT2208 = (bool)((buffer.at(1) & 0x02) == 0x02); + // io.ccRx.mercury2_LT2208 = (bool)((buffer.at(2) & 0x02) == 0x02); + // //qDebug() << "mercury1_LT2208: " << io.ccRx.mercury1_LT2208 << "mercury2_LT2208" << io.ccRx.mercury2_LT2208; + // break; + + // case 3: + // io.ccRx.mercury1_LT2208 = (bool)((buffer.at(1) & 0x02) == 0x02); + // io.ccRx.mercury2_LT2208 = (bool)((buffer.at(2) & 0x02) == 0x02); + // io.ccRx.mercury3_LT2208 = (bool)((buffer.at(3) & 0x02) == 0x02); + // //qDebug() << "mercury1_LT2208: " << io.ccRx.mercury1_LT2208 << "mercury2_LT2208" << io.ccRx.mercury2_LT2208; + // //qDebug() << "mercury3_LT2208: " << io.ccRx.mercury3_LT2208; + // break; + + // case 4: + // io.ccRx.mercury1_LT2208 = (bool)((buffer.at(1) & 0x02) == 0x02); + // io.ccRx.mercury2_LT2208 = (bool)((buffer.at(2) & 0x02) == 0x02); + // io.ccRx.mercury3_LT2208 = (bool)((buffer.at(3) & 0x02) == 0x02); + // io.ccRx.mercury4_LT2208 = (bool)((buffer.at(4) & 0x02) == 0x02); + // //qDebug() << "mercury1_LT2208: " << io.ccRx.mercury1_LT2208 << "mercury2_LT2208" << io.ccRx.mercury2_LT2208; + // //qDebug() << "mercury3_LT2208: " << io.ccRx.mercury3_LT2208 << "mercury4_LT2208" << io.ccRx.mercury4_LT2208; + // break; + //} + //break; + } // end switch cycle through C0 +} + +void DataProcessor::setOutputBuffer(int rx, const CPX &buffer) { + + if (rx == de->io.currentReceiver) { + processOutputBuffer(buffer); + } +} + +void DataProcessor::processOutputBuffer(const CPX &buffer) { + + //DATA_PROCESSOR_DEBUG << "processOutputBuffer: " << this->thread(); + + qint16 leftRXSample; + qint16 rightRXSample; + qint16 leftTXSample; + qint16 rightTXSample; + + // process the output + for (int j = 0; j < BUFFER_SIZE; j += de->io.outputMultiplier) { + + leftRXSample = (qint16)(buffer.at(j).re * 32767.0f); + rightRXSample = (qint16)(buffer.at(j).im * 32767.0f); + + leftTXSample = 0; + rightTXSample = 0; + + de->io.output_buffer[m_idx++] = leftRXSample >> 8; + de->io.output_buffer[m_idx++] = leftRXSample; + de->io.output_buffer[m_idx++] = rightRXSample >> 8; + de->io.output_buffer[m_idx++] = rightRXSample; + de->io.output_buffer[m_idx++] = leftTXSample >> 8; + de->io.output_buffer[m_idx++] = leftTXSample; + de->io.output_buffer[m_idx++] = rightTXSample >> 8; + de->io.output_buffer[m_idx++] = rightTXSample; + + if (m_idx == IO_BUFFER_SIZE) { + + //if (de->m_audioBuffer.length() == 1024) { + + // //m_audioEngine->setAudioBuffer(this, m_audioBuffer); + // de->m_audioBuffer.resize(0); + //} + // set the C&C bytes + encodeCCBytes(); + + switch (m_hwInterface) { + + case QSDR::Metis: + case QSDR::Hermes: + + de->io.audioDatagram.resize(IO_BUFFER_SIZE); + de->io.audioDatagram = QByteArray::fromRawData((const char *)&de->io.output_buffer, IO_BUFFER_SIZE); + + //if (m_dataIOThreadRunning) { + // de->m_dataIO->writeData(); + //} + + de->m_dataIO->sendAudio(de->io.output_buffer); //RRK + + writeData(); + break; + + case QSDR::NoInterfaceMode: + break; + } + m_idx = IO_HEADER_SIZE; + } + } +} + +void DataProcessor::encodeCCBytes() { + + de->io.output_buffer[0] = SYNC; + de->io.output_buffer[1] = SYNC; + de->io.output_buffer[2] = SYNC; + + de->io.mutex.lock(); + switch (m_sendState) { + + case 0: + + uchar rxAnt; + uchar rxOut; + uchar ant; + + de->io.control_out[0] = 0x0; // C0 + de->io.control_out[1] = 0x0; // C1 + de->io.control_out[2] = 0x0; // C2 + de->io.control_out[3] = 0x0; // C3 + de->io.control_out[4] = 0x0; // C4 + + // C0 + // 0 0 0 0 0 0 0 0 + // | + // +------------ MOX (1 = active, 0 = inactive) + + // set C1 + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + +------------ Speed (00 = 48kHz, 01 = 96kHz, 10 = 192kHz) + // | | | | + +---------------- 10MHz Ref. (00 = Atlas/Excalibur, 01 = Penelope, 10 = Mercury)* + // | | | +-------------------- 122.88MHz source (0 = Penelope, 1 = Mercury)* + // | + +---------------------- Config (00 = nil, 01 = Penelope, 10 = Mercury, 11 = both)* + // +-------------------------- Mic source (0 = Janus, 1 = Penelope)* + // + // * Ignored by Hermes + + de->io.control_out[1] |= de->io.speed; // sample rate + + de->io.control_out[1] &= 0x03; // 0 0 0 0 0 0 1 1 + de->io.control_out[1] |= de->io.ccTx.clockByte; + + // set C2 + // + // 0 0 0 0 0 0 0 0 + // | | | + // | | +------------ Mode (1 = Class E, 0 = All other modes) + // +---------- +-------------- Open Collector Outputs on Penelope or Hermes (bit 6...bit 0) + + de->io.control_out[2] = de->io.rxClass; + + if (de->io.ccTx.pennyOCenabled) { + + de->io.control_out[2] &= 0x1; // 0 0 0 0 0 0 0 1 + + if (de->io.ccTx.currentBand != (HamBand) gen) { + + if (de->io.ccTx.mox || de->io.ccTx.ptt) + de->io.control_out[2] |= (de->io.ccTx.txJ6pinList.at(de->io.ccTx.currentBand) >> 1) << 1; + else + de->io.control_out[2] |= (de->io.ccTx.rxJ6pinList.at(de->io.ccTx.currentBand) >> 1) << 1; + } + } + + + // set C3 + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + +------------ Alex Attenuator (00 = 0dB, 01 = 10dB, 10 = 20dB, 11 = 30dB) + // | | | | | +---------------- Preamp On/Off (0 = Off, 1 = On) + // | | | | +------------------ LT2208 Dither (0 = Off, 1 = On) + // | | | + ------------------- LT2208 Random (0= Off, 1 = On) + // | + + --------------------- Alex Rx Antenna (00 = none, 01 = Rx1, 10 = Rx2, 11 = XV) + // + ------------------------- Alex Rx out (0 = off, 1 = on). Set if Alex Rx Antenna > 00. + + + rxAnt = 0x07 & (de->io.ccTx.alexStates.at(de->io.ccTx.currentBand) >> 2); + rxOut = (rxAnt > 0) ? 1 : 0; + + de->io.control_out[3] = (de->io.ccTx.alexStates.at(de->io.ccTx.currentBand) >> 7); + + de->io.control_out[3] &= 0xFB; // 1 1 1 1 1 0 1 1 + de->io.control_out[3] |= (de->io.ccTx.mercuryAttenuator << 2); + + de->io.control_out[3] &= 0xF7; // 1 1 1 1 0 1 1 1 + de->io.control_out[3] |= (de->io.ccTx.dither << 3); + + de->io.control_out[3] &= 0xEF; // 1 1 1 0 1 1 1 1 + de->io.control_out[3] |= (de->io.ccTx.random << 4); + + de->io.control_out[3] &= 0x9F; // 1 0 0 1 1 1 1 1 + de->io.control_out[3] |= rxAnt << 5; + + de->io.control_out[3] &= 0x7F; // 0 1 1 1 1 1 1 1 + de->io.control_out[3] |= rxOut << 7; + + // set C4 + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | + + ----------- Alex Tx relay (00 = Tx1, 01= Tx2, 10 = Tx3) + // | | | | | + --------------- Duplex (0 = off, 1 = on) + // | | + + +------------------ Number of Receivers (000 = 1, 111 = 8) + // | +------------------------ Time stamp - 1PPS on LSB of Mic data (0 = off, 1 = on) + // +-------------------------- Common Mercury Frequency (0 = independent frequencies to Mercury + // Boards, 1 = same frequency to all Mercury boards) + + if (de->io.ccTx.mox || de->io.ccTx.ptt) + ant = (de->io.ccTx.alexStates.at(de->io.ccTx.currentBand) >> 5); + else + ant = de->io.ccTx.alexStates.at(de->io.ccTx.currentBand); + + de->io.control_out[4] |= (ant != 0) ? ant-1 : ant; + + de->io.control_out[4] &= 0xFB; // 1 1 1 1 1 0 1 1 + de->io.control_out[4] |= de->io.ccTx.duplex << 2; + + de->io.control_out[4] &= 0xC7; // 1 1 0 0 0 1 1 1 + de->io.control_out[4] |= (de->io.receivers - 1) << 3; + + de->io.control_out[4] &= 0xBF; // 1 0 1 1 1 1 1 1 + de->io.control_out[4] |= de->io.ccTx.timeStamp << 6; + + de->io.control_out[4] &= 0x7F; // 0 1 1 1 1 1 1 1 + de->io.control_out[4] |= de->io.ccTx.commonMercuryFrequencies << 7; + + // fill the out buffer with the C&C bytes + for (int i = 0; i < 5; i++) + de->io.output_buffer[i+3] = de->io.control_out[i]; + + m_sendState = 1; + break; + + case 1: + + // C0 + // 0 0 0 0 0 0 1 x C1, C2, C3, C4 NCO Frequency in Hz for Transmitter, Apollo ATU + // (32 bit binary representation - MSB in C1) + + de->io.output_buffer[3] = 0x2; // C0 + + if (de->io.tx_freq_change >= 0) { + + de->io.output_buffer[4] = de->RX.at(de->io.tx_freq_change)->getCtrFrequency() >> 24; + de->io.output_buffer[5] = de->RX.at(de->io.tx_freq_change)->getCtrFrequency() >> 16; + de->io.output_buffer[6] = de->RX.at(de->io.tx_freq_change)->getCtrFrequency() >> 8; + de->io.output_buffer[7] = de->RX.at(de->io.tx_freq_change)->getCtrFrequency(); + + de->io.tx_freq_change = -1; + } + + m_sendState = de->io.ccTx.duplex ? 2 : 3; + break; + + case 2: + + // C0 = 0 0 0 0 0 1 0 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver_1 + // C0 = 0 0 0 0 0 1 1 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver _2 + // C0 = 0 0 0 0 1 0 0 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver _3 + // C0 = 0 0 0 0 1 0 1 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver _4 + // C0 = 0 0 0 0 1 1 0 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver _5 + // C0 = 0 0 0 0 1 1 1 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver _6 + // C0 = 0 0 0 1 0 0 0 x C1, C2, C3, C4 NCO Frequency in Hz for Receiver _7 + + if (de->io.rx_freq_change >= 0) { + + de->io.output_buffer[3] = (de->io.rx_freq_change + 2) << 1; + de->io.output_buffer[4] = de->RX.at(de->io.rx_freq_change)->getCtrFrequency() >> 24; + de->io.output_buffer[5] = de->RX.at(de->io.rx_freq_change)->getCtrFrequency() >> 16; + de->io.output_buffer[6] = de->RX.at(de->io.rx_freq_change)->getCtrFrequency() >> 8; + de->io.output_buffer[7] = de->RX.at(de->io.rx_freq_change)->getCtrFrequency(); + + de->io.rx_freq_change = -1; + } + + m_sendState = 3; + break; + + case 3: + + de->io.control_out[0] = 0x12; // 0 0 0 1 0 0 1 0 + de->io.control_out[1] = 0x0; // C1 + de->io.control_out[2] = 0x0; // C2 + de->io.control_out[3] = 0x0; // C3 + de->io.control_out[4] = 0x0; // C4 + + // C1 + // 0 0 0 0 0 0 0 0 + // | | + // +-------------+------------ Hermes/PennyLane Drive Level (0-255) (ignored by Penelope) + + + // C2 + // 0 0 0 0 0 0 0 0 + // | | | | | | | | + // | | | | | | | +------------ Hermes/Metis Penelope Mic boost (0 = 0dB, 1 = 20dB) + // | | | | | | +-------------- Metis/Penelope or PennyLane Mic/Line-in (0 = mic, 1 = Line-in) + // | | | | | +---------------- Hermes - Enable/disable Apollo filter (0 = disable, 1 = enable) + // | | | | +------------------ Hermes - Enable/disable Apollo tuner (0 = disable, 1 = enable) + // | | | +-------------------- Hermes - Apollo auto tune (0 = end, 1 = start) + // | | +---------------------- Hermes - select filter board (0 = Alex, 1 = Apollo) + // | +------------------------ Alex - manual HPF/LPF filter select (0 = disable, 1 = enable) + // +-------------------------- VNA mode (0 = off, 1 = on) + + // Alex configuration: + // + // manual 0 + + de->io.control_out[2] &= 0xBF; // 1 0 1 1 1 1 1 1 + de->io.control_out[2] |= (de->io.ccTx.alexConfig & 0x01) << 6; + + // C3 + // 0 0 0 0 0 0 0 0 + // | | | | | | | + // | | | | | | +------------ Alex - select 13MHz HPF (0 = disable, 1 = enable)* + // | | | | | +-------------- Alex - select 20MHz HPF (0 = disable, 1 = enable)* + // | | | | +---------------- Alex - select 9.5MHz HPF (0 = disable, 1 = enable)* + // | | | +------------------ Alex - select 6.5MHz HPF (0 = disable, 1 = enable)* + // | | +-------------------- Alex - select 1.5MHz HPF (0 = disable, 1 = enable)* + // | +---------------------- Alex - Bypass all HPFs (0 = disable, 1 = enable)* + // +------------------------ Alex - 6M low noise amplifier (0 = disable, 1 = enable)* + // + // *Only valid when Alex - manual HPF/LPF filter select is enabled + + de->io.control_out[3] &= 0xFE; // 1 1 1 1 1 1 1 0 + // HPF 13 MHz: 1 0 0 0 0 0 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x40) >> 6; + + de->io.control_out[3] &= 0xFD; // 1 1 1 1 1 1 0 1 + // HPF 20 MHz: 1 0 0 0 0 0 0 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x80) >> 6; + + de->io.control_out[3] &= 0xFB; // 1 1 1 1 1 0 1 1 + // HPF 9.5 MHz: 1 0 0 0 0 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x20) >> 3; + + de->io.control_out[3] &= 0xF7; // 1 1 1 1 0 1 1 1 + // HPF 6.5 MHz: 1 0 0 0 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x10) >> 1; + + de->io.control_out[3] &= 0xEF; // 1 1 1 0 1 1 1 1 + // HPF 1.5 MHz: 1 0 0 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x08) << 1; + + de->io.control_out[3] &= 0xDF; // 1 1 0 1 1 1 1 1 + // bypass all: 1 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x02) << 4; + + de->io.control_out[3] &= 0xBF; // 1 0 1 1 1 1 1 1 + // 6m BPF/LNA: 1 0 0 + de->io.control_out[3] |= (de->io.ccTx.alexConfig & 0x04) << 4; + + de->io.control_out[3] &= 0x7F; // 0 1 1 1 1 1 1 1 + de->io.control_out[3] |= ((int)de->io.ccTx.vnaMode) << 7; + + // C4 + // 0 0 0 0 0 0 0 0 + // | | | | | | | + // | | | | | | +------------ Alex - select 30/20m LPF (0 = disable, 1 = enable)* + // | | | | | +-------------- Alex - select 60/40m LPF (0 = disable, 1 = enable)* + // | | | | +---------------- Alex - select 80m LPF (0 = disable, 1 = enable)* + // | | | +------------------ Alex - select 160m LPF (0 = disable, 1 = enable)* + // | | +-------------------- Alex - select 6m LPF (0 = disable, 1 = enable)* + // | +---------------------- Alex - select 12/10m LPF (0 = disable, 1 = enable)* + // +------------------------ Alex - select 17/15m LPF (0 = disable, 1 = enable)* + // + // *Only valid when Alex - manual HPF/LPF filter select is enabled + + de->io.control_out[4] &= 0xFE; // 1 1 1 1 1 1 1 0 + // LPF 30/20m: 1 0 0 0 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x800) >> 11; + + de->io.control_out[4] &= 0xFD; // 1 1 1 1 1 1 0 1 + // LPF 60/40m: 1 0 0 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x400) >> 9; + + de->io.control_out[4] &= 0xFB; // 1 1 1 1 1 0 1 1 + // LPF 80m: 1 0 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x200) >> 7; + + de->io.control_out[4] &= 0xF7; // 1 1 1 1 0 1 1 1 + // LPF 160m: 1 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x100) >> 5; + + de->io.control_out[4] &= 0xEF; // 1 1 1 0 1 1 1 1 + // LPF 6m: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x4000) >> 10; + + de->io.control_out[4] &= 0xDF; // 1 1 0 1 1 1 1 1 + // LPF 12/10m : 1 0 0 0 0 0 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x2000) >> 8; + + de->io.control_out[4] &= 0xBF; // 1 0 1 1 1 1 1 1 + // LPF 17/15m: 1 0 0 0 0 0 0 0 0 0 0 0 0 + de->io.control_out[4] |= (de->io.ccTx.alexConfig & 0x1000) >> 6; + + // fill the out buffer with the C&C bytes + for (int i = 0; i < 5; i++) + de->io.output_buffer[i+3] = de->io.control_out[i]; + + // round finished + m_sendState = 0; + break; + } + de->io.mutex.unlock(); + + + /*switch (m_hwInterface) { + + case QSDR::Metis: + case QSDR::Hermes: + + io.audioDatagram.resize(IO_BUFFER_SIZE); + io.audioDatagram = QByteArray::fromRawData((const char *)&io.output_buffer, IO_BUFFER_SIZE); + + if (m_dataIOThreadRunning) { + m_dataIO->writeData(); + } + break; + + case QSDR::NoInterfaceMode: + break; + }*/ +} + +void DataProcessor::writeData() { + + if (m_setNetworkDeviceHeader) { + + m_outDatagram.resize(0); + m_outDatagram += m_deviceSendDataSignature; + + QByteArray seq(reinterpret_cast(&m_sendSequence), sizeof(m_sendSequence)); + + m_outDatagram += seq; + m_outDatagram += de->io.audioDatagram; + + m_sendSequence++; + m_setNetworkDeviceHeader = false; + } + else { + + //QUdpSocket socket; + //DATA_PROCESSOR_DEBUG << "writeData: " << this->thread(); + m_outDatagram += de->io.audioDatagram; + + if (de->sendSocket->writeDatagram(m_outDatagram, m_deviceAddress, DEVICE_PORT) < 0) { + DATA_PROCESSOR_DEBUG << "error sending data to device: " << de->sendSocket->errorString(); + } + + //if (m_sendSequence%100 == 0) + // DATAIO_DEBUG << m_sendSequence; + + if (m_sendSequence != m_oldSendSequence + 1) { + DATA_PROCESSOR_DEBUG << "output sequence error: old = " << m_oldSendSequence << "; new =" << m_sendSequence; + } + + m_oldSendSequence = m_sendSequence; + m_setNetworkDeviceHeader = true; + } +} + + +// ********************************************************************* +// Audio out processor + +AudioOutProcessor::AudioOutProcessor(DataEngine *de, QSDR::_ServerMode serverMode) + : QObject() + , m_dataEngine(de) + , m_serverMode(serverMode) + , m_stopped(false) +{ + m_IQDatagram.resize(0); +} + +AudioOutProcessor::~AudioOutProcessor() { +} + +void AudioOutProcessor::stop() { + + m_stopped = true; +} + +void AudioOutProcessor::processDeviceData() { + + forever { + + //m_dataEngine->processInputBuffer(m_dataEngine->io.iq_queue.dequeue()); + //DATA_ENGINE_DEBUG << "IQ queue length:" << m_dataEngine->io.iq_queue.count(); + //DATA_ENGINE_DEBUG << "iq_queue length:" << m_dataEngine->io.iq_queue.dequeue().length(); + + m_mutex.lock(); + if (m_stopped) { + m_stopped = false; + m_mutex.unlock(); + break; + } + m_mutex.unlock(); + } +} + +void AudioOutProcessor::processData() { + + forever { + + //m_dataEngine->processFileBuffer(m_dataEngine->io.data_queue.dequeue()); + + m_mutex.lock(); + if (m_stopped) { + m_stopped = false; + m_mutex.unlock(); + break; + } + m_mutex.unlock(); + } +} + + +// ********************************************************************* +// Wide band data processor + +WideBandDataProcessor::WideBandDataProcessor(THPSDRParameter *ioData, QSDR::_ServerMode serverMode, int size) + : QObject() + , io(ioData) + , set(Settings::instance()) + , m_serverMode(serverMode) + , m_size(size) + , m_bytes(0) + , m_wbSpectrumAveraging(true) + , m_stopped(false) +{ + m_WBDatagram.resize(0); + + switch (m_serverMode) { + + case QSDR::SDRMode: + + wbFFT = new QFFT(m_size); + + cpxWBIn.resize(m_size); + cpxWBOut.resize(m_size); + + io->wbWindow.resize(m_size); + io->wbWindow.fill(0.0f); + + QFilter::MakeWindow(12, m_size, (float *)io->wbWindow.data()); // 12 = BLACKMANHARRIS_WINDOW + + wbAverager = new DualModeAverager(-1, m_size/2); + + break; + + //case QSDR::ExternalDSP: + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + break; + + case QSDR::NoServerMode: + case QSDR::DemoMode: + break; + } +} + +WideBandDataProcessor::~WideBandDataProcessor() { + + delete wbFFT; + + if (wbAverager) { + + delete wbAverager; + } + + cpxWBIn.clear(); + cpxWBOut.clear(); +} + +void WideBandDataProcessor::stop() { + + //mutex.lock(); + m_stopped = true; + //mutex.unlock(); +} + +void WideBandDataProcessor::processWideBandData() { + + forever { + + processWideBandInputBuffer(io->wb_queue.dequeue()); + + m_mutex.lock(); + if (m_stopped) { + m_stopped = false; + m_mutex.unlock(); + break; + } + m_mutex.unlock(); + } +} + +void WideBandDataProcessor::processWideBandInputBuffer(const QByteArray &buffer) { + + int size; + + //if (m_mercuryFW > 32 || m_hermesFW > 16) + if (io->mercuryFW > 32 || io->hermesFW > 11) + size = 2 * BIGWIDEBANDSIZE; + else + size = 2 * SMALLWIDEBANDSIZE; + + qint64 length = buffer.length(); + if (buffer.length() != size) { + + WIDEBAND_PROCESSOR_DEBUG << "wrong wide band buffer length: " << length; + return; + } + + int s; + float sample; + float norm = 1.0f / (4 * size); + + for (int i = 0; i < length; i += 2) { + + s = (int)((qint8 ) buffer.at(i+1)) << 8; + s += (int)((quint8) buffer.at(i)); + sample = (float)(s * norm); + + cpxWBIn[i/2].re = sample * io->wbWindow.at(i/2); + cpxWBIn[i/2].im = sample * io->wbWindow.at(i/2); + } + + wbFFT->DoFFTWForward(cpxWBIn, cpxWBOut, size/2); + + // averaging + QVector specBuf(size/4); + + m_mutex.lock(); + if (m_wbSpectrumAveraging) { + + for (int i = 0; i < size/4; i++) + specBuf[i] = (float)(10.0 * log10(MagCPX(cpxWBOut.at(i)) + 1.5E-45)); + + wbAverager->ProcessDBAverager(specBuf, specBuf); + m_mutex.unlock(); + } + else { + + for (int i = 0; i < size/4; i++) + specBuf[i] = (float)(10.0 * log10(MagCPX(cpxWBOut.at(i)) + 1.5E-45)); + + m_mutex.unlock(); + } + + //set->setWidebandSpectrumBuffer(specBuf); + emit wbSpectrumBufferChanged(specBuf); +} + +void WideBandDataProcessor::setWbSpectrumAveraging(QObject* sender, int rx, bool value) { + + Q_UNUSED (sender) + + if (rx != -1) return; + + m_mutex.lock(); + m_wbSpectrumAveraging = value; + m_mutex.unlock(); +} diff --git a/Source/src/DataEngine/cusdr_dataEngine.h b/Source/src/DataEngine/cusdr_dataEngine.h new file mode 100644 index 0000000..a1a7298 --- /dev/null +++ b/Source/src/DataEngine/cusdr_dataEngine.h @@ -0,0 +1,534 @@ +/** +* @file cusdr_dataEngine.h +* @brief cuSDR data engine header file +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-02 +*/ + +/* + * + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * using original C code by John Melton, G0ORX/N6LYT and Dave McMcQuate, WA8YWQ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_DATA_ENGINE_H +#define _CUSDR_DATA_ENGINE_H + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_settings.h" +#include "cusdr_dataIO.h" +#include "cusdr_receiver.h" +#include "cusdr_chirpProcessor.h" +#include "cusdr_audioReceiver.h" +#include "cusdr_discoverer.h" +#include "Util/qcircularbuffer.h" +#include "QtDSP/qtdsp_fft.h" +#include "QtDSP/qtdsp_filter.h" +#include "QtDSP/qtdsp_dualModeAverager.h" +#include "AudioEngine/cusdr_audio_engine.h" + +#ifdef LOG_DATA_ENGINE +# define DATA_ENGINE_DEBUG qDebug().nospace() << "DataEngine::\t" +#else +# define DATA_ENGINE_DEBUG nullDebug() +#endif + +#ifdef LOG_DATA_PROCESSOR +# define DATA_PROCESSOR_DEBUG qDebug().nospace() << "DataProcessor::\t" +#else +# define DATA_PROCESSOR_DEBUG nullDebug() +#endif + +#ifdef LOG_WIDEBAND_PROCESSOR +# define WIDEBAND_PROCESSOR_DEBUG qDebug().nospace() << "WidebandProcessor::\t" +#else +# define WIDEBAND_PROCESSOR_DEBUG nullDebug() +#endif + + +class DataProcessor; +class AudioOutProcessor; +class WideBandDataProcessor; + + +//Q_DECLARE_METATYPE (QAbstractSocket::SocketError) + + +// ********************************************************************* +// data engine class + +class DataEngine : public QObject { + + Q_OBJECT + +public: + DataEngine(QObject* parent = 0); + ~DataEngine(); + + Settings* set; + THPSDRParameter io; + + QList RX; + QList chirpData; + + QUdpSocket* sendSocket; + DataIO* m_dataIO; + +public slots: + bool initDataEngine(); + void stop(); + + // set Server parameter + void setRxPeerAddress(int rx, QHostAddress address); + void setRxClient(int rx, int client); + void setRx(int rx); + void setRxSocketState(int rx, const char* prop, QString); + + //void setSendIQSignal(QObject *sender, int value); + void setRcveIQSignal(QObject *sender, int value); + void setAudioReceiver(QObject *sender, int rx); + //void setAudioInProcessorRunning(bool value); + void setIQPort(int rx, int port); + void setRxConnectedStatus(QObject* sender, int rx, bool value); + void setClientConnected(QObject* sender, int rx); + void setClientConnected(bool value); + void setClientDisconnected(int client); + void setFramesPerSecond(QObject *sender, int rx, int value); + void createChirpDataProcessor(); + + // DSP processing + void processFileBuffer(const QList data); + + // change HPSDR hardware settings + void setPenelopeVersion(QObject *sender, int version); + void setHwIOVersion(QObject *sender, int version); + void setNumberOfRx(QObject *sender, int value); + void setSampleRate(QObject *sender, int value); + void setMercuryAttenuator(QObject *sender, HamBand band, int value); + void setDither(QObject *sender, int value); + void setRandom(QObject *sender, int value); + void setTimeStamp(QObject *sender, bool value); + void set10MhzSource(QObject *sender, int source); + void set122_88MhzSource(QObject *sender, int source); + void setMicSource(QObject *sender, int source); + void setMercuryClass(QObject *sender, int value); + void setMercuryTiming(QObject* sender, int value); + void setHamBand(QObject *sender, int rx, bool byBtn, HamBand band); + void setFrequency(QObject* sender, int mode, int rx, long frequency); + + void loadWavFile(const QString &fileName); + void suspend(); + void startPlayback(); + void showSettingsDialog(); + +private: + void setSystemState( + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void initAudioEngine(); + void setupConnections(); + void connectDSPSlots(); + void disconnectDSPSlots(); + void createDiscoverer(); + void createDataIO(); + void createDataProcessor(); + void createAudioOutProcessor(); + void createWideBandDataProcessor(); + //void createChirpDataProcessor(); + //void createAudioReceiver(int rx); + void createAudioReceiver(); + + bool initReceivers(int rx); + bool start(); + bool startDataEngineWithoutConnection(); + bool findHPSDRDevices(); + bool getFirmwareVersions(); + bool checkFirmwareVersions(); + bool startDiscoverer(QThread::Priority prio); + bool startDataIO(QThread::Priority prio); + bool startDataProcessor(QThread::Priority prio); + void startAudioOutProcessor(QThread::Priority prio); + bool startWideBandDataProcessor(QThread::Priority prio); + bool startChirpDataProcessor(QThread::Priority prio); + + void stopDiscoverer(); + void stopDataIO(); + void stopDataProcessor(); + void stopAudioOutProcessor(); + void stopWideBandDataProcessor(); + void stopChirpDataProcessor(); + void setHPSDRConfig(); + +private: + DataProcessor* m_dataProcessor; + WideBandDataProcessor* m_wbDataProcessor; + QDSPEngine* m_chirpDspEngine; + AudioReceiver* m_audioReceiver; + AudioEngine* m_audioEngine; + AudioOutProcessor* m_audioOutProcessor; + ChirpProcessor* m_chirpProcessor; + Discoverer* m_discoverer; + + QThreadEx* m_discoveryThread; + QThreadEx* m_dataIOThread; + QThreadEx* m_dataProcThread; + QThreadEx* m_wbDataProcThread; + QThreadEx* m_chirpDataProcThread; + QThreadEx* m_AudioRcvrThread; + QThreadEx* m_audioInProcThread; + QThreadEx* m_audioOutProcThread; + + QList m_dspThreadList; + + QMutex m_mutex; + + QString m_message; + QString m_HPSDRDevice; + + QByteArray m_commandDatagram; + QByteArray m_datagram; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QCircularBuffer audioringbuffer; + + TMeterType m_meterType; + + CPX cpxIn; + CPX cpxOut; + + bool m_restart; + bool m_networkDeviceRunning; + bool m_soundFileLoaded; + bool m_clientConnect; + //bool m_audioProcessorRunning; + bool m_chirpInititalized; + bool m_discoveryThreadRunning; + bool m_dataIOThreadRunning; + bool m_wbDataRcvrThreadRunning; + bool m_chirpDataProcThreadRunning; + bool m_dataProcThreadRunning; + bool m_audioRcvrThreadRunning; + bool m_audioInProcThreadRunning; + bool m_audioOutProcThreadRunning; + bool m_frequencyChange; + bool m_hamBandChanged; + bool m_chirpThreadStopped; + bool m_clientConnected; + + float m_mainVolume; + + int m_hpsdrDevices; + int m_fwCount; + int m_configure; + int m_timeout; + int m_txFrame; + int m_bytes; + int m_remainingTime; + int m_found; + int m_RxFrequencyChange; + int m_counter; + + int m_forwardPower; + int m_maxSamples; + int m_offset; + + int m_rxSamples; + int m_chirpSamples; + + int m_leftSample; + int m_rightSample; + int m_micSample; + + int m_spectrumSize; + int m_sendState; + + float m_lsample; + float m_rsample; + float m_scale; + float m_sMeterValue; + float m_sMeterCalibrationOffset; + float m_micSample_float; + float m_spectrumBuffer[SAMPLE_BUFFER_SIZE]; + + qint64 m_audioFileBufferPosition; + qint64 m_audioFileBufferLength; + QByteArray m_audioFileBuffer; + + float getFilterSizeCalibrationOffset(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + //void setCurrentNetworkDevice(TNetworkDevicecard card); + void setHPSDRDeviceNumber(int value); + void rxListChanged(QList rxList); + void searchHpsdrNetworkDevices(); + void setCurrentReceiver(QObject* sender, int rx); + + void setMercuryAttenuators(QObject *sender, QList attn); + void setAlexConfiguration(quint16 conf); + void setAlexStates(HamBand band, const QList &states); + void setPennyOCEnabled(bool value); + void setRxJ6Pins(const QList &list); + void setTxJ6Pins(const QList &list); + + void setAudioFileFormat(QObject *sender, const QAudioFormat &format); + void setAudioFilePosition(QObject *sender, qint64 position); + void setAudioFileBuffer(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + + void setAudioFileBuffer(const QList &buffer); + +signals: + void error(QUdpSocket::SocketError error); + void masterSwitchEvent(QObject *sender, bool power); + //void messageEvent(QString message); + void penelopeVersionInfoEvent(QObject *sender, int version); + void hwIOVersionInfoEvent(QObject *sender, int version); + void sendIQEvent(QObject *sender, int sendIQ); + void rcveIQEvent(QObject *sender, int value); + //void iqDataReady(int rx); + void chirpDataReady(int samples); + void audioDataReady(); + void clientConnectedEvent(int rx); + void audioRxEvent(int rx); + void outMultiplierEvent(int value); + void systemMessageEvent(const QString &str, int time); + void clearSystemMessageEvent(); + void DataProcessorReadyEvent(); + void audioSenderReadyEvent(bool value); +}; + + + +// ********************************************************************* +// Data processor class + +class DataProcessor : public QObject { + + Q_OBJECT + +public: + DataProcessor( + DataEngine* de = 0, + QSDR::_ServerMode serverMode = QSDR::NoServerMode, + QSDR::_HWInterfaceMode hwMode = QSDR::NoInterfaceMode); + + ~DataProcessor(); + +public slots: + void stop(); + void processData(); + void processDeviceData(); + void externalDspProcessing(int rx); + void externalDspProcessingBig(int rx); + +private slots: + void initDataProcessorSocket(); + void displayDataProcessorSocketError(QAbstractSocket::SocketError error); + void processInputBuffer(const QByteArray &buffer); + void processOutputBuffer(const CPX &buffer); + void decodeCCBytes(const QByteArray &buffer); + void encodeCCBytes(); + void setOutputBuffer(int rx, const CPX &buffer); + void writeData(); + +private: + DataEngine* de; + Settings* set; + QUdpSocket* m_dataProcessorSocket; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QHostAddress m_deviceAddress; + QMutex m_mutex; + QMutex m_spectrumMutex; + QByteArray m_IQDatagram; + QByteArray m_outDatagram; + QByteArray m_deviceSendDataSignature; + QString m_message; + + QTime m_SyncChangedTime; + QTime m_ADCChangedTime; + + bool m_socketConnected; + bool m_setNetworkDeviceHeader; + bool m_chirpGateBit; + bool m_chirpBit; + bool m_chirpStart; + + int m_leftSample; + int m_rightSample; + int m_micSample; + int m_bytes; + int m_maxSamples; + int m_rxSamples; + int m_chirpSamples; + int m_fwCount; + int m_idx; + int m_sendState; + int m_chirpStartSample; + + float m_lsample; + float m_rsample; + float m_micSample_float; + + unsigned long m_IQSequence; + unsigned long m_sequenceHi; + unsigned short m_offset; + unsigned short m_length; + + long m_sendSequence; + long m_oldSendSequence; + + volatile bool m_stopped; + + uchar m_ibuffer[IO_BUFFER_SIZE * IO_BUFFERS]; +signals: + void messageEvent(QString message); + void connectingEvent(QString addr, quint16 port); + void connectedEvent(QString addr, quint16 port); + void disconnectedEvent(); + void serverVersionEvent(QString version); +}; + + +// ********************************************************************* +// Audio out processor class + +class AudioOutProcessor : public QObject { + + Q_OBJECT + +public: + AudioOutProcessor(DataEngine* de = 0, QSDR::_ServerMode serverMode = QSDR::NoServerMode); + ~AudioOutProcessor(); + +public slots: + void stop(); + void processData(); + void processDeviceData(); + +private slots: + +private: + DataEngine* m_dataEngine; + + QMutex m_mutex; + QByteArray m_IQDatagram; + QString m_message; + + QSDR::_ServerMode m_serverMode; + + /*int m_bytes; + unsigned long m_IQSequence; + unsigned long m_sequenceHi; + unsigned short m_offset; + unsigned short m_length;*/ + volatile bool m_stopped; + +signals: + //void connectingEvent(QString addr, quint16 port); + //void connectedEvent(QString addr, quint16 port); + //void disconnectedEvent(); + //void serverVersionEvent(QString version); + ////void metisVersionEvent(QObject *sender, int version); + //void newData(); + //void newIQData(int rx); + //void newAudioDataEvent(float *lBuf, float *rBuf); +}; + +// ********************************************************************* +// Wide band data processor class + +class WideBandDataProcessor : public QObject { + + Q_OBJECT + +public: + WideBandDataProcessor(THPSDRParameter *ioData = 0, QSDR::_ServerMode serverMode = QSDR::NoServerMode, int size = 0); + ~WideBandDataProcessor(); + +public slots: + void stop(); + void processWideBandData(); + void setWbSpectrumAveraging(QObject* sender, int rx, bool value); + +private slots: + //void initDataProcessorSocket(); + //void displayDataProcessorSocketError(QAbstractSocket::SocketError error); + void processWideBandInputBuffer(const QByteArray &buffer); + +private: + THPSDRParameter* io; + Settings* set; + + QFFT* wbFFT; + DualModeAverager* wbAverager; + + CPX cpxWBIn; + CPX cpxWBOut; + + QMutex m_mutex; + QByteArray m_WBDatagram; + QString m_message; + + QSDR::_ServerMode m_serverMode; + + int m_size; + int m_bytes; + + bool m_wbSpectrumAveraging; + volatile bool m_stopped; + + unsigned char m_ibuffer[IO_BUFFER_SIZE * IO_BUFFERS]; + +signals: + void messageEvent(QString message); + void wbSpectrumBufferChanged(const qVectorFloat &buffer); +}; + + +#endif // _CUSDR_DATA_ENGINE_H diff --git a/Source/src/DataEngine/cusdr_dataIO.cpp b/Source/src/DataEngine/cusdr_dataIO.cpp new file mode 100644 index 0000000..acdfa80 --- /dev/null +++ b/Source/src/DataEngine/cusdr_dataIO.cpp @@ -0,0 +1,661 @@ +/** +* @file cusdr_dataIO.cpp +* @brief Data IO class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-10-01 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_DATAIO + +#include "cusdr_dataIO.h" +#include "soundout.h" + +#if defined(Q_OS_WIN32) +#include +#endif +#include +using namespace std; + + +DataIO::DataIO(THPSDRParameter *ioData) + : QObject() + , set(Settings::instance()) + , io(ioData) + , m_dataIOSocketOn(false) + , m_setNetworkDeviceHeader(true) + , m_sequence(0) + , m_oldSequence(-1) + , m_sequenceWideBand(0) + , m_oldSequenceWideBand(-1) + , m_wbBuffers(set->getWidebandBuffers() - 1) + , m_wbCount(0) + , m_socketBufferSize(set->getSocketBufferSize()) + , m_sendEP4(false) + , m_manualBufferSize(set->getManualSocketBufferSize()) + , m_packetsToggle(true) + , m_firstFrame(true) + , m_stopped(false) +{ + m_dataIOSocket = 0; + + m_metisGetDataSignature.resize(3); + m_metisGetDataSignature[0] = (char)0xEF; + m_metisGetDataSignature[1] = (char)0xFE; + m_metisGetDataSignature[2] = (char)0x01; + //m_metisGetDataSignature[3] = (char)0x06; + + m_datagram.resize(1032); + m_wbDatagram.resize(0); + m_twoFramesDatagram.resize(0); + + m_sendSequence = 0L; + m_oldSendSequence = 0L; + + m_deviceSendDataSignature.resize(4); + m_deviceSendDataSignature[0] = (char)0xEF; + m_deviceSendDataSignature[1] = (char)0xFE; + m_deviceSendDataSignature[2] = (char)0x01; + m_deviceSendDataSignature[3] = (char)0x02; + + m_packetLossTime.start(); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(setSampleRate(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(manualSocketBufferChanged(QObject*, bool)), + this, + SLOT(setManualSocketBufferSize(QObject*, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(socketBufferSizeChanged(QObject*, int)), + this, + SLOT(setSocketBufferSize(QObject*, int))); + + m_message = "m_sendSequence = %1, bytes sent: %2"; + + m_pSoundCardOut = new CSoundOut(this); + //RRK pass -1 to get the systems "default" audio device + m_pSoundCardOut->Start(-1, true, 48000, false); + m_pSoundCardOut->SetVolume(80); +} + +DataIO::~DataIO() { + + if (m_dataIOSocketOn) { + m_dataIOSocket->close(); + delete m_dataIOSocket; + m_dataIOSocket = 0; + } +} + +void DataIO::stop() { + + io->networkIOMutex.lock(); + m_stopped = true; + io->networkIOMutex.unlock(); + + if(m_pSoundCardOut) { + m_pSoundCardOut->Stop(); + delete m_pSoundCardOut; + } +} + +void DataIO::initDataReceiverSocket() { + + m_dataIOSocket = new QUdpSocket(); + + int newBufferSize; + + if (m_manualBufferSize) { + + newBufferSize = m_socketBufferSize * 1024;//m_socketBufferSize * 1032; + io->networkIOMutex.lock(); + DATAIO_DEBUG << "initDataReceiverSocket socket buffer size set to " << m_socketBufferSize << " kB."; + io->networkIOMutex.unlock(); + } + else { + + if (io->samplerate == 384000) { + + newBufferSize = 128*1024;//128 * 1032; + io->networkIOMutex.lock(); + DATAIO_DEBUG << "socket buffer size set to 128 kB."; + io->networkIOMutex.unlock(); + } + else if (io->samplerate == 192000) { + + newBufferSize = 64*1024;//64 * 1032; + io->networkIOMutex.lock(); + DATAIO_DEBUG << "socket buffer size set to 64 kB."; + io->networkIOMutex.unlock(); + } + else if (io->samplerate == 96000) { + + newBufferSize = 32*1024;//32 * 1032; + io->networkIOMutex.lock(); + DATAIO_DEBUG << "socket buffer size set to 32 kB."; + io->networkIOMutex.unlock(); + } + else if (io->samplerate == 48000) { + + newBufferSize = 16*1024;//16 * 1032; + io->networkIOMutex.lock(); + DATAIO_DEBUG << "socket buffer size set to 16 kB."; + io->networkIOMutex.unlock(); + } + } + + if (m_dataIOSocket->bind(QHostAddress(set->getHPSDRDeviceLocalAddr()), + set->getMetisPort(), + QUdpSocket::DontShareAddress)) + //QUdpSocket::ReuseAddressHint | QUdpSocket::ShareAddress)) + { + +#if defined(Q_OS_WIN32) + if (::setsockopt(m_dataIOSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&newBufferSize, sizeof(newBufferSize)) == -1) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "dataIOSocket error!"; + io->networkIOMutex.unlock(); + } +#endif + + + //m_dataIOSocket->setSocketOption(QAbstractSocket::LowDelayOption, 1); + //m_dataIOSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1); + + CHECKED_CONNECT( + m_dataIOSocket, + SIGNAL(error(QAbstractSocket::SocketError)), + this, + SLOT(displayDataReceiverSocketError(QAbstractSocket::SocketError))); + + /*CHECKED_CONNECT_OPT( + m_dataIOSocket, + SIGNAL(readyRead()), + this, + SLOT(readDeviceData()), + Qt::DirectConnection);*/ + + CHECKED_CONNECT( + m_dataIOSocket, + SIGNAL(readyRead()), + this, + SLOT(readDeviceData())); + + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "data receiver socket bound successful to local port " << m_dataIOSocket->localPort(); + io->networkIOMutex.unlock(); + + m_dataIOSocketOn = true; + set->setPacketLoss(1); + } + else { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "data receiver socket binding failed."; + io->networkIOMutex.unlock(); + + m_dataIOSocketOn = false; + } +} + +void DataIO::readDeviceData() { + + while (m_dataIOSocket->hasPendingDatagrams()) { + + QMutexLocker locker(&io->networkIOMutex); + if (m_dataIOSocket->readDatagram(m_datagram.data(), m_datagram.size()) == METIS_DATA_SIZE) { + + if (m_datagram.left(3) == m_metisGetDataSignature) { + + if (m_datagram[3] == (char)0x06) { + + m_sequence = (m_datagram[4] & 0xFF) << 24; + m_sequence += (m_datagram[5] & 0xFF) << 16; + m_sequence += (m_datagram[6] & 0xFF) << 8; + m_sequence += (m_datagram[7] & 0xFF); + + if (m_sequence != m_oldSequence + 1) { + + //DATAIO_DEBUG << "readData missed " << m_sequence - m_oldSequence << " packages."; + //RRK cout << "readData missed " << m_sequence - m_oldSequence << " packages." << endl; + + if (m_packetLossTime.elapsed() > 100) { + + set->setPacketLoss(2); + m_packetLossTime.restart(); + } + } + + m_oldSequence = m_sequence; + + //// enqueue first half of the HPSDR frame from the HPSDR device + //io->iq_queue.enqueue(m_datagram.mid(METIS_HEADER_SIZE, BUFFER_SIZE/2)); + //// enqueue second half of the HPSDR frame from the HPSDR device + //io->iq_queue.enqueue(m_datagram.right(BUFFER_SIZE/2)); + + // enqueue one frame from the HPSDR device + if (!io->iq_queue.isFull()) { + io->iq_queue.enqueue(m_datagram.mid(METIS_HEADER_SIZE, BUFFER_SIZE)); + } + + // collect two HPSDR frames + //if (m_firstFrame) { + + // m_twoFramesDatagram += m_datagram.mid(METIS_HEADER_SIZE, BUFFER_SIZE); + // m_firstFrame = false; + //} + //else { + + // m_twoFramesDatagram += m_datagram.mid(METIS_HEADER_SIZE, BUFFER_SIZE); + + // //enqueue the two frames + // io->iq_queue.enqueue(m_twoFramesDatagram); + // m_firstFrame = true; + + // m_twoFramesDatagram.resize(0); + //} + } + else if (m_datagram[3] == (char)0x04) { // wide band data + + //qDebug() << "wideband data received!"; + m_sequenceWideBand = (m_datagram[4] & 0xFF) << 24; + m_sequenceWideBand += (m_datagram[5] & 0xFF) << 16; + m_sequenceWideBand += (m_datagram[6] & 0xFF) << 8; + m_sequenceWideBand += (m_datagram[7] & 0xFF); + + if (m_sequenceWideBand != m_oldSequenceWideBand + 1) { + + DATAIO_DEBUG << "wideband readData missed " << m_sequenceWideBand - m_oldSequenceWideBand << " packages."; + + if (m_packetLossTime.elapsed() > 100) { + + set->setPacketLoss(2); + m_packetLossTime.restart(); + } + } + + m_oldSequenceWideBand = m_sequenceWideBand; + + // three 'if's from KISS Konsole + if ((m_wbBuffers & m_datagram[7]) == 0) + { + m_sendEP4 = true; + m_wbCount = 0; + } + + if (m_sendEP4) + { + m_wbDatagram.append(m_datagram.mid(METIS_HEADER_SIZE, BUFFER_SIZE)); + } + + if (m_wbCount++ == m_wbBuffers) + { + // enqueue + m_sendEP4 = false; + io->wb_queue.enqueue(m_wbDatagram); + m_wbDatagram.resize(0); + } + } + } + //DATA_RECEIVER_DEBUG << "got wrong HPSDR device signature!"; + } + //DATA_RECEIVER_DEBUG << "got wrong HPSDR device data size!"; + } + //DATA_RECEIVER_DEBUG << "no more pending datagrams."; +} + +void DataIO::readData() { + + qint64 length = io->inputBuffer.length(); + + //int buffers = qRound(length/(2*BUFFER_SIZE)); + int buffers = qRound((float) length/128); + + DATAIO_DEBUG << "input buffer length " << length << " buffers " << buffers; + + while (!m_stopped) { + + for (int i = 0; i < buffers; i++) { + + //io->data_queue.enqueue(io->inputBuffer.mid(i*2*BUFFER_SIZE, 2*BUFFER_SIZE)); + io->data_queue.enqueue(io->inputBuffer.mid(i*128, 128)); + if (m_stopped) break; + } + } + m_stopped = false; +} + +void DataIO::sendInitFramesToNetworkDevice(int rx) { + + QByteArray initDatagram; + initDatagram.resize(1032); + + initDatagram[0] = (char)0xEF; + initDatagram[1] = (char)0xFE; + initDatagram[2] = (char)0x01; + initDatagram[3] = (char)0x02; + initDatagram[4] = (char)0x00; + initDatagram[5] = (char)0x00; + initDatagram[6] = (char)0x00; + initDatagram[7] = (char)0x00; + + initDatagram[8] = SYNC; + initDatagram[9] = SYNC; + initDatagram[10] = SYNC; + + for (int i = 0; i < 5; i++) { + + initDatagram[i + 11] = io->control_out[i]; + } + + for (int i = 16; i < 520; i++) { + + initDatagram[i] = 0x00; + } + + initDatagram[520] = SYNC; + initDatagram[521] = SYNC; + initDatagram[522] = SYNC; + + initDatagram[523] = io->control_out[0] | ((rx + 2) << 1); + initDatagram[524] = set->getCtrFrequencies().at(rx) >> 24; + initDatagram[525] = set->getCtrFrequencies().at(rx) >> 16; + initDatagram[526] = set->getCtrFrequencies().at(rx) >> 8; + initDatagram[527] = set->getCtrFrequencies().at(rx) ; + + + for (int i = 528; i < 1032; i++) initDatagram[i] = 0x00; + +// for (int i = 0; i < 5; i++) { +// +// if (m_dataIOSocket->writeDatagram(initDatagram.data(), initDatagram.size(), io->hpsdrDeviceIPAddress, DEVICE_PORT) < 0) { +// +// io->networkIOMutex.lock(); +// DATAIO_DEBUG << "error sending init data to device: " << qPrintable(m_dataIOSocket->errorString()); +// io->networkIOMutex.unlock(); +// } +// else { +// +// if (i == 0) { +// +// io->networkIOMutex.lock(); +// DATAIO_DEBUG << "init frames sent to network device."; +// io->networkIOMutex.unlock(); +// } +// } +// } + + if (m_dataIOSocket->writeDatagram(initDatagram.data(), initDatagram.size(), io->hpsdrDeviceIPAddress, DEVICE_PORT) < 0) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "error sending init data to device: " << qPrintable(m_dataIOSocket->errorString()); + io->networkIOMutex.unlock(); + } + else { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "init frames sent to network device."; + io->networkIOMutex.unlock(); + } + + SleeperThread::msleep(20); + + if (m_dataIOSocket->writeDatagram(initDatagram.data(), initDatagram.size(), io->hpsdrDeviceIPAddress, DEVICE_PORT) < 0) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "error sending init data to device: " << qPrintable(m_dataIOSocket->errorString()); + io->networkIOMutex.unlock(); + } + else { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "init frames sent to network device."; + io->networkIOMutex.unlock(); + } +} + +void DataIO::networkDeviceStartStop(char value) { + + TNetworkDevicecard metis = set->getCurrentMetisCard(); + //QUdpSocket socket; + +// if (socket.bind(QHostAddress(set->getHPSDRDeviceLocalAddr()), +// set->getMetisPort(), +// //QUdpSocket::DefaultForPlatform)) +// QUdpSocket::ReuseAddressHint | QUdpSocket::ShareAddress)) +// { + //DATAIO_DEBUG << "device start/stop: socket bound successful to local port " << set->getMetisPort(); + + m_commandDatagram.resize(64); + m_commandDatagram[0] = (char)0xEF; + m_commandDatagram[1] = (char)0xFE; + m_commandDatagram[2] = (char)0x04; + m_commandDatagram[3] = (char)value; + + for (int i = 4; i < 64; i++) m_commandDatagram[i] = 0x00; + + if (m_dataIOSocket->writeDatagram(m_commandDatagram, metis.ip_address, DEVICE_PORT) == 64) { + + //if (value == 1) { + if (value != 0) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "sent start command to device at: "<< qPrintable(metis.ip_address.toString()); + io->networkIOMutex.unlock(); + m_networkDeviceRunning = true; + } + else { + + //DATA_ENGINE_DEBUG << "sent stop command to Metis at"<< m_metisCards[0].ip_address.toString(); + io->networkIOMutex.lock(); + DATAIO_DEBUG << "sent stop command to device at: "<< qPrintable(metis.ip_address.toString()); + io->networkIOMutex.unlock(); + m_networkDeviceRunning = false; + } + } + else + DATAIO_DEBUG << "device start/stop: sending command to device failed."; + + //socket.close(); +// } +// else { +// +// DATAIO_DEBUG << "device start/stop: socket binding failed."; +// } + +// socket.close(); +// DATAIO_DEBUG << "device start/stop: socket closed."; +} + +void DataIO::sendAudio(u_char *buf) { + //RRK send audio bytes here + static TYPECPX cbuf[252]; + int i, j; + short sample; + + for(i = 8, j = 0; i < 512; i += 8, j++) { + //bytes are L,R,I,Q skip the I,Q + sample = buf[i] << 8 | buf[i+1]; //left + cbuf[j].re = (double)sample; + sample = buf[i+2] << 8 | buf[i+3]; //right + cbuf[j].im = (double)sample; + } + + if(m_pSoundCardOut) + m_pSoundCardOut->PutOutQueue(63, cbuf); +} + +void DataIO::writeData() { + + if (m_setNetworkDeviceHeader) { + + m_outDatagram.resize(0); + m_outDatagram += m_deviceSendDataSignature; + + QByteArray seq(reinterpret_cast(&m_sendSequence), sizeof(m_sendSequence)); + + m_outDatagram += seq; + m_outDatagram += io->audioDatagram; + + m_sendSequence++; + m_setNetworkDeviceHeader = false; + } + else { + + m_outDatagram += io->audioDatagram; + + if (m_dataIOSocket->writeDatagram(m_outDatagram, set->getCurrentMetisCard().ip_address, DEVICE_PORT) < 0) { + DATAIO_DEBUG << "error sending data to device: " << m_dataIOSocket->errorString(); + } + + //if (m_sendSequence%100 == 0) + // DATAIO_DEBUG << m_sendSequence; + + if (m_sendSequence != m_oldSendSequence + 1) { + DATAIO_DEBUG << "output sequence error: old = " << m_oldSendSequence << "; new =" << m_sendSequence; + } + + m_oldSendSequence = m_sendSequence; + m_setNetworkDeviceHeader = true; + } +} + +void DataIO::displayDataReceiverSocketError(QAbstractSocket::SocketError error) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "data IO socket error: " << error; + io->networkIOMutex.unlock(); +} + +void DataIO::setManualSocketBufferSize(QObject *sender, bool value) { + + Q_UNUSED (sender) + + m_manualBufferSize = value; + DATAIO_DEBUG << "m_manualBufferSize to change = " << m_manualBufferSize; + int socketBufferSize = 1032 * set->getSocketBufferSize(); + + io->networkIOMutex.lock(); + + if (m_manualBufferSize) { + + DATAIO_DEBUG << "set data IO socket BufferSize to " << m_socketBufferSize; +#if defined(Q_OS_WIN32) + if (::setsockopt(m_dataIOSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&socketBufferSize, sizeof(socketBufferSize)) == -1) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "dataIOSocket error!"; + io->networkIOMutex.unlock(); + } +#endif + } + else { + + DATAIO_DEBUG << "set data IO socket BufferSize to 32 kB."; + socketBufferSize = 1032 * 32; +#if defined(Q_OS_WIN32) + if (::setsockopt(m_dataIOSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&socketBufferSize, sizeof(socketBufferSize)) == -1) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "dataIOSocket error!"; + io->networkIOMutex.unlock(); + } +#endif + } + io->networkIOMutex.unlock(); +} + +void DataIO::setSocketBufferSize(QObject *sender, int value) { + + Q_UNUSED (sender) + + int socketBufferSize = value * 1024; + DATAIO_DEBUG << "m_socketBufferSize = " << value; + + io->networkIOMutex.lock(); +#if defined(Q_OS_WIN32) + if (::setsockopt(m_dataIOSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&socketBufferSize, sizeof(socketBufferSize)) == -1) { + + io->networkIOMutex.lock(); + DATAIO_DEBUG << "dataIOSocket error!"; + io->networkIOMutex.unlock(); + } +#endif + io->networkIOMutex.unlock(); +} + +void DataIO::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + int bufferSize; + io->networkIOMutex.lock(); + switch (value) { + + case 48000: + bufferSize = 16*1024;//128 * 1032 + DATAIO_DEBUG << "socket buffer size set to 16 kB."; + break; + + case 96000: + bufferSize = 32*1024;//128 * 1032 + DATAIO_DEBUG << "socket buffer size set to 32 kB."; + break; + + case 192000: + bufferSize = 64*1024;//128 * 1032 + DATAIO_DEBUG << "socket buffer size set to 64 kB."; + break; + + case 384000: + bufferSize = 128*1024;//128 * 1032 + DATAIO_DEBUG << "socket buffer size set to 128 kB."; + break; + + default: + DATAIO_DEBUG << "invalid sample rate !\n"; + break; + } + +#if defined(Q_OS_WIN32) + if (::setsockopt(m_dataIOSocket->socketDescriptor(), SOL_SOCKET, + SO_RCVBUF, (char *)&bufferSize, sizeof(bufferSize)) == -1) { + + DATAIO_DEBUG << "dataIOSocket error!"; + } +#endif + + io->networkIOMutex.unlock(); +} diff --git a/Source/src/DataEngine/cusdr_dataIO.h b/Source/src/DataEngine/cusdr_dataIO.h new file mode 100644 index 0000000..fe1a14d --- /dev/null +++ b/Source/src/DataEngine/cusdr_dataIO.h @@ -0,0 +1,120 @@ +/** +* @file cusdr_dataIO.h +* @brief Data IO header file +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-10-01 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_DATAIO_H +#define _CUSDR_DATAIO_H + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_settings.h" +#include "soundout.h" + +#ifdef LOG_DATAIO +# define DATAIO_DEBUG qDebug().nospace() << "DataIO::\t" +#else +# define DATAIO_DEBUG nullDebug() +#endif + + +class DataIO : public QObject { + + Q_OBJECT + +public: + DataIO(THPSDRParameter *ioData = 0); + ~DataIO(); + +public slots: + void stop(); + void initDataReceiverSocket(); + void readData(); + void writeData(); + void sendAudio(u_char *buf); + void sendInitFramesToNetworkDevice(int rx); + void networkDeviceStartStop(char value); + //void setWidebandBuffers(int value); + +private slots: + void setSampleRate(QObject *sender, int value); + void displayDataReceiverSocketError(QAbstractSocket::SocketError error); + void setManualSocketBufferSize(QObject *sender, bool value); + void setSocketBufferSize(QObject *sender, int value); + void readDeviceData(); + +private: + Settings* set; + QUdpSocket* m_dataIOSocket; + //QMutex m_mutex; + QByteArray m_commandDatagram; + QByteArray m_datagram; + QByteArray m_wbDatagram; + QByteArray m_twoFramesDatagram; + QByteArray m_metisGetDataSignature; + QByteArray m_outDatagram; + QByteArray m_deviceSendDataSignature; + QString m_message; + + QTime m_packetLossTime; + + THPSDRParameter* io; + //TNetworkDevicecard netDevice; + + bool m_dataIOSocketOn; + bool m_networkDeviceRunning; + bool m_setNetworkDeviceHeader; + + long m_sequence; + long m_oldSequence; + long m_sequenceWideBand; + long m_oldSequenceWideBand; + long m_sendSequence; + long m_oldSendSequence; + + + int m_wbBuffers; + int m_wbCount; + int m_socketBufferSize; + + bool m_sendEP4; + bool m_manualBufferSize; + bool m_packetsToggle; + bool m_firstFrame; + + volatile bool m_stopped; + CSoundOut* m_pSoundCardOut; + +signals: + void messageEvent(QString message); +}; + +#endif // _CUSDR_DATAIO_H diff --git a/Source/src/DataEngine/cusdr_discoverer.cpp b/Source/src/DataEngine/cusdr_discoverer.cpp new file mode 100644 index 0000000..3177281 --- /dev/null +++ b/Source/src/DataEngine/cusdr_discoverer.cpp @@ -0,0 +1,271 @@ +/** +* @file cusdr_discoverer.cpp +* @brief HPSDR device discoverer class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-19 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_DISCOVERER + +#include "cusdr_discoverer.h" +#include "Util/cusdr_buttons.h" + + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + + + +//#define btn_height 18 +//#define btn_width 74 + +Discoverer::Discoverer(THPSDRParameter *ioData) + : QObject() + , set(Settings::instance()) + , io(ioData) +{ + m_deviceCards = set->getMetisCardsList(); +} + +Discoverer::~Discoverer() { +} + +void Discoverer::initHPSDRDevice() { + + m_searchTime.start(); + + int deviceNo = 0; + while (deviceNo == 0) { + + deviceNo = findHPSDRDevices(); + + if (deviceNo > 1) { + + set->setHPSDRDeviceNumber(deviceNo); + break; + } + + if (deviceNo > 0) { + + set->setHPSDRDeviceNumber(deviceNo); + break; + } + + if (m_searchTime.elapsed() > 1000) { + + set->setHPSDRDeviceNumber(0); + break; + } + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "no device found - trying again..."; + io->networkIOMutex.unlock(); + } + + io->networkIOMutex.lock(); + io->devicefound.wakeAll(); + io->networkIOMutex.unlock(); +} + +int Discoverer::findHPSDRDevices() { + + int devicesFound = 0; + + m_findDatagram.resize(63); + m_findDatagram[0] = (char)0xEF; + m_findDatagram[1] = (char)0xFE; + m_findDatagram[2] = (char)0x02; + for (int i = 3; i < 63; i++) + m_findDatagram[i] = (char)0x00; + + QUdpSocket socket; + + CHECKED_CONNECT( + &socket, + SIGNAL(error(QAbstractSocket::SocketError)), + this, + SLOT(displayDiscoverySocketError(QAbstractSocket::SocketError))); + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "using " << qPrintable(QHostAddress(set->getHPSDRDeviceLocalAddr()).toString()) << " for discovery."; + io->networkIOMutex.unlock(); + + // clear comboBox entries in the network dialogue + set->clearNetworkIOComboBoxEntry(); + +#if defined(Q_OS_WIN32) + + if (socket.bind( + QHostAddress(set->getHPSDRDeviceLocalAddr()), 0, + QUdpSocket::ReuseAddressHint | QUdpSocket::ShareAddress)) + //QUdpSocket::ReuseAddressHint)) + { + set->setMetisPort(this, socket.localPort()); + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery_socket bound successfully to port " << socket.localPort(); + io->networkIOMutex.unlock(); + } + else { + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery_socket bind failed."; + io->networkIOMutex.unlock(); + + socket.close(); + return 0; + } +#elif defined(Q_OS_LINUX) + + if (socket.bind( + QHostAddress(set->getHPSDRDeviceLocalAddr()), + QUdpSocket::DefaultForPlatform)) + { + CHECKED_CONNECT( + &socket, + SIGNAL(error(QAbstractSocket::SocketError)), + this, + SLOT(displayDiscoverySocketError(QAbstractSocket::SocketError))); + + set->setMetisPort(this, socket.localPort()); + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery_socket bound successfully to port " << socket.localPort(); + io->networkIOMutex.unlock(); + } + else { + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery_socket bind failed."; + io->networkIOMutex.unlock(); + + socket.close(); + return 0; + } +#endif + + if (socket.writeDatagram(m_findDatagram, QHostAddress::Broadcast, DEVICE_PORT) == 63) { + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery data sent."; + io->networkIOMutex.unlock(); + } + else { + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery data not sent."; + io->networkIOMutex.unlock(); + } + + + // wait a little + //SleeperThread::msleep(30); + SleeperThread::msleep(500); + + while (socket.hasPendingDatagrams()) { + + TNetworkDevicecard mc; + quint16 port; + + m_deviceDatagram.resize(socket.pendingDatagramSize()); + socket.readDatagram(m_deviceDatagram.data(), m_deviceDatagram.size(), &mc.ip_address, &port); + + if (m_deviceDatagram[0] == (char)0xEF && m_deviceDatagram[1] == (char)0xFE) { + + if (m_deviceDatagram[2] == (char)0x02) { + + sprintf(mc.mac_address, "%02X:%02X:%02X:%02X:%02X:%02X", + m_deviceDatagram[3] & 0xFF, m_deviceDatagram[4] & 0xFF, m_deviceDatagram[5] & 0xFF, + m_deviceDatagram[6] & 0xFF, m_deviceDatagram[7] & 0xFF, m_deviceDatagram[8] & 0xFF); + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "Device found at " << qPrintable(mc.ip_address.toString()) << ":" << port << "; Mac addr: [" << mc.mac_address << "]"; + DISCOVERER_DEBUG << "Device code version: " << qPrintable(QString::number(m_deviceDatagram.at(9), 16)); + io->networkIOMutex.unlock(); + + int no = m_deviceDatagram.at(10); + QString str; + if (no == 0) + str = "Metis"; + else if (no == 1) + str = "Hermes"; + else if (no == 2) + str = "Griffin"; + else if (no == 4) + str = "Angelia"; + + mc.boardID = no; + mc.boardName = str; + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "Device board ID: " << no; + DISCOVERER_DEBUG << "Device is: " << qPrintable(str); + io->networkIOMutex.unlock(); + + m_deviceCards.append(mc); + + str += " ("; + str += mc.ip_address.toString(); + str += ")"; + + set->addNetworkIOComboBoxEntry(str); + devicesFound++; + } + else if (m_deviceDatagram[2] == (char)0x03) { + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "Device already sending data!"; + io->networkIOMutex.unlock(); + } + } + + } + set->setMetisCardList(m_deviceCards); + + if (devicesFound == 1) { + + set->setCurrentHPSDRDevice(m_deviceCards.at(0)); + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "Device selected: " << qPrintable(m_deviceCards.at(0).ip_address.toString()); + io->networkIOMutex.unlock(); + } + + socket.close(); + return devicesFound; +} + +void Discoverer::displayDiscoverySocketError(QAbstractSocket::SocketError error) { + + io->networkIOMutex.lock(); + DISCOVERER_DEBUG << "discovery socket error: " << error; + io->networkIOMutex.unlock(); +} + +void Discoverer::clear() { + + //m_metisDeviceComboBox->clear(); + m_deviceCards.clear(); +} diff --git a/Source/src/DataEngine/cusdr_discoverer.h b/Source/src/DataEngine/cusdr_discoverer.h new file mode 100644 index 0000000..60d1484 --- /dev/null +++ b/Source/src/DataEngine/cusdr_discoverer.h @@ -0,0 +1,86 @@ +/** +* @file cusdr_discoverer.h +* @brief HPSDR device discoverer header file +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-19 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_DISCOVERER_H +#define _CUSDR_DISCOVERER_H + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_settings.h" + +#ifdef LOG_DISCOVERER +# define DISCOVERER_DEBUG qDebug().nospace() << "Discoverer::\t" +#else +# define DISCOVERER_DEBUG nullDebug() +#endif + + +class Discoverer : public QObject { + + Q_OBJECT + +public: + Discoverer(THPSDRParameter *ioData = 0); + ~Discoverer(); + + int findHPSDRDevices(); + void clear(); + +public slots: + void initHPSDRDevice(); + + +private slots: + void displayDiscoverySocketError(QAbstractSocket::SocketError error); + +private: + Settings* set; + THPSDRParameter* io; + QTime m_searchTime; + + QByteArray m_findDatagram; + QByteArray m_deviceDatagram; + + //QString m_deviceStr; + + TNetworkDevicecard m_deviceCard; + QList m_deviceCards; + +signals: + +}; + +#endif // _CUSDR_DISCOVERER_H diff --git a/Source/src/DataEngine/cusdr_receiver.cpp b/Source/src/DataEngine/cusdr_receiver.cpp new file mode 100644 index 0000000..556019d --- /dev/null +++ b/Source/src/DataEngine/cusdr_receiver.cpp @@ -0,0 +1,772 @@ +/** +* @file cusdr_receiver.cpp +* @brief cuSDR receiver class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-12 +*/ + +/* Copyright (C) +* +* 2010 - Hermann von Hasseln, DL3HVH +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ +#define LOG_RECEIVER + +// use: RECEIVER_DEBUG + +#include "cusdr_receiver.h" + +Receiver::Receiver(int rx) + : QObject() + , set(Settings::instance()) + , m_filterMode(set->getCurrentFilterMode()) + , m_stopped(false) + , m_receiver(rx) + , m_samplerate(set->getSampleRate()) + , m_audioMode(1) + //, m_calOffset(63.0) + //, m_calOffset(33.0) +{ + setReceiverData(set->getReceiverDataList().at(m_receiver)); + + InitCPX(inBuf, BUFFER_SIZE, 0.0f); + InitCPX(outBuf, BUFFER_SIZE, 0.0f); + + newSpectrum.resize(BUFFER_SIZE*4); + + qtdsp = 0; + + setupConnections(); + + highResTimer = new HResTimer(); + m_displayTime = (int)(1000000.0/set->getFramesPerSecond(m_receiver)); + + m_smeterTime.start(); +} + +Receiver::~Receiver() { + + inBuf.clear(); + outBuf.clear(); + + if (qtdsp) { + + delete qtdsp; + qtdsp = 0; + } + + if (highResTimer) { + delete highResTimer; + } + + m_stopped = false; +} + +void Receiver::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(setSystemState( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(mainVolumeChanged(QObject *, int, float)), + this, + SLOT(setAudioVolume(QObject *, int, float))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(setSampleRate(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(dspModeChanged(QObject *, int, DSPMode)), + this, + SLOT(setDspMode(QObject *, int, DSPMode))); + + CHECKED_CONNECT( + set, + SIGNAL(hamBandChanged(QObject *, int, bool, HamBand)), + this, + SLOT(setHamBand(QObject *, int, bool, HamBand))); + + CHECKED_CONNECT( + set, + SIGNAL(agcModeChanged(QObject *, int, AGCMode, bool)), + this, + SLOT(setAGCMode(QObject *, int, AGCMode, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(agcGainChanged(QObject *, int, int)), + this, + SLOT(setAGCGain(QObject *, int, int))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(agcMaximumGain_dBmChanged(QObject *, int, int)), +// this, +// SLOT(setAGCMaximumGain_dBm(QObject *, int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(agcMaximumGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCMaximumGain_dB(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcFixedGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCFixedGain_dB(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcThresholdChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCThreshold_dB(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcHangThresholdChanged(QObject *, int, int)), + this, + SLOT(setAGCHangThreshold(QObject *, int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(agcHangLevelChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCHangLevel_dB(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcVariableGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCVariableGain_dB(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcAttackTimeChanged(QObject *, int, qreal)), + this, + SLOT(setAGCAttackTime(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcDecayTimeChanged(QObject *, int, qreal)), + this, + SLOT(setAGCDecayTime(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcHangTimeChanged(QObject *, int, qreal)), + this, + SLOT(setAGCHangTime(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)), + this, + SLOT(setFilterFrequencies(QObject *, int, qreal, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(framesPerSecondChanged(QObject*, int, int)), + this, + SLOT(setFramesPerSecond(QObject*, int, int))); + + /*CHECKED_CONNECT( + set, + SIGNAL(receiverDataReady()), + this, + SLOT(dspProcessing()));*/ +} + +void Receiver::setReceiverData(TReceiver data) { + + m_receiverData = data; + + //m_serverMode = m_receiverData.serverMode; + m_dspCore = m_receiverData.dspCore; + m_sampleRate = m_receiverData.sampleRate; + m_hamBand = m_receiverData.hamBand; + m_dspMode = m_receiverData.dspMode; + m_dspModeList = m_receiverData.dspModeList; + m_agcMode = m_receiverData.agcMode; + m_agcGain = m_receiverData.acgGain; + m_agcFixedGain_dB = m_receiverData.agcFixedGain_dB; + m_agcMaximumGain_dB = m_receiverData.agcMaximumGain_dB; + m_agcHangThreshold = m_receiverData.agcHangThreshold; + m_agcVariableGain = m_receiverData.agcVariableGain; + + m_audioVolume = m_receiverData.audioVolume; + + m_filterLo = m_receiverData.filterLo; + m_filterHi = m_receiverData.filterHi; + + m_lastCtrFrequencyList = m_receiverData.lastCenterFrequencyList; + m_lastVfoFrequencyList = m_receiverData.lastVfoFrequencyList; + m_mercuryAttenuators = m_receiverData.mercuryAttenuators; +} + +bool Receiver::initDSPInterface() { + if (m_dspCore == QSDR::QtDSP) { + + if (!initQtDSPInterface()) return false; + } + return true; +} + +bool Receiver::initQtDSPInterface() { + + qtdsp = new QDSPEngine(this, m_receiver, BUFFER_SIZE); + + if (qtdsp) + qtdsp->setQtDSPStatus(true); + else { + + RECEIVER_DEBUG << "could not start QtDSP for receiver: " << m_receiver; + qtdsp = 0; + return false; + } + + qtdsp->setVolume(m_audioVolume); + + DSPMode mode = m_dspModeList.at(m_hamBand); + RECEIVER_DEBUG << "set DSP mode to: " << set->getDSPModeString(mode); + + qtdsp->setDSPMode(mode); + qtdsp->filter->setFilter( + getFilterFromDSPMode(set->getDefaultFilterList(), mode).filterLo, + getFilterFromDSPMode(set->getDefaultFilterList(), mode).filterHi); + qtdsp->wpagc->setMode(m_agcMode); + qtdsp->wpagc->setAGCFixedGainDb(m_agcFixedGain_dB); + qtdsp->wpagc->setMaximumGainDb(m_agcMaximumGain_dB); + +// if (m_agcMode == (AGCMode) agcOFF) +// set->setAGCFixedGain_dB(this, m_receiver, m_agcFixedGain_dB); +// else +// set->setAGCMaximumGain_dB(this, m_receiver, m_agcMaximumGain_dB); + + RECEIVER_DEBUG << "QtDSP for receiver: " << m_receiver << " started."; + return true; +} + +void Receiver::deleteDSPInterface() { + + if (m_dspCore == QSDR::QtDSP) + deleteQtDSP(); +} + +void Receiver::deleteQtDSP() { + + if (qtdsp) { + + delete qtdsp; + qtdsp = 0; + } +} + +void Receiver::enqueueData() { + + inQueue.enqueue(inBuf); + + if (inQueue.isFull()) { + RECEIVER_DEBUG << "inQueue full!"; + } + +} + +void Receiver::stop() { + + m_mutex.lock(); + m_stopped = true; + m_mutex.unlock(); +} + +void Receiver::dspProcessing() { + + //RECEIVER_DEBUG << "dspProcessing: " << this->thread(); + + //io.mutex.lock(); + qtdsp->processDSP(inBuf, outBuf, BUFFER_SIZE); + //io.mutex.unlock(); + + // spectrum + qtdsp->getSpectrum(newSpectrum, set->getFFTMultiplicator()); + if (highResTimer->getElapsedTimeInMicroSec() >= getDisplayDelay()) { + + emit spectrumBufferChanged(m_receiver, newSpectrum); + highResTimer->start(); + } + + if (m_receiver == set->getCurrentReceiver()) { + // S-Meter + if (m_smeterTime.elapsed() > 20) { + + m_sMeterValue = qtdsp->getSMeterInstValue(); + emit sMeterValueChanged(m_receiver, m_sMeterValue); + m_smeterTime.restart(); + } + + // process output data + emit outputBufferSignal(m_receiver, outBuf); + } +} + +void Receiver::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (m_samplerate == value) return; + + switch (value) { + + case 48000: + m_samplerate = value; + break; + + case 96000: + m_samplerate = value; + break; + + case 192000: + m_samplerate = value; + break; + + case 384000: + m_samplerate = value; + break; + + default: + RECEIVER_DEBUG << "invalid sample rate (possible values are: 48, 96, 192, or 384 kHz)!\n"; + break; + } + + if (qtdsp) + qtdsp->setSampleRate(this, m_samplerate); + else + RECEIVER_DEBUG << "qtdsp down: cannot set sample rate!\n"; +} + +void Receiver::setServerMode(QSDR::_ServerMode mode) { + + m_serverMode = mode; +} + +QSDR::_ServerMode Receiver::getServerMode() const { + + return m_serverMode; +} + +QSDR::_DSPCore Receiver::getDSPCoreMode() const { + + return m_dspCore; +} + +//void Receiver::setSocketState(SocketState state) { +// +// m_socketState = state; +//} + +//Receiver::SocketState Receiver::socketState() const { +// +// return m_socketState; +//} + +void Receiver::setSystemState( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; +} + +void Receiver::setAudioMode(QObject* sender, int mode) { + + if (sender != this && m_audioMode == mode) return; + + m_audioMode = mode; +} + +//void Receiver::setID(int value) { +// +// m_receiverID = value; +// RECEIVER_DEBUG << "This is receiver " << m_receiverID; +//} + +void Receiver::setReceiver(int value) { + + m_receiver = value; +} + +void Receiver::setSampleRate(int value) { + + m_sampleRate = value; +} + +void Receiver::setHamBand(QObject *sender, int rx, bool byBtn, HamBand band) { + + Q_UNUSED(sender) + Q_UNUSED(byBtn) + + if (m_receiver == rx) { + + if (m_hamBand == band) return; + m_hamBand = band; + } +} + +void Receiver::setDspMode(QObject *sender, int rx, DSPMode mode) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_dspMode == mode) return; + + m_dspMode = mode; + + if (qtdsp) { + + qtdsp->setDSPMode(mode); + qtdsp->filter->setFilter( + getFilterFromDSPMode(set->getDefaultFilterList(), mode).filterLo, + getFilterFromDSPMode(set->getDefaultFilterList(), mode).filterHi); + } + + //QString msg = "[receiver]: set mode for receiver %1 to %2"; + //emit messageEvent(msg.arg(rx).arg(set->getDSPModeString(m_dspMode))); +} + +void Receiver::setAGCMode(QObject *sender, int rx, AGCMode mode, bool hang) { + + Q_UNUSED(sender) + Q_UNUSED(hang) + + if (m_receiver != rx) return; + if (m_agcMode == mode) return; + + m_agcMode = mode; + + if (qtdsp) { + + qtdsp->wpagc->setMode(mode); + } +} + +void Receiver::setAGCGain(QObject *sender, int rx, int value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcGain == value) return; + + m_agcGain = value; + + if (qtdsp) { + + //RECEIVER_DEBUG << "AGCThreshDB (plus offset) = " << m_agcGain - AGCOFFSET; + //qtdsp->wpagc->setAGCThreshDb(m_filterLo, m_filterHi, BUFFER_SIZE, m_agcGain - AGCOFFSET); + } +} + +void Receiver::setAGCFixedGain_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcFixedGain_dB == value) return; + + m_agcFixedGain_dB = value; + + if (qtdsp) { + + //RECEIVER_DEBUG << "m_agcFixedGain = " << m_agcFixedGain; + qtdsp->wpagc->setAGCFixedGainDb(m_agcFixedGain_dB); + } +} + +void Receiver::setAGCMaximumGain_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcMaximumGain_dB == value) return; + + m_agcMaximumGain_dB = value; + + if (qtdsp) { + + //RECEIVER_DEBUG << "setAGCMaximumGain_dB = " << m_agcMaximumGain_dB; + qtdsp->wpagc->setMaximumGainDb(m_agcMaximumGain_dB); + } +} + +void Receiver::setAGCThreshold_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcThreshold_dBm == value) return; + + m_agcThreshold_dBm = value; + + if (qtdsp) { + + //RECEIVER_DEBUG << "AGCThreshDB (minus offset) for Rx " << m_receiver << ": " << m_agcThreshold_dBm - AGCOFFSET; + qtdsp->wpagc->setAGCThreshDb(m_filterLo, m_filterHi, 2*BUFFER_SIZE, m_agcThreshold_dBm - AGCOFFSET); + } +} + +void Receiver::setAGCHangThreshold(QObject *sender, int rx, int value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcHangThreshold == value) return; + + m_agcHangThreshold = value; + if (qtdsp) { + + RECEIVER_DEBUG << "m_agcHangThreshold =" << m_agcHangThreshold/100.0; + qtdsp->wpagc->setHangThresh(m_agcHangThreshold/100.0); + } +} + +void Receiver::setAGCHangLevel_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcHangLevel == value) return; + + m_agcHangLevel = value; + + if (qtdsp) { + + //RECEIVER_DEBUG << "m_agcHangLevel = " << m_agcHangLevel - AGCOFFSET; + qtdsp->wpagc->setHangLevelDb(m_agcHangLevel - AGCOFFSET); + } + //set->setAGCHangLeveldB(this, m_receiverID, value); +} + +void Receiver::setAGCVariableGain_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcVariableGain == value) return; + + m_agcVariableGain = value; + + if (qtdsp) { + + RECEIVER_DEBUG << "m_agcVariableGain = " << m_agcVariableGain; + qtdsp->wpagc->setVarGainDb(m_agcVariableGain); + } +} + +void Receiver::setAGCAttackTime(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcAttackTime == value) return; + + m_agcAttackTime = value; + + if (qtdsp) { + + RECEIVER_DEBUG << "m_agcAttackTime = " << m_agcAttackTime; + qtdsp->wpagc->setTauAttack(m_agcAttackTime); + } +} + +void Receiver::setAGCDecayTime(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcDecayTime == value) return; + + m_agcDecayTime = value; + + if (qtdsp) { + + RECEIVER_DEBUG << "m_agcDecayTime = " << m_agcDecayTime; + qtdsp->wpagc->setTauDecay(m_agcDecayTime); + } +} + +void Receiver::setAGCHangTime(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcHangTime == value) return; + + m_agcHangTime = value; + + if (qtdsp) { + + RECEIVER_DEBUG << "m_agcHangTime = " << m_agcHangTime; + qtdsp->wpagc->setHangTime(m_agcHangTime); + } +} + +void Receiver::setAudioVolume(QObject *sender, int rx, float value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + //if (m_audioVolume == value) return; + + m_audioVolume = value; + + if (qtdsp) { + + //RECEIVER_DEBUG << "setAudioVolume =" << m_audioVolume; + qtdsp->setVolume(value); + } +} + +void Receiver::setFilterFrequencies(QObject *sender, int rx, double low, double high) { + + Q_UNUSED(sender) + + if (m_receiver == rx) { + + if (m_filterLo == low && m_filterHi == high) return; + m_filterLo = low; + m_filterHi = high; + + if (qtdsp) { + + qtdsp->filter->setFilter((float)low, (float)high); + qtdsp->wpagc->filterChanged(); + } + } +} + +void Receiver::setCtrFrequency(long frequency) { + + if (m_ctrFrequency == frequency) return; + m_ctrFrequency = frequency; + + HamBand band = getBandFromFrequency(set->getBandFrequencyList(), frequency); + m_lastCtrFrequencyList[(int) band] = m_ctrFrequency; +} + +void Receiver::setVfoFrequency(long frequency) { + + if (m_vfoFrequency == frequency) return; + m_vfoFrequency = frequency; + + HamBand band = getBandFromFrequency(set->getBandFrequencyList(), frequency); + m_lastVfoFrequencyList[(int) band] = m_vfoFrequency; +} + +void Receiver::setLastCtrFrequencyList(const QList &fList) { + + m_lastCtrFrequencyList = fList; +} + +void Receiver::setLastVfoFrequencyList(const QList &fList) { + + m_lastVfoFrequencyList = fList; +} + +void Receiver::setdBmPanScaleMin(qreal value) { + + if (m_dBmPanScaleMin == value) return; + m_dBmPanScaleMin = value; +} + +void Receiver::setdBmPanScaleMax(qreal value) { + + if (m_dBmPanScaleMax == value) return; + m_dBmPanScaleMax = value; +} + +void Receiver::setMercuryAttenuators(const QList &attenuators) { + + m_mercuryAttenuators = attenuators; +} + +void Receiver::setFramesPerSecond(QObject *sender, int rx, int value) { + + Q_UNUSED(sender) + + if (m_receiver == rx) + m_displayTime = (int)(1000000.0/value); +} + +void Receiver::setPeerAddress(QHostAddress addr) { + + m_peerAddress = addr; +} + +void Receiver::setSocketDescriptor(int value) { + + m_socketDescriptor = value; +} + +void Receiver::setClient(int value) { + + m_client = value; +} + +void Receiver::setIQPort(int value) { + + m_iqPort = value; +} + +void Receiver::setBSPort(int value) { + + m_bsPort = value; +} + +void Receiver::setConnectedStatus(bool value) { + + m_connected = value; +} diff --git a/Source/src/DataEngine/cusdr_receiver.h b/Source/src/DataEngine/cusdr_receiver.h new file mode 100644 index 0000000..d5c62bd --- /dev/null +++ b/Source/src/DataEngine/cusdr_receiver.h @@ -0,0 +1,231 @@ +/** +* @file cusdr_receiver.h +* @brief cuSDR receiver header file +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-12 +*/ + +/* Copyright (C) +* +* 2010 - Hermann von Hasseln, DL3HVH +* +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU General Public License +* as published by the Free Software Foundation; either version 2 +* of the License, or (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* +*/ + +#ifndef CUSDR_RECEIVER_H +#define CUSDR_RECEIVER_H + +//#include +//#include + +#include "cusdr_settings.h" +#include "QtDSP/qtdsp_dspEngine.h" +#include "Util/cusdr_highResTimer.h" + +#ifdef LOG_RECEIVER +# define RECEIVER_DEBUG qDebug().nospace() << "Receiver::\t" +#else +# define RECEIVER_DEBUG nullDebug() +#endif + + +class Receiver : public QObject { + + Q_OBJECT + +public: + Receiver(int rx = 0); + ~Receiver(); + + void setupConnections(); + bool initDSPInterface(); + void deleteDSPInterface(); + + void enqueueData(); + + + QSDR::_ServerMode getServerMode() const; + QSDR::_DSPCore getDSPCoreMode() const; + QHostAddress getPeerAddress() { return m_peerAddress; } + HamBand getHamBand() { return m_hamBand; } + AGCMode getAGCMode() { return m_agcMode; } + QList getMercuryAttenuators() { return m_mercuryAttenuators; } + QList getDSPModeList() { return m_dspModeList; } + + int getAudioMode() { return m_audioMode; } + int getSocketDescriptor() { return m_socketDescriptor; } + int getReceiverNo() { return m_receiver; } + int getClient() { return m_client; } + int getIQPort() { return m_iqPort; } + int getBSPort() { return m_bsPort; } + //int getID() { return m_receiverID; } + int getSampleRate() { return m_sampleRate; } + int getDisplayDelay() { return m_displayTime; } + qreal getAGCGain() { return m_agcGain; } + float getAudioVolume() { return m_audioVolume; } + long getCtrFrequency() { return m_ctrFrequency; } + long getVfoFrequency() { return m_vfoFrequency; } + double getFilterLo() { return m_filterLo; } + double getFilterHi() { return m_filterHi; } + qreal getdBmPanScaleMin() { return m_dBmPanScaleMin; } + qreal getdBmPanScaleMax() { return m_dBmPanScaleMax; } + bool getConnectedStatus() { return m_connected; } + + float in[BUFFER_SIZE * 2]; + float out[BUFFER_SIZE * 2]; + float temp[BUFFER_SIZE * 4]; + float spectrum[BUFFER_SIZE * 4]; + float postSpectrum[BUFFER_SIZE * 4]; + + QVector newSpectrum; + + QDSPEngine *qtdsp; + HResTimer *highResTimer; + + CPX inBuf; + CPX outBuf; + + QHQueue inQueue; + +public slots: + void setReceiverData(TReceiver data); + void setAudioMode(QObject* sender, int mode); + void setServerMode(QSDR::_ServerMode mode); + void setPeerAddress(QHostAddress addr); + void setSocketDescriptor(int value); + void setReceiver(int value); + void setClient(int value); + void setIQPort(int value); + void setBSPort(int value); + void setConnectedStatus(bool value); + //void setID(int value); + void setSampleRate(int value); + void setHamBand(QObject* sender, int rx, bool byBtn, HamBand band); + void setDspMode(QObject* sender, int rx, DSPMode mode); + void setAGCMode(QObject* sender, int rx, AGCMode mode, bool hang); + void setAGCGain(QObject* sender, int rx, int value); + void setAudioVolume(QObject* sender, int rx, float value); + void setCtrFrequency(long frequency); + void setVfoFrequency(long frequency); + void setFilterFrequencies(QObject* sender, int rx, qreal low, qreal high); + void setLastCtrFrequencyList(const QList &frequencies); + void setLastVfoFrequencyList(const QList &frequencies); + void setdBmPanScaleMin(qreal value); + void setdBmPanScaleMax(qreal value); + void setMercuryAttenuators(const QList &attenuators); + + void dspProcessing(); + void stop(); + +private slots: + void setSystemState( + QObject* sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setSampleRate(QObject *sender, int value); + void setFramesPerSecond(QObject *sender, int rx, int value); + + bool initQtDSPInterface(); + void deleteQtDSP(); + + //void setAGCMaximumGain_dBm(QObject* sender, int rx, int value); + void setAGCMaximumGain_dB(QObject* sender, int rx, qreal value); + void setAGCFixedGain_dB(QObject* sender, int rx, qreal value); + void setAGCThreshold_dB(QObject* sender, int rx, qreal value); + void setAGCHangLevel_dB(QObject* sender, int rx, qreal value); + void setAGCHangThreshold(QObject* sender, int rx, int value); + void setAGCVariableGain_dB(QObject* sender, int rx, qreal value); + void setAGCAttackTime(QObject* sender, int rx, qreal value); + void setAGCDecayTime(QObject* sender, int rx, qreal value); + void setAGCHangTime(QObject* sender, int rx, qreal value); + +private: + Settings* set; + + QSDR::_DSPCore m_dspCore; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + TReceiver m_receiverData; + QHostAddress m_peerAddress; + quint16 m_peerPort; + + HamBand m_hamBand; + DSPMode m_dspMode; + AGCMode m_agcMode; + TDefaultFilterMode m_filterMode; + + QList m_lastCtrFrequencyList; + QList m_lastVfoFrequencyList; + QList m_dspModeList; + QList m_mercuryAttenuators; + + QTime m_smeterTime; + QMutex m_mutex; + + volatile bool m_stopped; + + int m_receiver; + int m_samplerate; + int m_audioMode; // 1 = audio on, 0 = audio off + int m_socketDescriptor; + int m_client; + int m_iqPort; + int m_bsPort; + int m_sampleRate; + int m_displayTime; + + long m_ctrFrequency; + long m_vfoFrequency; + + float m_audioVolume; + float m_sMeterValue; + + qreal m_agcGain; + qreal m_agcFixedGain_dB; + qreal m_agcMaximumGain_dB; + qreal m_agcThreshold_dBm; + qreal m_agcHangThreshold; + qreal m_agcHangLevel; + qreal m_agcVariableGain; + qreal m_agcAttackTime; + qreal m_agcDecayTime; + qreal m_agcHangTime; + //qreal m_calOffset; + qreal m_filterLo; + qreal m_filterHi; + qreal m_dBmPanScaleMin; + qreal m_dBmPanScaleMax; + + bool m_connected; + bool m_hangEnabled; + + //void setupConnections(); + +signals: + void messageEvent(QString msg); + void spectrumBufferChanged(int rx, const qVectorFloat& buffer); + void sMeterValueChanged(int rx, float value); + void outputBufferSignal(int rx, const CPX &buffer); + //void audioReady(int rx); +}; + +#endif // CUSDR_RECEIVER_H diff --git a/Source/src/DataEngine/datatypes.h b/Source/src/DataEngine/datatypes.h new file mode 100644 index 0000000..d01b53d --- /dev/null +++ b/Source/src/DataEngine/datatypes.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////// +// datatypes.h: Common data type declarations +// +// History: +// 2010-09-15 Initial creation MSW +// 2011-03-27 Initial release +////////////////////////////////////////////////////////////////////// +#ifndef DATATYPES_H +#define DATATYPES_H + +#include +#include + + +//define single or double precision reals and complex types +typedef float tSReal; +typedef double tDReal; + +typedef struct _sCplx +{ + tSReal re; + tSReal im; +}tSComplex; + +typedef struct _dCplx +{ + tDReal re; + tDReal im; +}tDComplex; + +typedef struct _isCplx +{ + qint16 re; + qint16 im; +}tStereo16; + + +#define TYPEREAL tDReal +#define TYPECPX tDComplex +#define TYPESTEREO16 tStereo16 +#define TYPEMONO16 qint16 + +//#define K_2PI (8.0*atan(1)) //maybe some compilers are't too smart to optimize out +#define K_2PI (2.0 * 3.14159265358979323846) +#define K_PI (3.14159265358979323846) +#define K_PI4 (K_PI/4.0) +#define K_PI2 (K_PI/2.0) +#define K_3PI4 (3.0*K_PI4) + + +#endif // DATATYPES_H diff --git a/Source/src/DataEngine/fractresampler.cpp b/Source/src/DataEngine/fractresampler.cpp new file mode 100644 index 0000000..da3caf4 --- /dev/null +++ b/Source/src/DataEngine/fractresampler.cpp @@ -0,0 +1,352 @@ +////////////////////////////////////////////////////////////////////// +// FractResampler.cpp: implementation of the CFractResampler class. +// +// This class implements a fractional resampler that can be used to +//convert between different sample rates. A windowes sinc interpolator +// is used to create samples "in between" input samples. +// +// History: +// 2010-09-15 Initial creation MSW +// 2011-03-27 Initial release +///////////////////////////////////////////////////////////////////// + +//========================================================================================== +// + + + This Software is released under the "Simplified BSD License" + + + +//Copyright 2010 Moe Wheatley. All rights reserved. +// +//Redistribution and use in source and binary forms, with or without modification, are +//permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other materials +// provided with the distribution. +// +//THIS SOFTWARE IS PROVIDED BY Moe Wheatley ``AS IS'' AND ANY EXPRESS OR IMPLIED +//WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +//FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Moe Wheatley OR +//CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +//CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +//SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +//ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +//NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +//ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +//The views and conclusions contained in the software and documentation are those of the +//authors and should not be interpreted as representing official policies, either expressed +//or implied, of Moe Wheatley. +//========================================================================================== + +#include "fractresampler.h" +#include +#include +#include + +////////////////////////////////////////////////////////////////////// +// Local defines +////////////////////////////////////////////////////////////////////// +#define SINC_PERIOD_PTS 10000 //number of points in sinc table between "zero crossings" + //smaller value increases noise floor + +#define SINC_PERIODS 28 //number of input sample periods("zero crossings"-1) in + //sinc function(should be even) + //decreasing reduces alias free bandwidth + +#define SINC_LENGTH ( (SINC_PERIODS)*SINC_PERIOD_PTS + 1)//number of total points in sinc table + +#define MAX_SOUNDCARDVAL 32767.0 + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// +CFractResampler::CFractResampler() +{ + m_pSinc = NULL; + m_pInputBuf = NULL; + +} + +CFractResampler::~CFractResampler() +{ + if(m_pSinc) + delete m_pSinc; + if(m_pInputBuf) + delete m_pInputBuf; +} +// + +////////////////////////////////////////////////////////////////////// +// Initialize resampler memory and create windowed sinc table +// MaxInputSize is the largest number of input samples expected to be processed +////////////////////////////////////////////////////////////////////// +void CFractResampler::Init(int MaxInputSize) +{ +int i; +TYPEREAL fi; +TYPEREAL window; + MaxInputSize += SINC_PERIODS; //expand buffer size to include wrap around + if(NULL == m_pSinc) + m_pSinc = new TYPEREAL[SINC_LENGTH]; + if(m_pInputBuf) + delete m_pInputBuf; + m_pInputBuf = new TYPECPX[MaxInputSize]; + for(i=0; i MAX_SOUNDCARDVAL) + tmp.re = MAX_SOUNDCARDVAL; + if(tmp.re < -MAX_SOUNDCARDVAL) + tmp.re = -MAX_SOUNDCARDVAL; + if(tmp.im>MAX_SOUNDCARDVAL) + tmp.im = MAX_SOUNDCARDVAL; + if(tmp.im < -MAX_SOUNDCARDVAL) + tmp.im = -MAX_SOUNDCARDVAL; + pOutBuf[outsamples].re = (qint16)tmp.re; + pOutBuf[outsamples++].im = (qint16)tmp.im; + + m_FloatTime += dt; //inc floating pt output time step + IntegerTime = (int)m_FloatTime; //truncate to integer + } + m_FloatTime -= (double)InLength; //move floating time position back for next call + //keeping leftover fraction + //need to copy last SINC_PERIODS input samples in buffer to beginning of buffer + // for FIR wrap around management. j points to last input sample processed + j = InLength; + for(i=0; i MAX_SOUNDCARDVAL) + tmp = MAX_SOUNDCARDVAL; + if(tmp < -MAX_SOUNDCARDVAL) + tmp = -MAX_SOUNDCARDVAL; + pOutBuf[outsamples++] = (TYPEMONO16)tmp; + + m_FloatTime += dt; + IntegerTime = (int)m_FloatTime; + } + m_FloatTime -= (double)InLength; //move floating time position back for next call + //keeping leftover fraction + //need to copy last SINC_PERIODS input samples in buffer to beginning of buffer + // for FIR wrap around management. j points to last input sample processed + j = InLength; + for(i=0; i +#include + +#define SOUNDCARD_RATE 48000 //output soundcard sample rate +//#define SOUNDCARD_RATE 44100 + +#define FILTERQLEVEL_ALPHA 0.001 +#define P_GAIN 2.38e-7 //Proportional gain + +#define TRUE 1 +#define FALSE 0 + +#define TEST_ERROR 1.0 +//#define TEST_ERROR 1.001 //use to force fixed sample rate error for testing +//#define TEST_ERROR 0.999 + +///////////////////////////////////////////////////////////////////// +// constructor/destructor +///////////////////////////////////////////////////////////////////// +CSoundOut::CSoundOut(QObject *parent) : + QThread(parent) +{ + m_pParent = parent; + m_pAudioOutput = NULL; + m_pOutput = NULL; + m_ThreadQuit = true; + m_UserDataRate = SOUNDCARD_RATE; + m_OutRatio = 1.0; + //RRK m_OutAudioFormat.setFrequency(SOUNDCARD_RATE); + m_OutAudioFormat.setSampleRate(SOUNDCARD_RATE); + m_OutResampler.Init(8192); + m_RateCorrection = 0.0; + m_Gain = 1.0; + m_Startup = true; + m_BlockingMode = false; +} + +CSoundOut::~CSoundOut() +{ + Stop(); +} + +void GetAlsaMasterVolume(long *volume) +{ + long min, max; + snd_mixer_t *handle; + snd_mixer_selem_id_t *sid; + const char *card = "default"; + const char *selem_name = "Master"; + + snd_mixer_open(&handle, 0); + snd_mixer_attach(handle, card); + snd_mixer_selem_register(handle, NULL, NULL); + snd_mixer_load(handle); + + snd_mixer_selem_id_alloca(&sid); + snd_mixer_selem_id_set_index(sid, 0); + snd_mixer_selem_id_set_name(sid, selem_name); + snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); + + snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT, volume); + + snd_mixer_close(handle); +} + +void SetAlsaMasterVolume(long volume) +{ + long min, max; + snd_mixer_t *handle; + snd_mixer_selem_id_t *sid; + const char *card = "default"; + const char *selem_name = "Master"; + + snd_mixer_open(&handle, 0); + snd_mixer_attach(handle, card); + snd_mixer_selem_register(handle, NULL, NULL); + snd_mixer_load(handle); + + snd_mixer_selem_id_alloca(&sid); + snd_mixer_selem_id_set_index(sid, 0); + snd_mixer_selem_id_set_name(sid, selem_name); + snd_mixer_elem_t* elem = snd_mixer_find_selem(handle, sid); + + snd_mixer_selem_get_playback_volume_range(elem, &min, &max); + snd_mixer_selem_set_playback_volume_all(elem, volume * max / 100); + + snd_mixer_close(handle); +} + +///////////////////////////////////////////////////////////////////// +// Starts up soundcard output thread using soundcard at list OutDevIndx +///////////////////////////////////////////////////////////////////// +bool CSoundOut::Start(int OutDevIndx, bool StereoOut, double UsrDataRate, bool BlockingMode) +{ +QAudioDeviceInfo DeviceInfo; + long mvolume; + m_StereoOut = StereoOut; + m_BlockingMode = BlockingMode; + //Get required soundcard from list + m_OutDevices = DeviceInfo.availableDevices(QAudio::AudioOutput); + + if (-1 == OutDevIndx) GetAlsaMasterVolume(&mvolume); + qDebug()<<"Soundcard volume" << mvolume; + + if (-1 == OutDevIndx) m_OutDeviceInfo = QAudioDeviceInfo::defaultOutputDevice(); + else m_OutDeviceInfo = m_OutDevices.at(OutDevIndx); + +#if 0 //RRK get a list of audio devices and the default + foreach (const QAudioDeviceInfo &deviceInfo, QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { + qDebug() << "l:" << deviceInfo.deviceName(); + } + + QAudioDeviceInfo info = QAudioDeviceInfo::defaultOutputDevice(); + qDebug() << "res:" << info.deviceName(); +#endif + + //Setup fixed format for sound ouput + m_OutAudioFormat.setCodec("audio/pcm"); + //m_OutAudioFormat.setFrequency(SOUNDCARD_RATE); + m_OutAudioFormat.setSampleRate(SOUNDCARD_RATE); + m_OutAudioFormat.setSampleSize(16); + m_OutAudioFormat.setSampleType(QAudioFormat::SignedInt); + m_OutAudioFormat.setByteOrder(QAudioFormat::LittleEndian); + if(m_StereoOut) + //RRK m_OutAudioFormat.setChannels(2); + m_OutAudioFormat.setChannelCount(2); + else + m_OutAudioFormat.setChannelCount(1); + + m_pAudioOutput = new QAudioOutput(m_OutDeviceInfo, m_OutAudioFormat, this); + if(!m_pAudioOutput) + { + qDebug()<<"Soundcard output error"; + return false; + } + if(QAudio::NoError == m_pAudioOutput->error() ) + { + //initialize the data queue variables + m_UserDataRate = 1; //force user data rate to be changed + ChangeUserDataRate(UsrDataRate); + m_pOutput = m_pAudioOutput->start(); //start QT AudioOutput + + //RRK workaround for default, for some reason choosing default + //sets the master volume to max! + if (-1 == OutDevIndx) SetAlsaMasterVolume(50); + + //determine how long to sleep between low level reads based on samplerate and period size + m_BlockTime = ( 250*m_pAudioOutput->periodSize() )/ + ( SOUNDCARD_RATE*m_OutAudioFormat.channelCount() ); + //RRK ( SOUNDCARD_RATE*m_OutAudioFormat.channels() ); +//qDebug()<<"periodSize "<periodSize(); +//qDebug()<<"BlockTime "<stop(); + wait(500); + } + if(NULL != m_pAudioOutput) + { + delete m_pAudioOutput; + m_pAudioOutput = NULL; + } +} + +///////////////////////////////////////////////////////////////////// +// Sets/changes user data input rate +///////////////////////////////////////////////////////////////////// +void CSoundOut::ChangeUserDataRate(double UsrDataRate) +{ + if(m_UserDataRate != UsrDataRate) + { + m_UserDataRate = UsrDataRate; + for(int i=0; iOUTQSIZE/2) + { + m_Startup = false; + m_RateUpdateCount = -5*SOUNDCARD_RATE; //delay first error update to let settle + m_PpmError = 0; + m_AveOutQLevel = m_OutQLevel; + m_UpdateToggle = true; + } + else + { + m_Mutex.unlock(); + return; + } + } + + for( i=0; i= SOUNDCARD_RATE) //every second + { + CalcError(); + m_RateUpdateCount = 0; + } + m_Mutex.unlock(); +} + +//////////////////////////////////////////////////////////////// +//Called by CSoundOut worker thread to get new samples from queue +// This routine is called from a worker thread so must be careful. +// STEREO version +//////////////////////////////////////////////////////////////// +void CSoundOut::GetOutQueue(int numsamples, TYPESTEREO16* pData ) +{ +int i; +bool underflow = false; + m_Mutex.lock(); + if(m_Startup) + { //if no data in queue yet just stuff in silence until something is put in queue + for( i=0; iOUTQSIZE/2) + { + m_Startup = false; + m_RateUpdateCount = -5*SOUNDCARD_RATE; //delay first error update to let settle + m_PpmError = 0; + m_AveOutQLevel = m_OutQLevel; + m_UpdateToggle = true; + } + else + { + m_Mutex.unlock(); + return; + } + } + + for( i=0; i= SOUNDCARD_RATE) //every second + { + CalcError(); + m_RateUpdateCount = 0; + } + m_Mutex.unlock(); +} + +//////////////////////////////////////////////////////////////// +// Called alternately from the Get routines to update the +// error correction process +//////////////////////////////////////////////////////////////// +void CSoundOut::CalcError() +{ +double error; + error = (double)(m_AveOutQLevel - OUTQSIZE/2 ); //neg==level is too low pos == level is to high + error = error * P_GAIN; + m_RateCorrection = error; + m_PpmError = (int)( m_RateCorrection*1e6 ); + if( abs(m_PpmError) > 500) + { +// qDebug()<<"SoundOut "<state() ) || + (QAudio::ActiveState == m_pAudioOutput->state() ) ) + { //Process sound data while soundcard is active and no errors + unsigned int len = m_pAudioOutput->bytesFree(); //in bytes + if( len>0 ) + { + //limit size to SOUND_WRITEBUFSIZE + if(len > SOUND_WRITEBUFSIZE) + len = SOUND_WRITEBUFSIZE; + if(m_StereoOut) + { + len &= ~(0x03); //keep on 4 byte chunks + GetOutQueue( len/4, (TYPESTEREO16*)m_pData ); + } + else + { + len &= ~(0x01); //keep on 2 byte chunks + GetOutQueue( len/2, (TYPEMONO16*)m_pData ); + } + m_pOutput->write((char*)m_pData,len); + } + else //no room in sound card output buffer so wait + { //not good but no other wait or blocking mechanism available + msleep(m_BlockTime); + } + } + else + { //bail out if error occurs + qDebug()<<"SoundOut Error"; +#if 0 //RRK + if(m_pParent) + ((CSdrInterface*)m_pParent)->SendIOStatus(CSdrInterface::ERROR); +#endif + m_ThreadQuit = true; + } + } + qDebug()<<"sound thread exit"; +} diff --git a/Source/src/DataEngine/soundout.h b/Source/src/DataEngine/soundout.h new file mode 100644 index 0000000..f5b4abf --- /dev/null +++ b/Source/src/DataEngine/soundout.h @@ -0,0 +1,76 @@ +////////////////////////////////////////////////////////////////////// +// soundout.h: interface for the CSoundOut class. +// +// History: +// 2010-09-15 Initial creation MSW +// 2011-03-27 Initial release +///////////////////////////////////////////////////////////////////// +#ifndef SOUNDOUT_H +#define SOUNDOUT_H + +#include +#include +#include +#include +#include +#include "fractresampler.h" +#include +#include + +#define OUTQSIZE 16384 //max samples (keep power of 2 for ptr wrap around) +#define SOUND_WRITEBUFSIZE 8192 + +class CSoundOut : public QThread +{ + Q_OBJECT +public: + explicit CSoundOut(QObject *parent = 0); + virtual ~CSoundOut(); + + //Exposed functions + bool Start(int OutDevIndx, bool StereoOut, double UsrDataRate, bool BlockingMode); //starts soundcard output + void Stop(); //stops soundcard output + void PutOutQueue(int numsamples, TYPEREAL* pData ); + void PutOutQueue(int numsamples, TYPECPX* pData ); + void ChangeUserDataRate(double UsrDataRate); + void SetVolume(qint32 vol); + int GetRateError(){return (int)m_PpmError;} + +protected: + void run(); //implements worker thread loop + int m_BlockTime; + +private: + void GetOutQueue(int numsamples, TYPEMONO16* pData ); + void GetOutQueue(int numsamples, TYPESTEREO16* pData ); + void CalcError(); + + QList m_OutDevices; + QAudioDeviceInfo m_OutDeviceInfo; + QAudioFormat m_OutAudioFormat; + QAudioOutput* m_pAudioOutput; + QIODevice* m_pOutput; // ptr to internal soundout IODevice + QObject* m_pParent; + QMutex m_Mutex; + CFractResampler m_OutResampler; + + TYPEMONO16 m_OutQueueMono[OUTQSIZE]; + TYPESTEREO16 m_OutQueueStereo[OUTQSIZE]; + bool m_BlockingMode; + bool m_ThreadQuit; + bool m_Startup; + bool m_StereoOut; + bool m_UpdateToggle; + quint32 m_OutQHead; + quint32 m_OutQTail; + char m_pData[SOUND_WRITEBUFSIZE]; + int m_RateUpdateCount; + int m_OutQLevel; + int m_PpmError; + double m_Gain; + double m_UserDataRate; + double m_OutRatio; + double m_RateCorrection; + double m_AveOutQLevel; +}; +#endif // SOUNDOUT_H diff --git a/Source/src/GL/cusdr_oglDisplayPanel.cpp b/Source/src/GL/cusdr_oglDisplayPanel.cpp new file mode 100644 index 0000000..96ace20 --- /dev/null +++ b/Source/src/GL/cusdr_oglDisplayPanel.cpp @@ -0,0 +1,2827 @@ +/** +* @file cusdr_oglDisplayPanel.cpp +* @brief Display panel class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-22 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_DISPLAYPANEL + +#include "cusdr_oglDisplayPanel.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809D +#endif + + +OGLDisplayPanel::OGLDisplayPanel(QWidget *parent) + : QGLWidget(QGLFormat(QGL::SampleBuffers), parent) + + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_smeterUpdate(true) + , m_smeterRenew(true) + , m_sMeterAvg(true) + , m_oldFreq(0) + , m_height(120)//(120) + , m_sMeterWidth(300) + , m_rxRectWidth(500) + , m_lowerRectY(12) + , m_upperRectY(1) + , m_syncStatus(0) + , m_adcStatus(0) + , m_packetLossStatus(0) + , m_sendIQStatus(0) + , m_recvAudioStatus(0) + , m_receivers(set->getNumberOfReceivers()) + , m_sample_rate(set->getSampleRate()/1000) + , m_dither(set->getMercuryDither()) + , m_random(set->getMercuryRandom()) + , m_currentReceiver(set->getCurrentReceiver()) + , m_sMeterDeform(15) + , m_freqDigitsPosY(30) + , m_sMeterPosY(50)//(45) + , m_sMeterHoldTime(set->getSMeterHoldTime()) + , m_sMeterPrevHoldTimeMax(0) + , m_sMeterPrevHoldTimeMin(0) + , m_sMeterMeanValueCnt(0) + , m_mouseWheelFreqStep(set->getMouseWheelFreqStep(m_currentReceiver)) + , m_dBmPanMin(-130.0f) + , m_dBmPanMax(10.0f) + , m_unit(1.0f) + , m_smeterVertices(256.0f) + , m_sMeterValue((float)(-156*ONEPI/256.0f)) + , m_sMeterMeanValue(0.0f) + , m_sMeterMaxValueA((float)(-ONEPI/2.0f)) + , m_sMeterMinValueA((float)(ONEPI/2.0f)) + , m_sMeterMaxValueB(-1000.0f) + , m_sMeterMinValueB(1000.0f) +{ +// QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + setAutoBufferSwap(true); + setAutoFillBackground(false); + setMouseTracking(true); + + m_freqStringLeftPos = 20; + setupDisplayRegions(size()); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_fonts.smallFont.setBold(true); + m_oglTextTiny = new OGLText(m_fonts.tinyFont); + m_oglTextSmall = new OGLText(m_fonts.smallFont); + + m_fonts.smallFont.setItalic(true); + //m_fonts.smallFont.setBold(true); + m_oglTextSmallItalic = new OGLText(m_fonts.smallFont); + m_oglTextNormal = new OGLText(m_fonts.normalFont); + m_oglTextBig = new OGLText(m_fonts.bigFont); + + m_fonts.bigFont.setItalic(true); + m_oglTextBigItalic = new OGLText(m_fonts.bigFont); + m_oglTextFreq1 = new OGLText(m_fonts.freqFont1); + m_oglTextFreq2 = new OGLText(m_fonts.freqFont2); + m_oglTextImpact = new OGLText(m_fonts.impactFont); + + setupConnections(); + setupTextstrings(); + + set10mhzSource(this, set->get10MHzSource()); + set122_88mhzSource(this, set->get122_8MHzSource()); + + QList fList = set->getVfoFrequencies(); + + for (int i = 0; i < MAX_RECEIVERS; i++) { + + TFrequency f; + f.freqMHz = (int)(fList.at(i) / 1000); + f.freqkHz = (int)(fList.at(i) % 1000); + + m_frequencyList << f; + } + + QList bandList = getHamBandFrequencies(); + HamBand band = getBandFromFrequency(bandList, fList.at(0)); + + m_mercuryAttenuator = set->getMercuryAttenuators(0).at(band); + + + m_smeterFBO = 0; + + m_colors = set->getPanadapterColors(); + + m_digitColor = QColor(68, 68, 68); + m_bkgColor1 = QColor(30, 30, 30); + m_bkgColor2 = QColor(50, 50, 50); + m_activeTextColor = QColor(166, 196, 208); + m_inactiveTextColor = QColor(68, 68, 68);//Qt::white;// + m_textBackgroundColor = QColor(66, 96, 208); + + m_sMeterTimer.start(); + m_sMeterMaxTimer.start(); + m_sMeterMinTimer.start(); + m_sMeterDisplayTime.start(); + + m_SMeterA = false; + //m_SMeterA = true; +} + +OGLDisplayPanel::~OGLDisplayPanel() { +} + +QSize OGLDisplayPanel::minimumSizeHint() const { + + return QSize(width(), m_height); +} + +QSize OGLDisplayPanel::sizeHint() const { + + //return QSize(width(), height()); + return QSize(width(), m_height); +} + +void OGLDisplayPanel::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setFrequency(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(numberOfRXChanged(QObject *, int)), + this, + SLOT(setReceivers(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(setMercuryAttenuator(QObject *, HamBand, int))); + + CHECKED_CONNECT( + set, + SIGNAL(ditherChanged(QObject *, int)), + this, + SLOT(setDither(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(randomChanged(QObject *, int)), + this, + SLOT(setRandom(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(setSampleRate(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryPresenceChanged(bool)), + this, + SLOT(setMercuryPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryVersionChanged(int)), + this, + SLOT(setMercuryVersion(int))); + + CHECKED_CONNECT( + set, + SIGNAL(penelopePresenceChanged(bool)), + this, + SLOT(setPenelopePresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(pennyLanePresenceChanged(bool)), + this, + SLOT(setPennylanePresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(metisVersionChanged(int)), + this, + SLOT(setMetisVersion(int))); + + CHECKED_CONNECT( + set, + SIGNAL(penelopeVersionChanged(int)), + this, + SLOT(setPenelopeVersion(int))); + + CHECKED_CONNECT( + set, + SIGNAL(penelopeVersionChanged(int)), + this, + SLOT(setPennylaneVersion(int))); + + CHECKED_CONNECT( + set, + SIGNAL(hermesVersionChanged(int)), + this, + SLOT(setHermesVersion(int))); + + CHECKED_CONNECT( + set, + SIGNAL(alexPresenceChanged(bool)), + this, + SLOT(setAlexPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(excaliburPresenceChanged(bool)), + this, + SLOT(setExcaliburPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(src10MhzChanged(QObject *, int)), + this, + SLOT(set10mhzSource(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(src122_88MhzChanged(QObject *, int)), + this, + SLOT(set122_88mhzSource(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(protocolSyncChanged(int)), + this, + SLOT(setSyncStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(adcOverflowChanged(int)), + this, + SLOT(setADCStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(packetLossChanged(int)), + this, + SLOT(setPacketLossStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(sendIQSignalChanged(int)), + this, + SLOT(setSendIQStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(rcveIQSignalChanged(int)), + this, + SLOT(setRecvAudioStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(mouseWheelFreqStepChanged(QObject*, int, qreal)), + this, + SLOT(setMouseWheelFreqStep(QObject*, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(sMeterValueChanged(int, float)), + this, + SLOT(setSMeterValue(int, float))); + + CHECKED_CONNECT( + set, + SIGNAL(sMeterHoldTimeChanged(int)), + this, + SLOT(setSMeterHoldTime(int))); +} + +void OGLDisplayPanel::setupTextstrings() { + + m_blankWidth = m_oglTextSmall->fontMetrics().width("."); + m_blankHeight = m_oglTextSmall->fontMetrics().height()-1; + + m_pointStringWidth = m_oglTextFreq1->fontMetrics().width("."); + m_blankWidthf = m_oglTextFreq1->fontMetrics().width("59.999"); + m_blankWidthf1 = m_oglTextFreq1->fontMetrics().width("0"); + m_blankWidthf2 = m_oglTextFreq2->fontMetrics().width("0"); + m_fUnitStringWidth = m_oglTextFreq2->fontMetrics().width("MHz"); + + m_versionStringWidth = m_oglTextSmall->fontMetrics().width("2.22"); + + m_SYNCString = QString("SYNC"); + m_syncWidth = m_oglTextSmall->fontMetrics().width(m_SYNCString); + + m_ADCString = QString("ADC"); + m_adcWidth = m_oglTextSmall->fontMetrics().width(m_ADCString); + + m_PacketLossString = QString("IP Packets"); + m_packetLossWidth = m_oglTextSmall->fontMetrics().width(m_PacketLossString); + + m_sendIQString = QString("send IQ"); + m_sendIQWidth = m_oglTextSmall->fontMetrics().width(m_sendIQString); + + m_recvAudioString = QString("recv Audio"); + m_recvAudioWidth = m_oglTextSmall->fontMetrics().width(m_recvAudioString); + + m_AttnString = QString("Attn:"); + m_AttnWidth = m_oglTextSmall->fontMetrics().width(m_AttnString); + + m_ditherString = QString("Dither"); + m_ditherWidth = m_oglTextSmall->fontMetrics().width(m_ditherString); + + m_randomString = QString("Random"); + m_randomWidth = m_oglTextSmall->fontMetrics().width(m_randomString); + + m_sampleRateString = QString("SampleRate:"); + m_sampleRateWidth = m_oglTextSmall->fontMetrics().width(m_sampleRateString); + + m_modusString = QString("Modus:"); + m_modusWidth = m_oglTextSmall->fontMetrics().width(m_modusString); + + m_10MHzString = QString("10 MHz:"); + m_10MHzWidth = m_oglTextSmall->fontMetrics().width(m_10MHzString); + + m_12288MHzString = QString("122.88 MHz:"); + m_12288MHzWidth = m_oglTextSmall->fontMetrics().width(m_12288MHzString); + + m_mercuryString = QString("Mercury "); + m_mercuryStringWidth = m_oglTextSmall->fontMetrics().width(m_mercuryString); + + m_penelopeString = QString("Penelope "); + m_penelopeStringWidth = m_oglTextSmall->fontMetrics().width(m_penelopeString); + + m_pennylaneString = QString("Pennylane "); + m_pennylaneStringWidth = m_oglTextSmall->fontMetrics().width(m_pennylaneString); + + m_excaliburString = QString("Excalibur "); + m_excaliburStringWidth = m_oglTextSmall->fontMetrics().width(m_excaliburString); + + m_metisString = QString("Metis "); + m_metisStringWidth = m_oglTextSmall->fontMetrics().width(m_metisString); + + m_alexString = QString("Alex "); + m_alexStringWidth = m_oglTextSmall->fontMetrics().width(m_alexString); + + m_hermesString = QString("Hermes "); + m_hermesStringWidth = m_oglTextSmall->fontMetrics().width(m_hermesString); + + m_hermesStepAttnString = QString("Hermes Step-Attn:"); + m_hermesStepAttnStringWidth = m_oglTextSmall->fontMetrics().width(m_hermesStepAttnString); + +} + +void OGLDisplayPanel::initializeGL() { + + if (!isValid()) return; + + //***************************************************************** + // default initialization + + //glShadeModel(GL_FLAT); + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.5f); + //glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + //glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + glDisable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glDisable(GL_POINT_SMOOTH); + glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); + glEnable(GL_POLYGON_SMOOTH); + glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + //glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glEnable(GL_MULTISAMPLE); +} + +void OGLDisplayPanel::resizeGL(int iWidth, int iHeight) { + + int width = (int)(iWidth/2) * 2; + int height = iHeight; + + glFinish(); + + //m_resizeTime.restart(); + setupDisplayRegions(QSize(width, height)); + glViewport(0, 0, (GLsizei)width, (GLsizei)height); + + setProjectionOrthographic(width, height); +} + +void OGLDisplayPanel::paintGL() { + + glClearColor(0, 0, 0, 1.0); + glClear(GL_DEPTH_BUFFER_BIT); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + //m_mutex.lock(); + paintUpperRegion(); + paintRxRegion(); + paintLowerRegion(); + paintSMeter(); + //m_mutex.unlock(); +} + +void OGLDisplayPanel::paintUpperRegion() { + + QString str; + + GLint x1 = m_rxRect.left() + m_blankWidth; + GLint y1 = m_rxRect.top() + m_upperRectY; + + // sync status + str = QString(m_SYNCString); + QRect rect = QRect(x1, y1, m_syncWidth + 2*m_blankWidth, m_blankHeight); + + switch (m_syncStatus) { + + case 0: + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + break; + + case 1: + drawGLRect(rect, QColor(56, 242, 115), -2.0f); + break; + + case 2: + drawGLRect(rect, QColor(242, 56, 109), -2.0f); + break; + } + qglColor(QColor(0, 0, 0)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, m_SYNCString); + + // ADC status + str = QString(m_ADCString); + x1 += m_syncWidth + 2*m_blankWidth + 2; + rect = QRect(x1, y1, m_adcWidth + 2*m_blankWidth, m_blankHeight); + + switch (m_adcStatus) { + + case 0: + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + break; + + case 1: + drawGLRect(rect, QColor(56, 242, 115), -2.0f); + break; + + case 2: + drawGLRect(rect, QColor(242, 56, 109), -2.0f); + break; + } + qglColor(QColor(0, 0, 0)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, m_ADCString); + + // Packet loss status + str = QString(m_PacketLossString); + x1 += m_adcWidth + 2*m_blankWidth + 2; + rect = QRect(x1, y1, m_packetLossWidth + 2*m_blankWidth, m_blankHeight); + + switch (m_packetLossStatus) { + + case 0: + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + break; + + case 1: + drawGLRect(rect, QColor(56, 242, 115), -2.0f); + break; + + case 2: + drawGLRect(rect, QColor(242, 56, 109), -2.0f); + break; + } + qglColor(QColor(0, 0, 0)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, m_PacketLossString); + +// // send IQ data status +// str = QString(m_sendIQString); +// rect = QRect(x1+63, y1 + m_upperRectY, d_fm.tightBoundingRect(str).width() + 6, fontHeight + 4); +// +// switch (m_sendIQStatus) { +// +// case 0: +// drawGLRect(rect, QColor(68, 68, 68), -2.0f); +// //qglColor(QColor(100, 100, 100)); +// break; +// +// case 1: +// drawGLRect(rect, QColor(56, 242, 115), -2.0f); +// //qglColor(QColor(56, 242, 115)); +// break; +// +// case 2: +// drawGLRect(rect, QColor(242, 56, 109), -2.0f); +// //qglColor(QColor(242, 56, 109)); +// break; +// } +// qglColor(QColor(0, 0, 0)); +// m_oglTextSmallItalic->renderText(m_syncWidth + m_adcWidth + 19, y1 + m_upperRectY, m_sendIQString); + +// // receiver Audio status +// str = QString(m_recvAudioString); +// rect = QRect(x1+108, y1 + m_upperRectY, d_fm.tightBoundingRect(str).width() + 8, fontHeight + 4); +// +// switch (m_recvAudioStatus) { +// +// case 0: +// drawGLRect(rect, QColor(68, 68, 68), -2.0f); +// //qglColor(QColor(100, 100, 100)); +// break; +// +// case 1: +// drawGLRect(rect, QColor(56, 242, 115), -2.0f); +// //qglColor(QColor(56, 242, 115)); +// break; +// +// case 2: +// drawGLRect(rect, QColor(242, 56, 109), -2.0f); +// //qglColor(QColor(242, 56, 109)); +// break; +// } +// qglColor(QColor(0, 0, 0)); +// m_oglTextSmallItalic->renderText(m_syncWidth + m_adcWidth + m_sendIQWidth + 29, y1 + m_upperRectY, m_recvAudioString); + + + // Metis status + str = m_metisString; + x1 += m_packetLossWidth + 15*m_blankWidth; + + if (m_hwInterface == QSDR::Metis && m_dataEngineState == QSDR::DataEngineUp) + rect = QRect(x1, y1, m_metisStringWidth + m_versionStringWidth, m_blankHeight); + else + rect = QRect(x1, y1, m_metisStringWidth, m_blankHeight); + + if (m_hwInterface == QSDR::Metis) { + + drawGLRect(rect, m_textBackgroundColor, -2.0f); + if (m_dataEngineState == QSDR::DataEngineUp) { + + str.append(m_metisVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else { + + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + qglColor(QColor(0, 0, 0)); + } + m_oglTextSmallItalic->renderText(x1, y1, 1.0f, str); + + + // Mercury status + str = m_mercuryString; + + if (m_hwInterface == QSDR::Metis && m_dataEngineState == QSDR::DataEngineUp) { + x1 += m_metisStringWidth + m_versionStringWidth + m_blankWidth; + rect = QRect(x1, y1, m_mercuryStringWidth + m_versionStringWidth, m_blankHeight); + } + else { + x1 += m_metisStringWidth + m_blankWidth; + rect = QRect(x1, y1, m_mercuryStringWidth, m_blankHeight); + } + + //rect = QRect(x1, y1, m_mercuryStringWidth + m_versionStringWidth, m_blankHeight); + + if (set->getMercuryPresence() && m_hwInterface == QSDR::Metis) { + drawGLRect(rect, m_textBackgroundColor, -2.0f); + + if (m_dataEngineState == QSDR::DataEngineUp) { + str.append(m_mercuryVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else { + + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + qglColor(QColor(0, 0, 0)); + } + + //m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, 1.0f, str); + m_oglTextSmallItalic->renderText(x1, y1, 1.0f, str); + + + // Penelope status + str = m_penelopeString; + + if (m_hwInterface == QSDR::Metis && m_dataEngineState == QSDR::DataEngineUp) + x1 += m_mercuryStringWidth + m_versionStringWidth + m_blankWidth; + else + x1 += m_mercuryStringWidth + m_blankWidth; + + if (set->getPenelopePresence() && m_hwInterface == QSDR::Metis) { + str = m_penelopeString; + + if (m_dataEngineState == QSDR::DataEngineUp) + rect = QRect(x1, y1, m_penelopeStringWidth + m_versionStringWidth, m_blankHeight); + else + rect = QRect(x1, y1, m_penelopeStringWidth, m_blankHeight); + + drawGLRect(rect, m_textBackgroundColor, -2.0f); + + if (m_dataEngineState == QSDR::DataEngineUp) { + str.append(m_penelopeVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else if (set->getPennyLanePresence() && m_hwInterface == QSDR::Metis) { + str = m_pennylaneString; + + if (m_dataEngineState == QSDR::DataEngineUp) + rect = QRect(x1, y1, m_pennylaneStringWidth + m_versionStringWidth, m_blankHeight); + else + rect = QRect(x1, y1, m_pennylaneStringWidth, m_blankHeight); + + drawGLRect(rect, m_textBackgroundColor, -2.0f); + + if (m_dataEngineState == QSDR::DataEngineUp) { + str.append(m_pennylaneVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else { +// if (m_dataEngineState == QSDR::DataEngineUp && m_hwInterface == QSDR::Metis) +// rect = QRect(x1, y1, m_penelopeStringWidth + m_versionStringWidth, m_blankHeight); +// else + rect = QRect(x1, y1, m_penelopeStringWidth, m_blankHeight); + + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + qglColor(QColor(0, 0, 0)); + } + + m_oglTextSmallItalic->renderText(x1, y1, 1.0f, str); + + + // Hermes status + str = m_hermesString; + + if(set->getPennyLanePresence()) + x1 += m_pennylaneStringWidth; + else + x1 += m_penelopeStringWidth; + + x1 += m_blankWidth; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if(m_hwInterface == QSDR::Metis) { + + if(set->getPenelopePresence() || set->getPennyLanePresence()) + x1 += m_versionStringWidth; + + rect = QRect(x1, y1, m_hermesStringWidth, m_blankHeight); + } + else { + rect = QRect(x1, y1, m_hermesStringWidth + m_versionStringWidth, m_blankHeight); + } + } + else { + rect = QRect(x1, y1, m_hermesStringWidth, m_blankHeight); + } + + if (set->getHPSDRHardware() == 1) { + drawGLRect(rect, m_textBackgroundColor, -2.0f); + + if (m_dataEngineState == QSDR::DataEngineUp) { + str.append(m_hermesVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else { + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + qglColor(QColor(0, 0, 0)); + } + + //m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, 1.0f, str); + m_oglTextSmallItalic->renderText(x1, y1, 1.0f, str); + + + // Excalibur status + str = m_excaliburString; + +// if (m_dataEngineState == QSDR::DataEngineUp && set->getHermesPresence()) + if (m_dataEngineState == QSDR::DataEngineUp && m_hwInterface == QSDR::Hermes) + x1 += m_hermesStringWidth + m_versionStringWidth + m_blankWidth; + else + x1 += m_hermesStringWidth + m_blankWidth; + + //rect = QRect(x1, y1, m_hermesStringWidth + m_versionStringWidth, m_blankHeight); + rect = QRect(x1, y1, m_excaliburStringWidth, m_blankHeight); + + if (set->getExcaliburPresence() && m_hwInterface == QSDR::Metis) { + + drawGLRect(rect, m_textBackgroundColor, -2.0f); + if (m_dataEngineState == QSDR::DataEngineUp) { + + str.append(m_excaliburVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else { + + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + qglColor(QColor(0, 0, 0)); + } + //m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, 1.0f, str); + m_oglTextSmallItalic->renderText(x1, y1, 1.0f, str); + + + // Alex status + str = m_alexString; + //x1 += m_hermesStringWidth + m_versionStringWidth + m_blankWidth; + x1 += m_excaliburStringWidth + m_blankWidth; + + rect = QRect(x1, y1, m_alexStringWidth + m_blankWidth, m_blankHeight); + + if (set->getAlexPresence()) { + + drawGLRect(rect, m_textBackgroundColor, -2.0f); + if (m_dataEngineState == QSDR::DataEngineUp) { + + str.append(m_alexVersion); + qglColor(QColor(206, 236, 248)); + } + else + qglColor(QColor(0, 0, 0)); + } + else { + + drawGLRect(rect, QColor(68, 68, 68), -2.0f); + qglColor(QColor(0, 0, 0)); + } + //m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y1, 1.0f, str); + m_oglTextSmallItalic->renderText(x1, y1, 1.0f, str); +} + +void OGLDisplayPanel::paintLowerRegion() { + + QString str; + + GLint x1 = m_rxRect.left() + m_blankWidth; + GLint y2 = m_rxRect.height() - m_lowerRectY; + + // Attenuator + qglColor(QColor(106, 136, 148)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_AttnString); + + x1 += m_AttnWidth + 2*m_blankWidth; + if (m_mercuryAttenuator == 1) + str = "0 dB"; + else + str = "-20 dB"; + + int attnValueWidth = m_oglTextSmall->fontMetrics().tightBoundingRect(str).width(); + qglColor(m_activeTextColor); + m_oglTextSmallItalic->renderText(x1, y2, str); + + // Dither status + x1 += attnValueWidth + 5*m_blankWidth; + + if (m_dither == 1) + qglColor(m_activeTextColor); + else + qglColor(QColor(68, 68, 68)); + + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_ditherString); + + // Random status + x1 += m_ditherWidth + 5*m_blankWidth; + + if (m_random == 1) + qglColor(m_activeTextColor); + else + qglColor(QColor(68, 68, 68)); + + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_randomString); + + // Sample rate status + x1 += m_randomWidth + 10*m_blankWidth; + str = "%1"; + + qglColor(QColor(166, 196, 208)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, str.arg(m_sample_rate, 3, 10, QLatin1Char(' '))); + + int samplerateWidth = m_oglTextSmall->fontMetrics().tightBoundingRect(str.arg(m_sample_rate, 3, 10, QLatin1Char(' '))).width(); + x1 += samplerateWidth + 4*m_blankWidth; + + str = "kHz"; + int samplerateUnitWidth = m_oglTextSmall->fontMetrics().tightBoundingRect(str).width(); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, str); + + + // server modus status + x1 += samplerateUnitWidth + 10*m_blankWidth; + switch (m_serverMode) { + + case QSDR::DemoMode: + + str = "Demo mode"; + break; + + case QSDR::NoServerMode: + + str = "No Server mode"; + break; + + case QSDR::SDRMode: + + str = "SDR Mode"; + break; + + case QSDR::ChirpWSPR: + + str = "Chirp Dec"; + break; + + case QSDR::ChirpWSPRFile: + + str = "Chirp Dec File"; + break; + } + int serverModeStringWidth = m_oglTextSmall->fontMetrics().tightBoundingRect(str).width(); + + qglColor(QColor(166, 196, 208)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, str); + + if (m_hwInterface == QSDR::Metis) { + + x1 += serverModeStringWidth + 15*m_blankWidth; + + // 10 MHz source status + qglColor(QColor(106, 136, 148)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_10MHzString); + + x1 += m_10MHzWidth + 4*m_blankWidth; + qglColor(QColor(166, 196, 208)); + int src10MHStringWidth = m_oglTextSmall->fontMetrics().tightBoundingRect(m_src10mhz).width(); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_src10mhz); + + // 122.88 MHz source status + x1 += src10MHStringWidth + 10*m_blankWidth; + qglColor(QColor(106, 136, 148)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_12288MHzString); + + x1 += m_12288MHzWidth + 4*m_blankWidth; + qglColor(QColor(166, 196, 208)); + m_oglTextSmallItalic->renderText(x1 + m_blankWidth, y2, m_src122_88mhz); + } + else if (m_hwInterface == QSDR::Hermes) { + + //x1 += serverModeStringWidth + 10*m_blankWidth; + + //qglColor(QColor(166, 196, 208)); + //m_oglTextSmallItalic->renderText(x1, y2, m_hermesStepAttnString); + + //x1 += m_hermesStepAttnStringWidth + 2*m_blankWidth; + //y2 += 1; + + //QColor triCol; + //QColor onLCol = QColor(0x11, 0x6b, 0x7f);//QColor(26, 56, 168); + //QColor onHCol = QColor(0x51, 0xab, 0xbf);//QColor(66, 96, 208); + //QColor offCol = QColor(68, 68, 68); + + //if (m_dataEngineState == QSDR::DataEngineUp) + // triCol = QColor(156, 186, 198); + //else + // triCol = QColor(68, 68, 68); + + //QRect rect = QRect(x1, y2, 9, 10); + //drawGLTriangleLeft(rect, triCol, -2.0f); + //x1 += 10; + + //for (int i = 0; i < 31; i++) { + + // rect = QRect(x1 + i*4, y2, 3, 10); + // if (m_dataEngineState == QSDR::DataEngineUp) { + + // if (i < 19) + // drawGLRect(rect, onHCol, -2.0f); + // else + // drawGLRect(rect, onLCol, -2.0f); + // } + // else + // drawGLRect(rect, offCol, -2.0f); + //} + + //x1 += 124; + //rect = QRect(x1, y2, 9, 10); + //drawGLTriangleRight(rect, triCol, -2.0f); + + //if (m_dataEngineState == QSDR::DataEngineUp) + // qglColor(QColor(166, 196, 208)); + //else + // qglColor(QColor(0, 0, 0)); + + //x1 += 12; + //m_oglTextSmallItalic->renderText(x1, y2, "-19 dB"); + } +} + +void OGLDisplayPanel::paintRxRegion() { + + QString str; + + GLint x1 = m_rxRect.left() + 20; + GLint y1 = m_rxRect.top() + m_freqDigitsPosY; + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) { + + drawGLRect(m_rect, Qt::black, m_bkgColor2, -3.0f, false); + qglColor(m_activeTextColor); + } + else { + + drawGLRect(m_rect, QColor(0, 0, 0, 255), -3.0f); + qglColor(QColor(68, 68, 68)); + } + + str = "%1.%2"; + + int f1 = m_frequencyList[m_currentReceiver].freqMHz; + int f2 = m_frequencyList[m_currentReceiver].freqkHz; + + QString f1str = str.arg(f1/1000).arg(f1 - 1000 * (int)(f1/1000), 3, 10, QLatin1Char('0')); + + if (f1 / 1000 < 10) + x1 += m_blankWidthf1; + + m_freqStringLeftPos = x1; + m_oglTextFreq1->renderText(x1, y1, f1str); + + str = "%1"; + x1 = m_rxRect.left() + m_blankWidthf + 2*m_blankWidthf2; + + QString f2str = str.arg(f2, 3, 10, QLatin1Char('0')); + //int f2strWidth = m_oglTextFreq2->fontMetrics().tightBoundingRect(f2str).width(); + + m_oglTextFreq2->renderText(x1, y1 + 1, f2str); + + //x1 += f2strWidth + m_blankWidthf2; + x1 = m_rxRect.left() + m_blankWidthf + 6*m_blankWidthf2; + m_oglTextFreq1->renderText(x1, y1 - 1, "MHz"); + + // current mouse wheel step size + str = "step: %1"; + x1 += m_fUnitStringWidth + 4*m_blankWidthf2; + + m_oglTextNormal->renderText(x1, y1 + 2, str.arg(set->getValue1000(m_mouseWheelFreqStep, 0, "Hz"))); + + // current receiver + str = "Rx: %1"; + m_oglTextBig->renderText(x1, y1 + 1.5f * m_fonts.fontHeightBigFont, str.arg(m_currentReceiver + 1)); + + // frequency info + if (m_oldFreq != m_frequencyList[m_currentReceiver].frequency) { + + m_bandText = getHamBandTextString(set->getHamBandTextList(), false, m_frequencyList[m_currentReceiver].frequency); + m_oldFreq = m_frequencyList[m_currentReceiver].frequency; + } + + m_oglTextSmall->renderText(m_freqStringLeftPos, y1 + 1.75*m_fonts.fontHeightFreqFont1, m_bandText); +} + +void OGLDisplayPanel::paintSMeter() { + + GLint width = m_smeterRect.width(); + GLint height = m_smeterRect.height(); + GLint x1 = m_smeterRect.left(); + GLint x2 = x1 + width; + GLint y1 = m_smeterRect.top(); + GLint y2 = y1 + height; + + //float X = m_smeterRect.left() + width/2.0f; + //float Y = 370; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glEnable(GL_LINE_SMOOTH); + + if (!m_smeterFBO || m_smeterUpdate || m_smeterRenew) { + + if (!m_smeterFBO || m_smeterRenew) { + + if (m_smeterFBO) { + + delete m_smeterFBO; + m_smeterFBO = 0; + } + + m_smeterFBO = new QGLFramebufferObject(m_sMeterWidth, height); + //DISPLAYPANEL_DEBUG << "m_smeterFBO generated."; + } + + m_smeterFBO->bind(); + renderSMeterScale(); + //renderSMeterB(); + m_smeterFBO->release(); + + m_smeterUpdate = false; + m_smeterRenew = false; + } + + QRect rect = QRect(m_rxRect.right() + m_sMeterOffset, 0, m_sMeterWidth, height); + //renderTexture(rect, m_smeterFBO->texture(), -1.0f); + renderTexture(rect, m_smeterFBO->texture(), -2.0f); + + // set a scissor box + glScissor(x1, size().height() - y2, x2, height); + glEnable(GL_SCISSOR_TEST); + + if (m_dataEngineState == QSDR::DataEngineUp) { + + // S-Meter hold value + glLineWidth(1); + + int min = (int)(m_sMeterMinValueB * m_unit); + int max = (int)(m_sMeterMaxValueB * m_unit); + min += min%2; + max += max%2; + + QRect bar = QRect(x1 + min, m_sMeterPosY + 4, max - min, 5); + if (min > 0) + drawGLRect(bar, QColor(255, 50, 50), QColor(255, 255, 50), true); + + glDisable(GL_LINE_SMOOTH); + glDisable(GL_BLEND); + glDisable(GL_MULTISAMPLE); + + /*if (min > 0) { + + for (int i = min; i <= max; i += 2) { + + glBegin(GL_LINES); + glVertex3i(x1 + i, m_sMeterPosY + 3, 0.0); + glVertex3i(x1 + i, m_sMeterPosY + 10, 0.0); + glEnd(); + } + }*/ + + // S-Meter needle + glLineWidth(2); + qglColor(QColor(255, 255, 255)); + if (m_sMeterValue > 0) { + + glBegin(GL_LINES); + glVertex3f(x1 + (int)(m_sMeterValue * m_unit), m_sMeterPosY - 15, 1.0f); + glVertex3f(x1 + (int)(m_sMeterValue * m_unit), m_sMeterPosY + 28, 1.0f); + glEnd(); + } + + // actual S-Meter value + glEnable(GL_MULTISAMPLE); + qglColor(m_activeTextColor); + + QString str = "%1"; + m_sMeterNumValueString = QString(str.arg(m_sMeterOrgValue, 0, 'f', 1)); + //m_oglTextBig->renderText(x1 + m_sMeterWidth - 85, 80, 3.0, m_sMeterNumValueString); + //m_oglTextNormal->renderText(x1 + m_sMeterWidth - 28, 86, 3.0, "dBm"); + m_oglTextBig->renderText(x1 + m_sMeterWidth - 85, 2, 3.0, m_sMeterNumValueString); + m_oglTextNormal->renderText(x1 + m_sMeterWidth - 28, 9, 3.0, "dBm"); + + glEnable(GL_MULTISAMPLE); + } + + // disable scissor box + glDisable(GL_SCISSOR_TEST); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +void OGLDisplayPanel::renderSMeterA() { + + GLint width = m_smeterRect.width(); + GLint height = m_smeterRect.height(); + + GLint x1 = m_smeterRect.left(); + GLint y1 = m_smeterRect.top(); + GLint x2 = x1 + width; + GLint y2 = y1 + height; + + float X = (x2-x1)/2.0; + float Y = 370;//355.0; + + GLint mid = m_smeterRect.width()/2; + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) + //drawGLRect(QRect(0, 0, x2-x1, y2-y1), QColor(0, 0, 0, 255), QColor(0, 0, 90, 255), false); + drawGLRect(QRect(0, 0, x2-x1, y2-y1), Qt::black, m_bkgColor2, false); + //drawGLRect(QRect(0, 0, x2-x1, y2-y1), QColor(0, 0, 0, 255), QColor(15, 55, 75, 255), false); + else + drawGLRect(QRect(0, 0, x2-x1, y2-y1), Qt::black); + + glDisable(GL_MULTISAMPLE); + + //*********************************************************** + // center of S-Meter circles + + // circle 0, first half + float t = (float)(-156*ONEPI/256.0f); + float R0 = 320.0; + + if (m_dataEngineState == QSDR::DataEngineUp) + //qglColor(QColor(106, 136, 148)); + qglColor(QColor(180, 180, 180)); + else + qglColor(QColor(68, 68, 68)); + + glLineWidth(2); + glBegin(GL_LINE_STRIP); + for (int i = 0; i < m_smeterVertices; ++i) { + + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + t += TWOPI / m_smeterVertices; + if ( t > -128*ONEPI/256.0f) break; + } + glEnd(); + + // circle 0, second half + R0 = 321.0; + t = (float)(-126*ONEPI/256.0); + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(105, 110, 250)); + else + qglColor(QColor(68, 68, 68)); + + glLineWidth(3); + glBegin(GL_LINE_STRIP); + for (int i = 0; i < m_smeterVertices; ++i) { + + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + t += TWOPI / m_smeterVertices; + if ( t > -99*ONEPI/256.0f) break; + } + glEnd(); + + // circle 1 + if (m_dataEngineState == QSDR::DataEngineUp) + //qglColor(QColor(106, 136, 148)); + qglColor(QColor(180, 180, 180)); + else + qglColor(QColor(68, 68, 68)); + + glLineWidth(2); + float R1 = 312.0; + t = (float)(-156*ONEPI/256.0f); + glBegin(GL_LINE_STRIP); + for (int i = 0; i < m_smeterVertices; ++i) { + + glVertex3f(X + R1 * qCos(t), Y + R1 * qSin(t), 0.0); + t += TWOPI / m_smeterVertices; + if ( t > -99*ONEPI/256.0f) break; + } + glEnd(); + + + // circle 2 + /*if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(106, 136, 148)); + else + qglColor(QColor(68, 68, 68)); + + glLineWidth(2); + float R2 = 290.0; + t = -156*ONEPI/256.0f; + glBegin(GL_LINE_STRIP); + for (int i = 0; i < numVertices; ++i) { + + glVertex3f(X + R2 * qCos(t), Y + R2 * qSin(t), 0.0); + t += TWOPI / numVertices; + if ( t > -99*ONEPI/256.0f) break; + } + glEnd();*/ + + + // circle 3 + /*if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(106, 136, 148)); + else + qglColor(QColor(68, 68, 68)); + + glLineWidth(2); + float R3 = 270.0; + t = -156*ONEPI/256.0f; + glBegin(GL_LINE_STRIP); + for (int i = 0; i < numVertices; ++i) { + + glVertex3f(X + R3 * qCos(t), Y + R3 * qSin(t), 0.0); + t += TWOPI / numVertices; + if ( t > -99*ONEPI/256.0f) break; + } + glEnd();*/ + + + // S-Meter ticks + if (m_dataEngineState == QSDR::DataEngineUp) + //qglColor(QColor(106, 136, 148)); + qglColor(QColor(180, 180, 180)); + else + qglColor(QColor(68, 68, 68)); + + QFontMetrics fm = m_oglTextNormal->fontMetrics(); + + m_oglTextBigItalic->renderText(X - mid + 30, Y - R0, "S"); + + t = (float)(-152*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + int d = fm.width("1"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "1"); + + t = (float)(-149*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + t = (float)(-146*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + d = fm.width("3"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "3"); + + t = (float)(-143*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + t = (float)(-140*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + d = fm.width("5"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "5"); + + t = (float)(-137*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + t = (float)(-134*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + d = fm.width("7"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "7"); + + t = (float)(-131*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + t = (float)(-ONEPI/2.0f); + glBegin(GL_LINES); + glVertex3f(X + (R0-1) * qCos(t), Y + (R0-1) * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + d = fm.width("9"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "9"); + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(85, 90, 250)); + else + qglColor(QColor(68, 68, 68)); + + t = (float)(-123*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + t = (float)(-118*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + d = fm.width("+20"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "+20"); + + t = (float)(-113*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + t = (float)(-108*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+11) * qCos(t), Y + (R0+11) * qSin(t), 0.0); + glEnd(); + + d = fm.width("+40"); + m_oglTextNormal->renderText(X + (R0+28) * qCos(t) - d/2, Y + (R0+28) * qSin(t), "+40"); + + t = (float)(-103*ONEPI/256.0f); + glBegin(GL_LINES); + glVertex3f(X + R0 * qCos(t), Y + R0 * qSin(t), 0.0); + glVertex3f(X + (R0+7) * qCos(t), Y + (R0+7) * qSin(t), 0.0); + glEnd(); + + m_oglTextBigItalic->renderText(X + mid - 35, Y - R0, "dB"); + + glEnable(GL_MULTISAMPLE); +} + +void OGLDisplayPanel::renderSMeterScale() { + + GLint width = m_sMeterWidth; + GLint height = m_smeterRect.height(); + + GLint x1 = m_smeterRect.left(); + GLint y1 = m_smeterRect.top(); + GLint x2 = x1 + width; + GLint y2 = y1 + height; + + QFontMetrics fm = m_oglTextNormal->fontMetrics(); + + //int fontHeight = fm.tightBoundingRect("S9").height(); + //int fontMaxWidth = fm.boundingRect("-000").width(); + + qreal dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin); + m_unit = (qreal)(m_sMeterWidth / dBmRange); + + QRect rect = QRect(0, 0, x2-x1, y2-y1); + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) + drawGLRect(rect, Qt::black, m_bkgColor2, -3.0f, false); + else + drawGLRect(rect, Qt::black); + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + + // draw horizontal lines + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor); + + glBegin(GL_LINES); + glVertex3f(0, m_sMeterPosY, 0.0); + glVertex3f(width-1, m_sMeterPosY, 0.0); + glVertex3f(0, m_sMeterPosY + 12, 0.0); + glVertex3f(width-1, m_sMeterPosY + 12, 0.0); + glEnd(); + + // draw integer step scale + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(126, 156, 168)); + else + qglColor(m_inactiveTextColor); + + int vertexArrayLength = m_sMeterWidth; + vertexArrayLength += vertexArrayLength%2; + TGL3float *vertexArray = new TGL3float[2*vertexArrayLength]; + + for (int i = 0; i < vertexArrayLength; i++) { + + vertexArray[2*i].x = (GLfloat)(2.0f * i); + vertexArray[2*i].y = (GLfloat)(m_sMeterPosY + 4); + vertexArray[2*i].z = 0.0; + + vertexArray[2*i+1].x = (GLfloat)(2.0f * i); + vertexArray[2*i+1].y = (GLfloat)(m_sMeterPosY + 9); + vertexArray[2*i+1].z = 0.0; + } + + glEnableClientState(GL_VERTEX_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, width); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + + // Draw the dbm items + QString marker; + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor); + + for (int i = 1, z = -120; z < 10; i++, z += 10) { + + // big ticks + glBegin(GL_LINES); + glVertex3f(10*i*m_unit, m_sMeterPosY - 4, 0.0); + glVertex3f(10*i*m_unit, m_sMeterPosY, 0.0); + glEnd(); + + // small ticks + glBegin(GL_LINES); + glVertex3f((10*i - 5)*m_unit, m_sMeterPosY - 2, 0.0); + glVertex3f((10*i - 5)*m_unit, m_sMeterPosY, 0.0); + glEnd(); + + marker = QString::number(z, 'f', 0); + int d = fm.width(marker); + + if (z == -120 || z == -100 || z == -80 || z == -60 || z == -40 || z == -20) + m_oglTextNormal->renderText(10*i*m_unit-d/2-2, m_sMeterPosY - 18, marker); + + if (m_sMeterWidth > 500) { + + if (z == -110 || z == -90 || z == -70 || z == -50 || z == -30 || z == -10) + m_oglTextNormal->renderText(10*i*m_unit-d/2-2, m_sMeterPosY - 18, marker); + } + + if (m_sMeterWidth > 400) + if (z == 0) m_oglTextNormal->renderText(10*i*m_unit-d/2, m_sMeterPosY - 18, marker); + } + + m_oglTextSmallItalic->renderText(m_sMeterWidth - 25, m_sMeterPosY - 16, "dBm"); + + // Draw the S1..S9 value items + for (int i = 0; i < 17; i++) { + + if (i < 10) { + + glBegin(GL_LINES); + glVertex3f((6*i + 3)*m_unit, m_sMeterPosY + 12, 0.0f); + glVertex3f((6*i + 3)*m_unit, m_sMeterPosY + 17, 0.0f); + glEnd(); + + marker = "S1"; + int d = fm.width(marker); + + if (i == 1) { + + m_oglTextNormal->renderText((6*(i+1) - d/2 + 1)*m_unit, m_sMeterPosY + 18, marker); + } + else if (i == 3) { + + marker = "S3"; + m_oglTextNormal->renderText((6*(i+1) - d/2 + 1)*m_unit, m_sMeterPosY + 18, marker); + } + else if (i == 5) { + + marker = "S5"; + m_oglTextNormal->renderText((6*(i+1) - d/2 + 1)*m_unit, m_sMeterPosY + 18, marker); + } + else if (i == 7) { + + marker = "S7"; + m_oglTextNormal->renderText((6*(i+1) - d/2 + 1)*m_unit, m_sMeterPosY + 18, marker); + } + else if (i == 9) { + + marker = "S9"; + m_oglTextNormal->renderText((6*(i+1) - d/2 + 1)*m_unit, m_sMeterPosY + 18, marker); + } + } + else { + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(255, 80, 80)); + //qglColor(QColor(55, 180, 220)); + else + qglColor(m_inactiveTextColor); + + int idx = (10*i - 33)*m_unit; + glBegin(GL_LINES); + glVertex3f(idx, m_sMeterPosY + 12, 0.0); + glVertex3f(idx, m_sMeterPosY + 17, 0.0); + glEnd(); + + marker = "+20"; + int d = fm.width(marker); + + if (i == 11) { + m_oglTextNormal->renderText(idx - d/2 - 2, m_sMeterPosY + 18, marker); + } + else if (i == 13) { + + marker = "+40"; + m_oglTextNormal->renderText(idx - d/2 - 2, m_sMeterPosY + 18, marker); + } + else if (i == 15) { + + marker = "+60"; + m_oglTextNormal->renderText(idx - d/2 - 2, m_sMeterPosY + 18, marker); + } + /*else if (i == 17) { + + marker = "+80"; + m_oglTextNormal->renderText(idx - d/2 - 2, m_sMeterPosY + 18, marker); + }*/ + } + } + + glBegin(GL_LINES); + glVertex3f(57*m_unit+1, m_sMeterPosY+12, 0.0); + glVertex3f(width-1, m_sMeterPosY+12, 0.0); + glEnd(); + + /*if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor);*/ + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_MULTISAMPLE); +} + +void OGLDisplayPanel::renderSMeterB() { + + //GLint width = m_smeterRect.width(); + GLint width = m_sMeterWidth; + GLint height = m_smeterRect.height(); + + //GLint x1 = m_smeterRect.left(); + GLint x1 = m_smeterRect.left() + m_sMeterOffset; + GLint y1 = m_smeterRect.top(); + GLint x2 = x1 + width; + GLint y2 = y1 + height; + + QFontMetrics fm = m_oglTextNormal->fontMetrics(); + + int vertexArrayLength = width/2; + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) + drawGLRect(QRect(0, 0, x2-x1, y2-y1), Qt::black, m_bkgColor2, -3.0f, false); + else + drawGLRect(QRect(0, 0, x2-x1, y2-y1), Qt::black); + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + + // Draw horizontal lines + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor); + + glBegin(GL_LINES); + glVertex3f(0, m_sMeterPosY, 0.0); + glVertex3f(width-1, m_sMeterPosY, 0.0); + glVertex3f(0, m_sMeterPosY + 12, 0.0); + glVertex3f(width-1, m_sMeterPosY + 12, 0.0); + glEnd(); + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(100, 100, 100)); + else + qglColor(m_inactiveTextColor); + + TGL3float *vertexArray = new TGL3float[width]; + + for (int i = 0; i < vertexArrayLength; i++) { + + vertexArray[2*i].x = (GLfloat)(2.0f * i); + vertexArray[2*i].y = (GLfloat)(m_sMeterPosY + 3); + vertexArray[2*i].z = 0.0; + + vertexArray[2*i+1].x = (GLfloat)(2.0f * i); + vertexArray[2*i+1].y = (GLfloat)(m_sMeterPosY + 10); + vertexArray[2*i+1].z = 0.0; + } + + glEnableClientState(GL_VERTEX_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, width); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + + // Draw the S1..S9 value items + //int d; + //int markerSpacing = 24; // spacing for the S value items + //int markerSpacing = m_sMeterWidth/12.5f; // spacing for the S value items + float markerSpacing = qRound(m_sMeterWidth/12.5f); // spacing for the S value items + //DISPLAYPANEL_DEBUG << "S markerSpacing:" << markerSpacing; + + QString marker; + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor); + + //for (int x = 21, y = 9, z = 0; z < 5; x += markerSpacing, y += markerSpacing, z++) { + for (int x = markerSpacing - 3, y = x - markerSpacing/2, z = 0; z < 5; x += markerSpacing, y += markerSpacing, z++) { + + if (z == 0) marker = "S1"; + else if (z == 1) marker = "S3"; + else if (z == 2) marker = "S5"; + else if (z == 3) marker = "S7"; + else if (z == 4) marker = "S9"; + + // big ticks + glBegin(GL_LINES); + glVertex3f(x, m_sMeterPosY + 12, 0.0); + glVertex3f(x, m_sMeterPosY + 16, 0.0); + glEnd(); + + // small ticks + glBegin(GL_LINES); + glVertex3f(y, m_sMeterPosY + 12, 0.0); + glVertex3f(y, m_sMeterPosY + 15, 0.0); + glEnd(); + + // S strings + //d = fm.width(marker); + m_oglTextNormal->renderText(x-7, m_sMeterPosY + 18, marker); + } + + // Draw the S+ value items + //markerSpacing = 20; + markerSpacing = qRound(m_sMeterWidth/15.0f); + //DISPLAYPANEL_DEBUG << "S+ markerSpacing:" << markerSpacing; + + for (int x = 118 + markerSpacing, y = 128 + markerSpacing, z = 0; z < 8; x += markerSpacing, y += 2 * markerSpacing, z++) { + //for (int x = next + markerSpacing, y = next + markerSpacing/2, z = 0; z < 8; x += markerSpacing, y += 2 * markerSpacing, z++) { + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor); + + if (z == 0) marker = "+20"; + else if (z == 1) marker = "+40"; + else if (z == 2) marker = "+60"; + else if (z == 3) marker = "+80"; + + // big ticks + glBegin(GL_LINES); + glVertex3f(x, m_sMeterPosY + 12, 0.0); + glVertex3f(x, m_sMeterPosY + 16, 0.0); + glEnd(); + + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(QColor(255, 80, 80)); + else + qglColor(QColor(68, 68, 68)); + + m_oglTextNormal->renderText(y, m_sMeterPosY + 18, marker); + } + + // Draw the dbm items + if (m_dataEngineState == QSDR::DataEngineUp) + qglColor(m_activeTextColor); + else + qglColor(m_inactiveTextColor); + + //for (int x = 4, y = 14, z = -130; z < 10; x += markerSpacing, y += markerSpacing, z += 10) { + for (int x = markerSpacing - 16, y = x + markerSpacing/2, z = -130; z < 10; x += markerSpacing, y += markerSpacing, z += 10) { + + marker = QString::number(z, 'f', 0); + int d = fm.width(marker); + + // big ticks + glBegin(GL_LINES); + glVertex3f(x, m_sMeterPosY - 4, 0.0); + glVertex3f(x, m_sMeterPosY, 0.0); + glEnd(); + + // small ticks + glBegin(GL_LINES); + glVertex3f(y, m_sMeterPosY - 2, 0.0); + glVertex3f(y, m_sMeterPosY, 0.0); + glEnd(); + + if (z == -120 || z == -100 || z == -80 || z == -60 || z == -40 || z == -20) + m_oglTextNormal->renderText(x-d/2-2, m_sMeterPosY - 18, marker); + + if (z == 0) m_oglTextNormal->renderText(x-d/2-1, m_sMeterPosY - 18, marker); + } + + m_oglTextSmallItalic->renderText(width - 25, m_sMeterPosY - 16, "dBm"); + + glEnable(GL_LINE_SMOOTH); + glEnable(GL_MULTISAMPLE); +} + +//void OGLDisplayPanel::renderSMeterB() { +// +// //GLint width = m_smeterRect.width(); +// GLint width = m_sMeterWidth; +// GLint height = m_smeterRect.height(); +// +// GLint x1 = m_smeterRect.left(); +// GLint y1 = m_smeterRect.top(); +// GLint x2 = x1 + width; +// GLint y2 = y1 + height; +// +// QFontMetrics fm = m_oglTextNormal->fontMetrics(); +// +// int vertexArrayLength = width/2; +// +// // draw background +// if (m_dataEngineState == QSDR::DataEngineUp) +// drawGLRect(QRect(0, 0, x2-x1, y2-y1), Qt::black, m_bkgColor2, -3.0f, false); +// else +// drawGLRect(QRect(0, 0, x2-x1, y2-y1), Qt::black); +// +// glDisable(GL_MULTISAMPLE); +// glDisable(GL_LINE_SMOOTH); +// glLineWidth(1.0f); +// +// // Draw horizontal lines +// if (m_dataEngineState == QSDR::DataEngineUp) +// qglColor(m_activeTextColor); +// else +// qglColor(QColor(68, 68, 68)); +// +// glBegin(GL_LINES); +// glVertex3f(0, m_sMeterPosY, 0.0); +// glVertex3f(width-1, m_sMeterPosY, 0.0); +// glVertex3f(0, m_sMeterPosY + 12, 0.0); +// glVertex3f(width-1, m_sMeterPosY + 12, 0.0); +// glEnd(); +// +// if (m_dataEngineState == QSDR::DataEngineUp) +// qglColor(QColor(100, 100, 100)); +// else +// qglColor(QColor(68, 68, 68)); +// +// TGL3float *vertexArray = new TGL3float[width]; +// +// for (int i = 0; i < vertexArrayLength; i++) { +// +// vertexArray[2*i].x = (GLfloat)(2.0f * i); +// vertexArray[2*i].y = (GLfloat)(m_sMeterPosY + 3); +// vertexArray[2*i].z = 0.0; +// +// vertexArray[2*i+1].x = (GLfloat)(2.0f * i); +// vertexArray[2*i+1].y = (GLfloat)(m_sMeterPosY + 10); +// vertexArray[2*i+1].z = 0.0; +// } +// +// glEnableClientState(GL_VERTEX_ARRAY); +// +// glVertexPointer(3, GL_FLOAT, 0, vertexArray); +// glDrawArrays(GL_LINES, 0, width); +// glDisableClientState(GL_VERTEX_ARRAY); +// +// delete[] vertexArray; +// +// // Draw the S1..S9 value items +// int d; +// //int markerSpacing = 24; // spacing for the S value items +// int markerSpacing = m_sMeterWidth/12.5f; // spacing for the S value items +// QString marker; +// +// if (m_dataEngineState == QSDR::DataEngineUp) +// qglColor(m_activeTextColor); +// else +// qglColor(QColor(68, 68, 68)); +// +// for (int x = 21, y = 9, z = 0; z < 5; x += markerSpacing, y += markerSpacing, z++) { +// +// if (z == 0) marker = "S1"; +// else if (z == 1) marker = "S3"; +// else if (z == 2) marker = "S5"; +// else if (z == 3) marker = "S7"; +// else if (z == 4) marker = "S9"; +// +// // big ticks +// glBegin(GL_LINES); +// glVertex3f(x, m_sMeterPosY + 12, 0.0); +// glVertex3f(x, m_sMeterPosY + 16, 0.0); +// glEnd(); +// +// // small ticks +// glBegin(GL_LINES); +// glVertex3f(y, m_sMeterPosY + 12, 0.0); +// glVertex3f(y, m_sMeterPosY + 15, 0.0); +// glEnd(); +// +// // S strings +// //d = fm.width(marker); +// m_oglTextNormal->renderText(x-7, m_sMeterPosY + 18, marker); +// } +// +// // Draw the S+ value items +// //markerSpacing = 20; +// markerSpacing = m_sMeterWidth/15; +// +// for (int x = 118 + markerSpacing, y = 128 + markerSpacing, z = 0; z < 8; x += markerSpacing, y += 2 * markerSpacing, z++) { +// +// if (m_dataEngineState == QSDR::DataEngineUp) +// qglColor(m_activeTextColor); +// else +// qglColor(QColor(68, 68, 68)); +// +// if (z == 0) marker = "+20"; +// else if (z == 1) marker = "+40"; +// else if (z == 2) marker = "+60"; +// else if (z == 3) marker = "+80"; +// +// // big ticks +// glBegin(GL_LINES); +// glVertex3f(x, m_sMeterPosY + 12, 0.0); +// glVertex3f(x, m_sMeterPosY + 16, 0.0); +// glEnd(); +// +// // small ticks +// /*glBegin(GL_LINES); +// glVertex3f(y, 42, 0.0); +// glVertex3f(y, 45, 0.0); +// glEnd();*/ +// +// if (m_dataEngineState == QSDR::DataEngineUp) +// qglColor(QColor(255, 80, 80)); +// else +// qglColor(QColor(68, 68, 68)); +// +// m_oglTextNormal->renderText(y, m_sMeterPosY + 18, marker); +// } +// +// // Draw the dbm items +// for (int x = 4, y = 14, z = -130; z < 10; x += markerSpacing, y += markerSpacing, z += 10) { +// +// if (m_dataEngineState == QSDR::DataEngineUp) +// qglColor(m_activeTextColor); +// else +// qglColor(QColor(68, 68, 68)); +// +// marker = QString::number(z, 'f', 0); +// int d = fm.width(marker); +// +// // big ticks +// glBegin(GL_LINES); +// glVertex3f(x, m_sMeterPosY - 4, 0.0); +// glVertex3f(x, m_sMeterPosY, 0.0); +// glEnd(); +// +// // small ticks +// glBegin(GL_LINES); +// glVertex3f(y, m_sMeterPosY - 2, 0.0); +// glVertex3f(y, m_sMeterPosY, 0.0); +// glEnd(); +// +// if (z == -120 || z == -100 || z == -80 || z == -60 || z == -40 || z == -20) +// m_oglTextNormal->renderText(x-d/2-2, m_sMeterPosY - 18, marker); +// +// if (z == 0) m_oglTextNormal->renderText(x-d/2-1, m_sMeterPosY - 18, marker); +// } +// +// m_oglTextSmallItalic->renderText(width - 25, m_sMeterPosY - 16, "dBm"); +// +// glEnable(GL_MULTISAMPLE); +//} + +//*********************************************** +void OGLDisplayPanel::setSMeterValue(int rx, float value) { + + Q_UNUSED(rx) + + //qDebug() << "setSMeterValue = " << value; + if (m_SMeterA) { + +// float tmp = (0.444f * value - 111.111f) * ONEPI/256.0f; +// +// if (m_sMeterTimer.elapsed() > 40) { +// +// if (tmp < m_sMeterMinValueA) m_sMeterMinValueA = tmp; +// +// if (tmp > m_sMeterMaxValueA) m_sMeterMaxValueA = tmp; +// +// int elapsedTimeMax = m_sMeterMaxTimer.elapsed(); +// if (elapsedTimeMax > m_sMeterHoldTime) { +// +// if (m_sMeterPrevHoldTimeMax <= 0) +// m_sMeterPrevHoldTimeMax = 1500; +// +// m_sMeterMaxValueA -= (float)(elapsedTimeMax - m_sMeterPrevHoldTimeMax) / 40; +// m_sMeterPrevHoldTimeMax = elapsedTimeMax; +// +// if ((qRound(m_sMeterMaxValueA) <= qRound(tmp)) || (m_sMeterMaxValueA <= tmp)) { +// +// m_sMeterMaxValueA = tmp; +// m_sMeterMaxTimer.restart(); +// m_sMeterPrevHoldTimeMax = 0; +// } +// } +// +// if (m_sMeterMinTimer.elapsed() > m_sMeterHoldTime) { +// +// m_sMeterMinValueA = tmp; +// m_sMeterMinTimer.restart(); +// } +// +// m_sMeterValue = tmp * 0.13f + m_sMeterValue * 0.87f; +// +// QString str = "%1"; +// //m_sMeterNumValueString = QString(str.arg(value, 0, 'g', 3)); +// //qDebug() << "m_sMeterValue" << value; +// +// update(); +// m_sMeterTimer.restart(); +// } + } + else { + + //float tmp = (1.00423f * value + 93.3932f); + float tmp; + if (m_mercuryAttenuator) + //tmp = (1.67f * value + 156.237f); + tmp = (1.06962f * value + 99.1537f); + else + //tmp = (1.06962f * value + 99.1537f); + tmp = (1.67f * value + 156.237f); + + //qDebug() << "S-Meter tmp = " << tmp; + if (m_sMeterTimer.elapsed() > 40) { + + if (tmp < m_sMeterMinValueB) m_sMeterMinValueB = tmp; + + if (tmp > m_sMeterMaxValueB) m_sMeterMaxValueB = tmp; + + /*if (m_sMeterMaxTimer.elapsed() > m_sMeterHoldTime) { + + m_sMeterMaxValueB = tmp; + m_sMeterMaxTimer.restart(); + }*/ + + int elapsedTimeMax = m_sMeterMaxTimer.elapsed(); + if (elapsedTimeMax > m_sMeterHoldTime) { + + if (m_sMeterPrevHoldTimeMax <= 0) + m_sMeterPrevHoldTimeMax = m_sMeterHoldTime; + + // slowly reduce the peak hold level (taken from SDRMAX3 by (c) Cathy Moss) + m_sMeterMaxValueB -= (float)(elapsedTimeMax - m_sMeterPrevHoldTimeMax) / 15; + m_sMeterPrevHoldTimeMax = elapsedTimeMax; + + if ((qRound(m_sMeterMaxValueB) <= qRound(tmp)) || (m_sMeterMaxValueB <= tmp)) { + + m_sMeterMaxValueB = tmp; + m_sMeterMaxTimer.restart(); + m_sMeterPrevHoldTimeMax = 0; + } + } + + int elapsedTimeMin = m_sMeterMinTimer.elapsed(); + if (elapsedTimeMin > m_sMeterHoldTime) { + + if (m_sMeterPrevHoldTimeMin <= 0) + m_sMeterPrevHoldTimeMin = m_sMeterHoldTime; + + // slowly increase the minimum hold level (taken from SDRMAX3 by (c) Cathy Moss) + m_sMeterMinValueB += (float)(elapsedTimeMin - m_sMeterPrevHoldTimeMin) / 15; + m_sMeterPrevHoldTimeMin = elapsedTimeMin; + + if ((qRound(m_sMeterMinValueB) >= qRound(tmp)) || (m_sMeterMinValueB >= tmp)) { + + m_sMeterMinValueB = tmp; + m_sMeterMinTimer.restart(); + m_sMeterPrevHoldTimeMin = 0; + } + } + + /*if (m_sMeterMinTimer.elapsed() > m_sMeterHoldTime) { + + m_sMeterMinValueB = tmp; + m_sMeterMinTimer.restart(); + }*/ + + m_sMeterValue = tmp * 0.13f + m_sMeterValue * 0.87f; + //qDebug() << "scaled m_sMeterValue " << m_sMeterValue; + + if (m_sMeterDisplayTime.elapsed() > 200) { + + if (m_mercuryAttenuator) + //m_sMeterOrgValue = value - 17.7f; + m_sMeterOrgValue = value - 37.7f; + else + //m_sMeterOrgValue = value - 37.7f; + m_sMeterOrgValue = value - 17.7f; + + m_sMeterDisplayTime.restart(); + } + //m_sMeterOrgValue = value - 37.7f; + + /*m_sMeterMeanValue+= value; + m_sMeterMeanValueCnt++; + + if (m_sMeterMeanValueCnt > 100) { + + qDebug() << "m_sMeterMeanValue" << m_sMeterMeanValue/100; + m_sMeterMeanValue = 0.0f; + m_sMeterMeanValueCnt = 0; + }*/ + //qDebug() << " tmp" << tmp; + + update(); + m_sMeterTimer.restart(); + } + } +} + +void OGLDisplayPanel::setupDisplayRegions(QSize size) { + + int width = size.width(); + int height = size.height(); + + m_sMeterWidth = (int)(0.8f*(width - m_rxRectWidth)); + + if (m_sMeterWidth < 300) m_sMeterWidth = 300; + if (m_sMeterWidth > 600) m_sMeterWidth = 600; + + int d = 320 - m_sMeterWidth; + if (d > 0) + m_sMeterOffset = (int)(width - m_rxRectWidth - m_sMeterWidth)/2.0f; + else + m_sMeterOffset = width - m_rxRectWidth - m_sMeterWidth - 40; + + //m_sMeterOffset = 0; + + m_rect = QRect(0, 0, width, height); + m_rxRect = QRect(0, 0, m_rxRectWidth, height); + m_smeterRect = QRect(m_rxRect.right() + m_sMeterOffset, 0, width - m_rxRectWidth, height); + + //DISPLAYPANEL_DEBUG << "m_sMeterWidth:" << m_sMeterWidth; + //DISPLAYPANEL_DEBUG << " d:" << d; + //DISPLAYPANEL_DEBUG << "m_smeterRectWidth:" << m_smeterRect.width(); + //DISPLAYPANEL_DEBUG << "m_sMeterOffset:" << m_sMeterOffset; + + int x = m_rxRect.left() + 20; + int y = m_rxRect.top() + m_freqDigitsPosY + 10; + + m_freg10000000 = QRegion(QRect(x, y, m_blankWidthf1, m_fonts.fontHeightFreqFont1)); + + x += m_blankWidthf1; + m_freg1000000 = QRegion(QRect(x, y, m_blankWidthf1, m_fonts.fontHeightFreqFont1)); + + x += m_blankWidthf1; + m_freg100000 = QRegion(QRect(x, y, m_blankWidthf1, m_fonts.fontHeightFreqFont1)); + + x += m_blankWidthf1 + m_pointStringWidth; + m_freg10000 = QRegion(QRect(x, y, m_blankWidthf1, m_fonts.fontHeightFreqFont1)); + + x += m_blankWidthf1; + m_freg1000 = QRegion(QRect(x, y, m_blankWidthf1, m_fonts.fontHeightFreqFont1)); + + //x += m_blankWidthf1; + x = m_rxRect.left() + m_blankWidthf + 2*m_blankWidthf2; + m_freg100 = QRegion(QRect(x, y, m_blankWidthf2, m_fonts.fontHeightFreqFont2)); + + x += m_blankWidthf2; + m_freg10 = QRegion(QRect(x, y, m_blankWidthf2, m_fonts.fontHeightFreqFont2)); + + x += m_blankWidthf2; + m_freg1 = QRegion(QRect(x, y, m_blankWidthf2, m_fonts.fontHeightFreqFont2)); + + m_smeterRenew = true; +} + +void OGLDisplayPanel::getSelectedDigit(QPoint p) { + + if (m_freg1.contains(p)) + m_digitPosition = Freq1; + else + if (m_freg10.contains(p)) + m_digitPosition = Freq10; + else + if (m_freg100.contains(p)) + m_digitPosition = Freq100; + else + if (m_freg1000.contains(p)) + m_digitPosition = Freq1000; + else + if (m_freg10000.contains(p)) + m_digitPosition = Freq10000; + else + if (m_freg100000.contains(p)) + m_digitPosition = Freq100000; + else + if (m_freg1000000.contains(p)) + m_digitPosition = Freq1000000; + else + if (m_freg10000000.contains(p)) + m_digitPosition = Freq10000000; + else + m_digitPosition = None; +} + +//*********************************************** +void OGLDisplayPanel::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::mousePressEvent(QMouseEvent *event) { + + QPoint pos = event->pos(); + + //if (m_serverMode != QSDR::ExternalDSP) { + + getSelectedDigit(pos); + switch (m_digitPosition) { + + case Freq1: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 1.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 5.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 1.0); + } + break; + + case Freq10: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 10.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 50.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 10.0); + } + break; + + case Freq100: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 100.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 500.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 100.0); + } + break; + + case Freq1000: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 1000.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 5000.0); + else if (set->getMouseWheelFreqStep(m_currentReceiver) == 5000.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 9000.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 1000.0); + } + break; + + case Freq10000: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 10000.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 50000.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 10000.0); + } + break; + + case Freq100000: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 100000.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 500000.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 100000.0); + } + break; + + case Freq1000000: + if (event->buttons() == Qt::LeftButton) { + if (set->getMouseWheelFreqStep(m_currentReceiver) == 1000000.0) + set->setMouseWheelFreqStep(this, m_currentReceiver, 5000000.0); + else + set->setMouseWheelFreqStep(this, m_currentReceiver, 1000000.0); + } + break; + + case Freq10000000: + case None: + return; + } + + //} + + QWidget::mousePressEvent(event); +} + +void OGLDisplayPanel::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::mouseMoveEvent(QMouseEvent *event) { + + QPoint pos = event->pos(); + + QColor oldDigitColor = m_digitColor; + + //if (m_serverMode != QSDR::ExternalDSP) { + + getSelectedDigit(pos); + switch (m_digitPosition) { + + case Freq1: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq10: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq100: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq1000: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq10000: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq100000: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq1000000: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case Freq10000000: + setCursor(Qt::PointingHandCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(136, 166, 178); + else + m_digitColor = QColor(98, 98, 98); + break; + + case None: + setCursor(Qt::ArrowCursor); + if (m_dataEngineState == QSDR::DataEngineUp) + m_digitColor = QColor(106, 136, 148); + else + m_digitColor = QColor(68, 68, 68); + + break; + } + //} + + if (oldDigitColor != m_digitColor) update(); + + QGLWidget::mouseMoveEvent(event); +} + +void OGLDisplayPanel::wheelEvent(QWheelEvent * event) { + + //if (m_serverMode != QSDR::ExternalDSP) { + + long deltaF = 0; + switch (m_digitPosition) { + + case Freq1: + deltaF = 1; + break; + + case Freq10: + deltaF = 10; + break; + + case Freq100: + deltaF = 100; + break; + + case Freq1000: + deltaF = 1000; + break; + + case Freq10000: + deltaF = 10000; + break; + + case Freq100000: + deltaF = 100000; + break; + + case Freq1000000: + deltaF = 1000000; + break; + + case Freq10000000: + deltaF = 10000000; + break; + + case None: + return; + } + + int numDegrees = event->delta() / 8; + int numSteps = numDegrees / 15; + + int f1 = m_frequencyList[m_currentReceiver].freqMHz; + int f2 = m_frequencyList[m_currentReceiver].freqkHz; + + long newFreq = -1; + if (deltaF > 0) + //newFreq = frequency1 * 1000 + frequency2 + numSteps * deltaF; + newFreq = f1 * 1000 + f2 + numSteps * deltaF; + + if (newFreq < MAXFREQUENCY && newFreq >= 0) { + + if (set->getPanLockedStatus(m_currentReceiver)) { + + long ctrf = set->getCtrFrequency(m_currentReceiver); + int s = set->getSampleRate()/2; + if (newFreq > ctrf + s) + newFreq = ctrf + s; + else if (newFreq < ctrf - s) + newFreq = ctrf - s; + + set->setVFOFrequency(this, 0, m_currentReceiver, newFreq); + } + else + set->setVFOFrequency(this, 1, m_currentReceiver, newFreq); + } + + //qDebug() << "set frequency for rx" << m_currentReceiver; + + //} + event->accept(); + QGLWidget::wheelEvent(event); +} + +void OGLDisplayPanel::keyPressEvent(QKeyEvent* event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::closeEvent(QCloseEvent *event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::showEvent(QShowEvent *event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::timerEvent(QTimerEvent *event) { + + Q_UNUSED(event) +} + +void OGLDisplayPanel::setSMeterHoldTime(int value) { + + m_sMeterHoldTime = value; +} + +void OGLDisplayPanel::setSyncStatus(int value) { + + m_syncStatus = value; + update(); + + //QTimer::singleShot(50, this, SLOT(updateSyncStatus())); +} + +void OGLDisplayPanel::updateSyncStatus() { + + if (m_dataEngineState == QSDR::DataEngineUp) + m_syncStatus = 1; + else + m_syncStatus = 0; + + update(); +} + +void OGLDisplayPanel::setADCStatus(int value) { + + m_adcStatus = value; + update(); + + QTimer::singleShot(500, this, SLOT(updateADCStatus())); +} + +void OGLDisplayPanel::updateADCStatus() { + + if (m_dataEngineState == QSDR::DataEngineUp) + m_adcStatus = 1; + else + m_adcStatus = 0; + + update(); +} + +void OGLDisplayPanel::setPacketLossStatus(int value) { + + m_packetLossStatus = value; + update(); + + QTimer::singleShot(100, this, SLOT(updatePacketLossStatus())); +} + +void OGLDisplayPanel::updatePacketLossStatus() { + + if (m_dataEngineState == QSDR::DataEngineUp) + m_packetLossStatus = 1; + else + m_packetLossStatus = 0; + + update(); +} + +void OGLDisplayPanel::setSendIQStatus(int value) { + + m_sendIQStatus = value; + update(); +} + +void OGLDisplayPanel::setRecvAudioStatus(int value) { + + m_recvAudioStatus = value; + update(); +} + +void OGLDisplayPanel::setReceivers(QObject *sender, int value) { + + Q_UNUSED (sender) + + m_receivers = value; + update(); +} + +void OGLDisplayPanel::setSampleRate(QObject *sender, int value) { + + Q_UNUSED (sender) + + m_sample_rate = value / 1000; + update(); +} + +void OGLDisplayPanel::setMercuryAttenuator(QObject *sender, HamBand band, int value) { + + Q_UNUSED (sender) + Q_UNUSED (band) + + m_mercuryAttenuator = value; + update(); +} + +void OGLDisplayPanel::setDither(QObject *sender, int value) { + + Q_UNUSED (sender) + + m_dither = value; + update(); +} + +void OGLDisplayPanel::setRandom(QObject *sender, int value) { + + Q_UNUSED (sender) + + m_random = value; + update(); +} + +void OGLDisplayPanel::setCurrentReceiver(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_currentReceiver = value; + update(); +} + +void OGLDisplayPanel::setFrequency(QObject *sender, int mode, int rx, long freq) { + + Q_UNUSED (sender) + Q_UNUSED (mode) + //Q_UNUSED (rx) + + //m_oldFreq = freq; + + TFrequency f; + f.frequency = freq; + f.freqMHz = (int)(freq / 1000); + f.freqkHz = (int)(freq % 1000); + + //frequency1 = (int)(freq / 1000); + //frequency2 = (int)(freq % 1000); + + /*if (m_frequencyList.count() < set->getCurrentReceivers()) { + + m_frequencyList << f; + } + else*/ + m_frequencyList[rx] = f; + + update(); +} + +void OGLDisplayPanel::set10mhzSource(QObject *sender, int value) { + + Q_UNUSED (sender) + + switch (value) { + case 0: + m_src10mhz = "Atlas"; + break; + case 1: + m_src10mhz = "Penelope"; + break; + case 2: + m_src10mhz = "Mercury"; + break; + } + update(); +} + +void OGLDisplayPanel::set122_88mhzSource(QObject *sender, int value) { + + Q_UNUSED (sender) + + switch (value) { + case 0: + m_src122_88mhz = "Penelope"; + break; + case 1: + m_src122_88mhz = "Mercury"; + break; + } + update(); +} + +void OGLDisplayPanel::setMercuryPresence(bool value) { + + m_mercury = value; + update(); +} + +void OGLDisplayPanel::setPenelopePresence(bool value) { + + m_penelope = value; + update(); +} + +void OGLDisplayPanel::setPennylanePresence(bool value) { + + m_pennylane = value; + update(); +} + +void OGLDisplayPanel::setAlexPresence(bool value) { + + m_alex = value; + update(); +} + +void OGLDisplayPanel::setExcaliburPresence(bool value) { + + m_excalibur = value; + update(); +} + +void OGLDisplayPanel::setMercuryVersion(int value) { + + m_mercuryVersion.setNum(value/10); + m_mercuryVersion.append("."); + QString str; + m_mercuryVersion.append(str.setNum(value%10)); +} + +void OGLDisplayPanel::setPenelopeVersion(int value) { + + m_penelopeVersion.setNum(value/10); + m_penelopeVersion.append("."); + QString str; + m_penelopeVersion.append(str.setNum(value%10)); +} + +void OGLDisplayPanel::setPennylaneVersion(int value) { + + m_pennylaneVersion.setNum(value/10); + m_pennylaneVersion.append("."); + QString str; + m_pennylaneVersion.append(str.setNum(value%10)); +} + +void OGLDisplayPanel::setHermesVersion(int value) { + + m_hermesVersion.setNum(value/10); + m_hermesVersion.append("."); + QString str; + m_hermesVersion.append(str.setNum(value%10)); +} + +void OGLDisplayPanel::setMetisVersion(int value) { + + QString str; + switch (m_hwInterface) { + + case QSDR::Metis: + + m_metisVersion.setNum(value/10); + m_metisVersion.append("."); + m_metisVersion.append(str.setNum(value%10)); + break; + + case QSDR::Hermes: + case QSDR::NoInterfaceMode: + + break; + } + +} + +void OGLDisplayPanel::setExcaliburVersion(QObject *sender, int value) { + + Q_UNUSED (sender) + + m_excaliburVersion.setNum(value/10); + m_excaliburVersion.append("."); + QString str; + m_excaliburVersion.append(str.setNum(value%10)); +} + +void OGLDisplayPanel::setAlexVersion(QObject *sender, int value) { + + Q_UNUSED (sender) + + m_alexVersion.setNum(value/10); + m_alexVersion.append("."); + QString str; + m_alexVersion.append(str.setNum(value%10)); +} + +void OGLDisplayPanel::setMouseWheelFreqStep(QObject *sender, int rx, qreal value) { + + Q_UNUSED (sender) + + if (rx == m_currentReceiver) + m_mouseWheelFreqStep = value; + + update(); +} + +void OGLDisplayPanel::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + //m_mutex.lock(); + if (m_serverMode != mode) { + + m_serverMode = mode; + + } + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_dataEngineState != state) + m_dataEngineState = state; + + if (state == QSDR::DataEngineDown) { + + m_sMeterMaxValueB = -1000.0f; + m_sMeterMinValueB = 1000.0f; + + m_sMeterTimer.restart(); + m_sMeterDisplayTime.restart(); + m_sMeterMaxTimer.restart(); + m_sMeterMinTimer.restart(); + + QTimer::singleShot(50, this, SLOT(updateADCStatus())); + QTimer::singleShot(50, this, SLOT(updateSyncStatus())); + QTimer::singleShot(50, this, SLOT(updatePacketLossStatus())); + + //resizeGL(width(), height()); + } +// else if (state == QSDR::DataEngineUp) { +// +// resizeGL(width(), height()); +// } + + m_smeterUpdate = true; + m_smeterRenew = true; + + update(); + //paintGL(); +} diff --git a/Source/src/GL/cusdr_oglDisplayPanel.h b/Source/src/GL/cusdr_oglDisplayPanel.h new file mode 100644 index 0000000..f50d6e0 --- /dev/null +++ b/Source/src/GL/cusdr_oglDisplayPanel.h @@ -0,0 +1,345 @@ +/** +* @file cusdr_oglDisplayPanel.h +* @brief display panel header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-22 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_QGL_DISPLAYPANEL_H +#define _CUSDR_QGL_DISPLAYPANEL_H + +#include "cusdr_oglUtils.h" +#include "cusdr_oglInfo.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" +#include "cusdr_oglText.h" + +//#include +//#include +//#include +#include +//#include +//#include +//#include +//#include + +#ifdef LOG_DISPLAYPANEL +# define DISPLAYPANEL_DEBUG qDebug().nospace() << "DisplayPanel::\t" +#else +# define DISPLAYPANEL_DEBUG nullDebug() +#endif + + +class OGLDisplayPanel : public QGLWidget { + + Q_OBJECT + +public: + OGLDisplayPanel(QWidget *parent = 0); + ~OGLDisplayPanel(); + +public slots: + QSize minimumSizeHint() const; + QSize sizeHint() const; + + void setSampleRate(QObject *sender, int value); + void setFrequency(QObject *sender, int mode, int rx, long freq); + +protected: + void initializeGL(); + void resizeGL(int iWidth, int iHeight); + void paintGL(); + + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event ); + void keyPressEvent(QKeyEvent* event); + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void timerEvent(QTimerEvent *); + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QGLFramebufferObject *m_smeterFBO; + + QList m_frequencyList; + + TPanadapterColors m_colors; + TScale m_dBmScale; + + CFonts *fonts; + TFonts m_fonts; + + QMutex m_mutex; + + OGLText *m_oglTextTiny; + OGLText *m_oglTextSmall; + OGLText *m_oglTextSmallItalic; + OGLText *m_oglTextNormal; + OGLText *m_oglTextBig; + OGLText *m_oglTextBigItalic; + OGLText *m_oglTextFreq1; + OGLText *m_oglTextFreq2; + OGLText *m_oglTextImpact; + + QRect m_rect; + QRect m_rxRect; + QRect m_smeterRect; + + QString m_src10mhz; + QString m_src122_88mhz; + QString m_mercuryVersion; + QString m_penelopeVersion; + QString m_pennylaneVersion; + QString m_hermesVersion; + QString m_excaliburVersion; + QString m_metisVersion; + QString m_alexVersion; + QString m_mercuryString; + QString m_penelopeString; + QString m_pennylaneString; + QString m_excaliburString; + QString m_metisString; + QString m_alexString; + QString m_hermesString; + QString m_hermesStepAttnString; + + QString m_SYNCString; + QString m_ADCString; + QString m_PacketLossString; + QString m_sendIQString; + QString m_recvAudioString; + QString m_AttnString; + QString m_ditherString; + QString m_randomString; + QString m_sampleRateString; + QString m_modusString; + QString m_10MHzString; + QString m_12288MHzString; + QString m_sMeterNumValueString; + + QString m_bandText; + + QRegion m_freg1; + QRegion m_freg10; + QRegion m_freg100; + QRegion m_freg1000; + QRegion m_freg10000; + QRegion m_freg100000; + QRegion m_freg1000000; + QRegion m_freg10000000; + + QColor m_digitColor; + QColor m_bkgColor1; + QColor m_bkgColor2; + QColor m_activeTextColor; + QColor m_inactiveTextColor; + QColor m_textBackgroundColor; + + QTime m_sMeterTimer; + QTime m_sMeterMaxTimer; + QTime m_sMeterMinTimer; + QTime m_sMeterDisplayTime; + + enum Region { + + upperRegion, + lowerRegion, + rxRegion, + smeterRegion, + hpsdrRegion, + elsewhere, + out + }; + + enum FreqDigit { + + Freq1, + Freq10, + Freq100, + Freq1000, + Freq10000, + Freq100000, + Freq1000000, + Freq10000000, + None + }; + + GLuint m_sMeterTex; + + bool m_mercury; + bool m_penelope; + bool m_pennylane; + bool m_excalibur; + bool m_metis; + bool m_alex; + bool m_smeterUpdate; + bool m_smeterRenew; + bool m_SMeterA; + bool m_sMeterAvg; + + long m_oldFreq; + + int m_height; + int m_sMeterWidth; + int m_sMeterOffset; + int m_rxRectWidth; + int m_lowerRectY; + int m_upperRectY; + int m_digitPosition; + int m_syncStatus; + int m_adcStatus; + int m_packetLossStatus; + int m_sendIQStatus; + int m_recvAudioStatus; + int m_receivers; + int m_sample_rate; + int m_mercuryAttenuator; + int m_dither; + int m_random; + int m_currentReceiver; + + int m_pointStringWidth; + int m_blankWidth; + int m_blankWidthf; + int m_blankWidthf1; + int m_blankWidthf2; + int m_fUnitStringWidth; + int m_blankHeight; + int m_freqStringLeftPos; + int m_versionStringWidth; + int m_syncWidth; + int m_adcWidth; + int m_packetLossWidth; + int m_sendIQWidth; + int m_recvAudioWidth; + int m_metisStringWidth; + int m_mercuryStringWidth; + int m_penelopeStringWidth; + int m_pennylaneStringWidth; + int m_hermesStringWidth; + int m_hermesStepAttnStringWidth; + int m_alexStringWidth; + int m_excaliburStringWidth; + int m_AttnWidth; + int m_ditherWidth; + int m_randomWidth; + int m_sampleRateWidth; + int m_modusWidth; + int m_10MHzWidth; + int m_sMeterDeform; + int m_12288MHzWidth; + int m_freqDigitsPosY; + int m_sMeterPosY; + int m_sMeterHoldTime; + int m_sMeterPrevHoldTimeMax; + int m_sMeterPrevHoldTimeMin; + int m_sMeterMeanValueCnt; + + qreal m_mouseWheelFreqStep; + qreal m_dBmPanMin; + qreal m_dBmPanMax; + qreal m_unit; + + float m_smeterVertices; + float m_sMeterValue; + float m_sMeterMeanValue; + float m_sMeterOrgValue; + float m_sMeterMaxValueA; + float m_sMeterMinValueA; + float m_sMeterMaxValueB; + float m_sMeterMinValueB; + + //************************* + void setupConnections(); + void setupTextstrings(); + void paintUpperRegion(); + void paintLowerRegion(); + void paintRxRegion(); + + void paintSMeter(); + void renderSMeterScale(); + void renderSMeterA(); + void renderSMeterB(); + + void getSelectedDigit(QPoint p); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setupDisplayRegions(QSize size); + + void setSyncStatus(int value); + void setADCStatus(int value); + void setPacketLossStatus(int value); + void setSendIQStatus(int value); + void setRecvAudioStatus(int value); + void setCurrentReceiver(QObject *sender, int value); + void setMercuryAttenuator(QObject* sender, HamBand band, int value); + void setReceivers(QObject *sender, int value); + void setDither(QObject *sender, int value); + void setRandom(QObject *sender, int value); + void set10mhzSource(QObject *sender, int value); + void set122_88mhzSource(QObject *sender, int value); + + void setMercuryPresence(bool value); + void setPenelopePresence(bool value); + void setPennylanePresence(bool value); + void setAlexPresence(bool value); + void setExcaliburPresence(bool value); + void setHermesVersion(int value); + void setMercuryVersion(int value); + void setPenelopeVersion(int value); + void setPennylaneVersion(int value); + void setMetisVersion(int value); + void setExcaliburVersion(QObject *sender, int value); + void setAlexVersion(QObject *sender, int value); + + void setMouseWheelFreqStep(QObject *sender, int rx, qreal value); + + void setSMeterValue(int rx, float value); + void setSMeterHoldTime(int value); + void updateSyncStatus(); + void updateADCStatus(); + void updatePacketLossStatus(); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString msg); +}; + + +#endif // _CUSDR_QGL_DISPLAYPANEL_H diff --git a/Source/src/GL/cusdr_oglDistancePanel.cpp b/Source/src/GL/cusdr_oglDistancePanel.cpp new file mode 100644 index 0000000..7503389 --- /dev/null +++ b/Source/src/GL/cusdr_oglDistancePanel.cpp @@ -0,0 +1,2760 @@ +/** +* @file cusdr_oglDistancePanel.cpp +* @brief distance panel class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-14 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_GRAPHICS + +#include "cusdr_oglDistancePanel.h" + +//#include +//#include +////#include +//#include +//#include +//#include +//#include + + +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809D +#endif + +QGLDistancePanel::QGLDistancePanel(QWidget *parent) + : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent) + + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_panMode(set->getPanadapterMode(0)) + , m_mousePos(QPoint(-1, -1)) + , m_mouseDownPos(QPoint(-1, -1)) + , m_specAveragingCnt(set->getSpectrumAveragingCnt(0)) + , m_freqRulerDisplayWidth(0) + , m_panSpectrumMinimumHeight(70) + , m_spectrumUpdate(false) + , m_showZerodBmLine(false) + , m_spectrumVertexColorUpdate(false) + , m_spectrumColorsChanged(true) + , m_showChirpFFT(false) + , m_spectrumAveraging(set->getSpectrumAveraging(0)) + , m_spectrumAveragingOld(m_spectrumAveraging) + , m_crossHairCursor(false) + , m_panGrid(set->getPanGridStatus(0)) + , m_freqRulerPosition(0.5) + , m_distRulerDisplayDelta(0.0) + , m_distRulerDisplayDeltaStep(500.0) + , m_distRulerMaxDist(150000.0) + , m_freqScaleZoomFactor(1.0f) + , m_distScaleZoomFactor(1.0) // 0.2 .. 1.0 + , m_scaleMult(1.0f) + , m_filterLowerFrequency(-3050.0) + , m_filterUpperFrequency(-150.0) + , m_snapMouse(3) + , m_sampleRate(set->getSampleRate()) + , m_downRate(set->getChirpDownSampleRate()) + , m_chirpBufferLength(set->getChirpBufferLength()) +{ +// QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + + setAutoBufferSwap(true); + setAutoFillBackground(false); + + setMouseTracking(true); + setFocusPolicy(Qt::StrongFocus); + + setupDisplayRegions(size()); + m_oldWidth = size().width(); + + m_rxDataList = set->getReceiverDataList(); + //m_frequency = m_rxDataList.at(0).frequency; + m_frequency = m_rxDataList.at(0).vfoFrequency; + + m_dBmScalePanadapterRenew = true; + m_dBmScalePanadapterUpdate = true; + m_freqScalePanadapterRenew = true; + m_freqScalePanadapterUpdate = true; + m_panGridRenew = true; + m_panGridUpdate = true; + + HamBand band = m_rxDataList.at(0).hamBand; + + m_dBmPanMin = m_rxDataList.at(0).dBmPanScaleMinList.at(band); + m_dBmPanMax = m_rxDataList.at(0).dBmPanScaleMaxList.at(band); + + m_filterLowerFrequency = m_rxDataList.at(0).filterLo; + m_filterUpperFrequency = m_rxDataList.at(0).filterHi; + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_oglTextTiny = new OGLText(m_fonts.tinyFont); + m_oglTextSmall = new OGLText(m_fonts.smallFont); + m_oglTextNormal = new OGLText(m_fonts.normalFont); + + timer = 0; + + setupConnections(); + + m_displayTime.start(); + m_resizeTime.start(); + //freqChangeTimer.start(); + + memset(m_spectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float)); + memset(m_distanceSpectrumBuffer, -10000, 16 * BUFFER_SIZE * sizeof(float)); + + m_kilometersPerGate = 0.5f * 3E5 / (m_sampleRate/m_downRate); + + m_dBmPanLogGain = 69; // allow user to calibrate this value + + m_dBmDistMin = set->getdBmDistScaleMin(); + m_dBmDistMax = set->getdBmDistScaleMax(); + m_dBmDistScaleMin = m_dBmDistMin; + m_dBmDistScaleMax = m_dBmDistMax; + + m_panSpectrumBinsLength = 0; + + /*m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0);*/ + + m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0); + m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0); + m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0); + + m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + m_frequencyScaleFBO = 0; + m_dBmScaleFBO = 0; + m_panadapterGridFBO = 0; + m_textureFBO = 0; + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + + memset(m_tmpBuf, 0, SAMPLE_BUFFER_SIZE * sizeof(float)); + + updateGL(); +} + +QGLDistancePanel::~QGLDistancePanel() { + + disconnect(set, 0, this, 0); + + makeCurrent(); + glFinish(); + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + if (m_textureFBO) { + + delete m_textureFBO; + m_textureFBO = 0; + } + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + + if (m_panadapterGridFBO) { + + delete m_panadapterGridFBO; + m_panadapterGridFBO = 0; + } + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); +} + +//QSize QGLDistancePanel::minimumSizeHint() const { +// +// //return QSize(1000, 1024); +// return QSize(width(), height()); +//} + +QSize QGLDistancePanel::sizeHint() const { + + return QSize(width(), height()); +} + +void QGLDistancePanel::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + + CHECKED_CONNECT( + set, + SIGNAL(freqRulerPositionChanged(float, int)), + this, + SLOT(freqRulerPositionChanged(float, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)), + this, + SLOT(setFilterFrequencies(QObject *, int, qreal, qreal))); + + CHECKED_CONNECT_OPT( + set, + SIGNAL(chirpSpectrumBufferChanged(int, qint64, const float *)), + this, + SLOT(distanceSpectrumBufferChanged(int, qint64, const float *)), + Qt::DirectConnection); + + CHECKED_CONNECT( + set, + SIGNAL(chirpFFTShowChanged(bool)), + this, + SLOT(setChirpFFTShow(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallTimeChanged(int, int)), + this, + SLOT(setWaterfallTime(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallOffesetLoChanged(int, int)), + this, + SLOT(setWaterfallOffesetLo(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallOffesetHiChanged(int, int)), + this, + SLOT(setWaterfallOffesetHi(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingChanged(bool)), + this, + SLOT(setSpectrumAveraging(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingCntChanged(int)), + this, + SLOT(setSpectrumAveragingCnt(int))); + + CHECKED_CONNECT( + set, + SIGNAL(panGridStatusChanged(bool)), + this, + SLOT(setPanGridStatus(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(panadapterColorChanged()), + this, + SLOT(setPanadapterColors())); +} + +void QGLDistancePanel::initializeGL() { + + if (!isValid()) return; + + /*QOpenGLInfo glInfo; + glInfo.getInfo(); + glInfo.printSelf();*/ + + //***************************************************************** + // default initialization + + //glShadeModel(GL_FLAT); + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.5f); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + //glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + m_cnt = 0; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +void QGLDistancePanel::paintGL() { + + switch (m_serverMode) { + + case QSDR::SDRMode: + + drawGLRect(QRect(0, 0, width(), height()), QColor(0, 0, 0)); + break; + + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + + //if (freqChangeTimer.elapsed() > 50) m_spectrumAveraging = m_spectrumAveragingOld; + + if (m_resizeTime.elapsed() > 100 || m_dataEngineState == QSDR::DataEngineDown) { + + paintReceiverDisplay(); + paintChirpWSPRDisplay(); + } + + break; + + default: + break; + } +} + +//**************************************************** +// painting modes +void QGLDistancePanel::paintReceiverDisplay() { + + QRect mouse_rect(0, 0, 100, 100); + mouse_rect.moveCenter(m_mousePos); + + drawPanadapter(); + drawPanHorizontalScale(); + drawPanVerticalScale(); + + if (m_panGrid) + drawPanadapterGrid(); + + drawPanFilter(); + + if (m_mouseRegion == panadapterRegion && m_crossHairCursor) + drawCrossHair(); + + m_oldFreq = m_frequency; + } + +void QGLDistancePanel::paintChirpWSPRDisplay() { + + //drawGLBackground(m_distanceSpectrumRect); + + distanceSpectrumBufferMutex.lock(); + drawDistanceSpectrum(); + distanceSpectrumBufferMutex.unlock(); + + drawDistHorizontalScale(); + drawDistVerticalScale(); + + //// chirp distance spectrum + //m_distancePanadapter->drawGLDistanceRuler( + // m_freqScaleDistancePanRect, + // m_freqScalePanadapterRect, + // m_mouseRegion, + // m_distRulerZoomFactor, + // m_distRulerDisplayDelta, + // m_kilometersPerGate, + // m_showChirpFFT, + // m_chirpBufferLength); + + //m_distancePanadapter->drawGLdBmScale( + // m_dBmScaleDistancePanRect, + // m_distanceSpectrumRect, + // m_mouseRegion, + // m_dBmDistScaleMin, + // m_dBmDistScaleMax, + // m_showZerodBmLine); + + //m_distancePanadapter->drawGLGrid(m_distanceSpectrumRect, m_dBmScaleDistancePanRect); +} + +void QGLDistancePanel::drawPanadapter() { + + GLint vertexArrayLength = (GLint)m_panadapterBins.size(); + + GLint height = m_panRect.height(); + GLint x1 = m_panRect.left(); + GLint y1 = m_panRect.top(); + GLint x2 = x1 + m_panRect.width(); + GLint y2 = y1 + m_panRect.height(); + + // y scale + float yScale; + float yScaleColor; + float yTop; + + qreal dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin); + + yScale = m_panRect.height() / dBmRange; + //yScaleColor = 4.0f / dBmRange; + yScaleColor = 10.0f / dBmRange; + yTop = (float) y2; + + if (m_dataEngineState == QSDR::DataEngineUp) + glClear(GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_MULTISAMPLE); + glEnable(GL_LINE_SMOOTH); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glLineWidth(1); + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_panGrid) { + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.15f, 0.15f, 0.3f); glVertex3f(x1, y1, -3.0); // top left corner + glColor3f(0.15f, 0.15f, 0.3f); glVertex3f(x2, y1, -3.0); // top right corner + glColor3f(0.15f, 0.15f, 0.51f); glVertex3f(x1, y2, -3.0); // bottom left corner + glColor3f(0.15f, 0.15f, 0.61f); glVertex3f(x2, y2, -3.0); // bottom right corner + glEnd(); + } + else { + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.05f, 0.05f, 0.2f); glVertex3f(x1, y1, -3.0); // top left corner + glColor3f(0.05f, 0.05f, 0.2f); glVertex3f(x2, y1, -3.0); // top right corner + glColor3f(0.05f, 0.05f, 0.31f); glVertex3f(x1, y2, -3.0); // bottom left corner + glColor3f(0.05f, 0.05f, 0.41f); glVertex3f(x2, y2, -3.0); // bottom right corner + glEnd(); + } + } + else { + + drawGLRect(m_panRect, QColor(30, 30, 50, 155), -3.0f); + } + + //glBegin(GL_TRIANGLE_STRIP); + //glColor3f(m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x1, y1, -3.0); // top left corner + //glColor3f(m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x2, y1, -3.0); // top right corner + //glColor3f(m_bkgRed * 1.2, m_bkgGreen * 1.2, m_bkgBlue * 1.2); glVertex3f(x1, y2, -3.0); // bottom left corner + //glColor3f(m_bkgRed * 1.6, m_bkgGreen * 1.6, m_bkgBlue * 1.6); glVertex3f(x2, y2, -3.0); // bottom right corner + //glEnd(); + + // set a scissor box + glScissor(x1, size().height() - y2, x2, height); + glEnable(GL_SCISSOR_TEST); + + TGL3float *vertexArray = new TGL3float[vertexArrayLength]; + TGL3float *vertexColorArray = new TGL3float[vertexArrayLength]; + + TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength]; + TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength]; + + switch (m_panMode) { + + case (PanGraphicsMode) FilledLine: + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + vertexColorArrayBg[2*i].x = m_redF; + vertexColorArrayBg[2*i].y = m_greenF; + vertexColorArrayBg[2*i].z = m_blueF; + + vertexColorArrayBg[2*i+1].x = 0.3 * m_redF; + vertexColorArrayBg[2*i+1].y = 0.3 * m_greenF; + vertexColorArrayBg[2*i+1].z = 0.3 * m_blueF; + + vertexColorArray[i].x = m_red * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].y = m_green * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].z = m_blue * (yScaleColor * m_panadapterBins.at(i)); + mutex.unlock(); + + vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i].z = -2.5; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + vertexArrayBg[2*i+1].z = -2.5; + + vertexArray[i].x = (GLfloat)(i/m_scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArray[i].z = -1.0; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + + break; + + case (PanGraphicsMode) Line: + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + vertexColorArray[i].x = m_red * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].y = m_green * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].z = m_blue * (yScaleColor * m_panadapterBins.at(i)); + mutex.unlock(); + + vertexArray[i].x = (GLfloat)(i/m_scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArray[i].z = -1.0; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + + break; + + case (PanGraphicsMode) Solid: + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + vertexColorArrayBg[2*i].x = m_redST; + vertexColorArrayBg[2*i].y = m_greenST; + vertexColorArrayBg[2*i].z = m_blueST; + + vertexColorArrayBg[2*i+1].x = m_redSB; + vertexColorArrayBg[2*i+1].y = m_greenSB; + vertexColorArrayBg[2*i+1].z = m_blueSB; + mutex.unlock(); + + vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i].z = -2.0f; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + vertexArrayBg[2*i+1].z = -2.0f; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + //glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength); + glDrawArrays(GL_LINES, 0, 2*vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + //glEnable(GL_MULTISAMPLE); + //glEnable(GL_LINE_SMOOTH); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + + break; + } + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + // disable scissor box + glDisable(GL_SCISSOR_TEST); +} + +void QGLDistancePanel::drawPanVerticalScale() { + + if (!m_dBmScalePanRect.isValid()) return; + + int width = m_dBmScalePanRect.width(); + int height = m_dBmScalePanRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_dBmScaleFBO || m_dBmScalePanadapterUpdate || m_dBmScalePanadapterRenew) { + + if (!m_dBmScaleFBO || m_dBmScalePanadapterRenew) { + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + m_dBmScaleFBO = new QGLFramebufferObject(width, height); + } + + m_dBmScaleFBO->bind(); + renderPanVerticalScale(); + m_dBmScaleFBO->release(); + + m_dBmScalePanadapterUpdate = false; + m_dBmScalePanadapterRenew = false; + } + + renderTexture(m_dBmScalePanRect, m_dBmScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLDistancePanel::drawPanHorizontalScale() { + + if (!m_freqScalePanRect.isValid()) return; + + int width = m_freqScalePanRect.width(); + int height = m_freqScalePanRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_frequencyScaleFBO || m_freqScalePanadapterUpdate || m_freqScalePanadapterRenew) { + + if (!m_frequencyScaleFBO || m_freqScalePanadapterRenew) { + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + m_frequencyScaleFBO = new QGLFramebufferObject(width, height); + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_frequencyScaleFBO->bind(); + renderPanHorizontalScale(); + m_frequencyScaleFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + m_freqScalePanadapterUpdate = false; + m_freqScalePanadapterRenew = false; + } + + renderTexture(m_freqScalePanRect, m_frequencyScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLDistancePanel::drawPanadapterGrid() { + + if (!m_panRect.isValid()) return; + + int width = m_panRect.width(); + int height = m_panRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + //glColor4f(0.35, 0.46, 0.51, 0.7); + //glColor4f(0.45, 0.56, 0.61, 1.0); + glColor4f(0.45f, 0.56f, 0.61f, 0.8f); + + glDisable(GL_MULTISAMPLE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_panadapterGridFBO || m_panGridUpdate || m_panGridRenew) { + + if (!m_panadapterGridFBO || m_panGridRenew) { + + if (m_panadapterGridFBO) { + + delete m_panadapterGridFBO; + m_panadapterGridFBO = 0; + } + + m_panadapterGridFBO = new QGLFramebufferObject(width, height); + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_panadapterGridFBO->bind(); + renderPanadapterGrid(); + m_panadapterGridFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + m_panGridUpdate = false; + m_panGridRenew = false; + } + + //renderTexture(m_panRect, m_panadapterGridFBO->texture(), -2.0f); + //renderTexture(m_panRect, m_panadapterGridFBO->texture(), -1.5f); + renderTexture(m_panRect, m_panadapterGridFBO->texture(), -2.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); + glEnable(GL_MULTISAMPLE); +} + +void QGLDistancePanel::drawPanFilter() { + + qreal freqLo = m_filterLowerFrequency / m_sampleRate; + qreal freqHi = m_filterUpperFrequency / m_sampleRate; + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + //glColor4f(0.65, 0.65, 0.65, 0.25); + QColor color = QColor(150, 150, 150, 100); + + GLint x1 = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + freqLo * m_panRect.width() / m_freqScaleZoomFactor); + GLint x2 = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + freqHi * m_panRect.width() / m_freqScaleZoomFactor); + GLint y1 = m_panRect.top() + 1; + GLint y2 = m_panRect.top() + m_panRect.height() - 1; + + QRect filterRect = QRect(x1, y1, x2 - x1, y2 - y1); + + if ((x1 >= m_panRect.left() && x1 <= m_panRect.right()) || + (x2 >= m_panRect.left() && x2 <= m_panRect.right()) || + (x1 < m_panRect.left() && x2 > m_panRect.right())) + { + if (filterRect.height() > 5) + drawGLRect(filterRect, color, 3.0); + } + + // draw a line for the display center + y1 = m_panRect.top() + 3; + y2 = m_panRect.top() + (m_panRect.height() - 3); + + if (y2 > y1 + 3) { + + GLint x = m_panRect.width()/2; + + color = set->getPanadapterColors().panCenterLineColor; + + //glDisable(GL_LINE_SMOOTH); + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + glBegin(GL_LINES); + /*glVertex2i(x, y1); + glVertex2i(x, y2);*/ + glVertex3f(x, y1, 4.0f); + glVertex3f(x, y2, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + } +} + +void QGLDistancePanel::drawCrossHair() { + + QRect rect(0, m_panRect.top(), width(), height() - m_panRect.top()); + + int x = m_mousePos.x(); + int y = m_mousePos.y(); + + glDisable(GL_MULTISAMPLE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + + qglColor(QColor(255, 255, 255, 80)); + + // set a scissor box + glScissor(rect.left(), rect.top(), rect.width() - 1, rect.height()); + glEnable(GL_SCISSOR_TEST); + + // horizontal line + glBegin(GL_LINES); + glVertex3f(m_dBmScalePanRect.right() - 2, y, 4.0f); + glVertex3f(rect.right() - 1, y, 4.0f); + glEnd(); + + // vertical line + glBegin(GL_LINES); + glVertex3f(x, rect.top() + 1, 4.0f); + glVertex3f(x, rect.bottom() - 1, 4.0f); + glEnd(); + + // cross hair + qglColor(QColor(255, 255, 255, 180)); + glBegin(GL_LINES); + glVertex3f(x , y - 20, 5.0f); + glVertex3f(x , y + 20, 5.0f); + glVertex3f(x - 20, y, 5.0f); + glVertex3f(x + 20, y, 5.0f); + glEnd(); + + // text only on panadapter + //if (m_mouseRegion == panadapterRegion) { + + QString str; + qglColor(QColor(255, 255, 255, 255)); + + int dx = m_panRect.width()/2 - x; + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + qreal df = unit * dx; + qreal frequency = m_frequency - df; + + str = frequencyString(-df, true); + if (x > m_panRect.width() - 85) + m_oglTextSmall->renderText(x -90, y - 30, 5.0f, str); + else + m_oglTextSmall->renderText(x + 4, y - 30, 5.0f, str); + + str = frequencyString(frequency); + if (x > m_panRect.width() - 85) + m_oglTextSmall->renderText(x - 90, y - 18, 5.0f, str); + else + m_oglTextSmall->renderText(x + 4, y - 18, 5.0f, str); + + if (m_mouseRegion == panadapterRegion) { + + qreal dBm = m_dBmPanMax - ((m_dBmPanMax - m_dBmPanMin) * ((qreal)(y - m_panRect.top()) / m_panRect.height())); + str = QString::number(dBm, 'f', 1) + " dBm"; + if (x > m_panRect.width() - 85) + m_oglTextSmall->renderText(x - 90, y + 6, 5.0f, str); + else + m_oglTextSmall->renderText(x + 4, y + 6, 5.0f, str); + } + + // disable scissor box + glDisable(GL_SCISSOR_TEST); + + glEnable(GL_MULTISAMPLE); +} + +//************ +void QGLDistancePanel::drawDistanceSpectrum() { + + //float yScale; + //float yScaleColor; + //float yTop; + float localMax; + + GLint displayWidth = (GLint)m_distanceSpectrumRect.width(); + + double distScale = 0; + //freqScale = (float)m_sampleRate / rect.width(); + //distScale = 1024.0f / rect.width(); + + distScale = (double)(1.0f * qRound(m_chirpBufferLength * m_distScaleZoomFactor) / m_distanceSpectrumRect.width()); + if (distScale < 1.0) distScale = 1.0; + + if (distScale < 0) { + + drawGLRect(m_distanceSpectrumRect, Qt::black); + //GRAPHICS_DEBUG << "drawDistanceSpectrum bad distance scale:" << distScale; + return; + } + + //qreal dBmRange = qAbs(dBmMax - dBmMin); + qreal dBmRange = (m_dBmDistMax - m_dBmDistMin) * m_distScaleZoomFactor; + + float yScale = m_distanceSpectrumRect.height() / dBmRange; + //float yScaleColor = 2.0f / dBmRange; + float yTop = m_distanceSpectrumRect.top() + m_distanceSpectrumRect.height(); + + int idx = 0; + int lIdx = 0; + int rIdx = 0; + + // set a scissor box + glScissor(m_distanceSpectrumRect.left(), size().height() - m_distanceSpectrumRect.bottom() - 1, m_distanceSpectrumRect.left() + m_distanceSpectrumRect.width(), m_distanceSpectrumRect.height()); + glEnable(GL_SCISSOR_TEST); + + GLint vertexArrayLength = 0; + + /*if (m_vertexArray) { + + delete [] m_vertexArray; + m_vertexArray = 0; + } + + if (m_vertexColorArray) { + + delete [] m_vertexColorArray; + m_vertexColorArray = 0; + }*/ + + glLineWidth(1); + glShadeModel(GL_SMOOTH); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + vertexArrayLength = displayWidth; + TGL2float *vertexArray = new TGL2float[vertexArrayLength]; + TGL3float *vertexColorArray = new TGL3float[vertexArrayLength]; + + //TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength]; + //TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength]; + + //m_vertexArray = new TGL2float[vertexArrayLength]; + //m_vertexColorArray = new TGL3float[vertexArrayLength]; + + m_redD = (GLfloat)(set->getPanadapterColors().distanceLineColor.red() / 256.0); + m_greenD = (GLfloat)(set->getPanadapterColors().distanceLineColor.green() / 256.0); + m_blueD = (GLfloat)(set->getPanadapterColors().distanceLineColor.blue() / 256.0); + + /*m_rf = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_gf = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_bf = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0);*/ + + for (int i = 0; i < vertexArrayLength; i++) { + + lIdx = (int)floor((qreal)(i * distScale)); + rIdx = (int)floor((qreal)(i * distScale) + distScale); + + // max value; later we try mean value also! + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + if (m_distanceSpectrumBuffer[j] > localMax) { + + localMax = m_distanceSpectrumBuffer[j]; + idx = j; + } + } + + /*m_spectrumVertexColorArrayBg[2*i].x = 0.10; + m_spectrumVertexColorArrayBg[2*i].y = 0.20; + m_spectrumVertexColorArrayBg[2*i].z = 0.25;*/ + + vertexColorArray[i].x = m_redD;// * (yScaleColor * (m_distanceSpectrumBuffer[idx] - dBmMin)); + vertexColorArray[i].y = m_greenD;// * (yScaleColor * (m_distanceSpectrumBuffer[idx] - dBmMin)); + vertexColorArray[i].z = m_blueD;// * (yScaleColor * (m_distanceSpectrumBuffer[idx] - dBmMin)); + + vertexArray[i].x = i; + vertexArray[i].y = yTop - yScale * (m_distanceSpectrumBuffer[idx] - m_dBmDistMin); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(2, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + delete[] vertexArray; + delete[] vertexColorArray; + + // disable scissor box + glDisable(GL_SCISSOR_TEST); +} + +void QGLDistancePanel::drawDistHorizontalScale() { + + if (m_freqScaleDistancePanRect.isEmpty()) return; + + //QFontMetrics d_fm(m_smallFont); + + int rulerFontHeight; + int rulerFontMaxWidth; + double maxSpanDist; + + if (m_showChirpFFT) { + + rulerFontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0Hz").height(); + rulerFontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000000").width(); + + //maxSpanDist = m_sampleRate / 2; + maxSpanDist = m_sampleRate / 4; + //maxSpanDist = m_sampleRate; + } + else { + + rulerFontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kmM").height(); + rulerFontMaxWidth = m_fonts.smallFontMetrics->boundingRect("0000000").width(); + + maxSpanDist = m_chirpBufferLength * m_kilometersPerGate; + } + + qreal kilometerSpan = maxSpanDist * m_distScaleZoomFactor; + + qreal lowerDist = 0; + qreal upperDist = 0; + + if (m_showChirpFFT) + lowerDist = -maxSpanDist/2; + else { + + lowerDist = m_dBmDistDelta; + if (lowerDist < 0.0) lowerDist = 0.0; + } + + upperDist = lowerDist + kilometerSpan; + if (upperDist > maxSpanDist) { + + upperDist = maxSpanDist; + lowerDist = maxSpanDist - kilometerSpan; + } + + qreal unit = (float)(m_freqScaleDistancePanRect.width() / kilometerSpan); + + m_distanceScale = getXRuler(m_freqScaleDistancePanRect, rulerFontMaxWidth, unit, lowerDist, upperDist); + + // draw the scale background + drawGLScaleBackground(m_freqScaleDistancePanRect, Qt::black); + + // draw the distance scale + int offset_X = -1; + int textOffset_y = 17; + double distScale = 1; + +// char *str; +// if (m_showChirpFFT) +// str = " Hz "; +// else +// str = " km "; + + QRect scaledTextRect(0, textOffset_y, 1, rulerFontHeight); + //scaledTextRect.setWidth(d_fm.width(str)); + scaledTextRect.moveLeft(m_freqScaleDistancePanRect.width() - scaledTextRect.width());// - menu_pull_right_rect.width()); + + glColor3f(0.94f, 0.22f, 0.43f); + glRasterPos3f(m_freqScaleDistancePanRect.width() - 30, m_freqScaleDistancePanRect.top() + textOffset_y, 0.0); + //writeBitmapString(GLUT_BITMAP_HELVETICA_10, str); + + if (m_mouseRegion == freqScaleDistancePanRegion) + glColor3f(0.8f, 0.92f, 0.97f); + else + glColor3f(0.65f, 0.76f, 0.81f); + + int len = m_distanceScale.mainPointPositions.length(); + if (len > 0) { + + glLineWidth(3); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_distanceScale.mainPointPositions.at(i), m_freqScaleDistancePanRect.top() + 1, 0.0f); // origin of the line + glVertex3f(m_distanceScale.mainPointPositions.at(i), m_freqScaleDistancePanRect.top() + 4, 0.0f); // ending point of the line + } + glEnd(); + + for (int i = 0; i < len; i++) { + + QString str = QString::number(m_distanceScale.mainPoints.at(i) / distScale, 'f', 0); + + int textWidth = m_fonts.smallFontMetrics->width(str); + QRect textRect(m_distanceScale.mainPointPositions.at(i) + offset_X - (textWidth / 2), textOffset_y, textWidth, rulerFontHeight); + + QByteArray ba = str.toLatin1(); + char *cstr = ba.data(); + + if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue; + + glRasterPos3f(m_distanceScale.mainPointPositions.at(i) + offset_X - (textWidth / 2), m_freqScaleDistancePanRect.top() + textOffset_y, 0.0); + m_oglTextSmall->renderText(textRect.x(), textRect.y(), cstr); + //writeBitmapString(GLUT_BITMAP_HELVETICA_10, cstr); + } + } + + len = m_distanceScale.subPointPositions.length(); + if (len > 0) { + + glLineWidth(1); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_distanceScale.subPointPositions.at(i), m_freqScaleDistancePanRect.top() + 1, 0.0f); // origin of the line + glVertex3f(m_distanceScale.subPointPositions.at(i), m_freqScaleDistancePanRect.top() + 3, 0.0f); // ending point of the line + } + glEnd(); + } +} + +void QGLDistancePanel::drawDistVerticalScale() { + /*const QRect &rect, + const QRect &distRect, + int region, + qreal dBmMin, + qreal dBmMax, + bool showZerodBmLine*/ + + if (m_dBmScaleDistancePanRect.isEmpty()) return; + + //QFontMetrics d_fm(m_smallFont); + int spacing = 5; + int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing; + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width(); + + qreal dBmRange = qAbs(m_dBmDistScaleMax - m_dBmDistScaleMin); + //if (dBmRange <= 0) return; + + qreal unit = (float)(m_dBmScaleDistancePanRect.height() / dBmRange); + + m_dBmScale = getYRuler(m_dBmScaleDistancePanRect, fontHeight, unit, m_dBmDistScaleMin, m_dBmDistScaleMax); + + // draw the scale background + drawGLScaleBackground(m_dBmScaleDistancePanRect, QColor(60, 60, 60, 80)); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + textRect.moveRight(14); + int yOld = -textRect.height(); + + if (m_mouseRegion == dBmScaleDistancePanRegion) + glColor3f(0.8f, 0.92f, 0.97f); + else + glColor3f(0.65f, 0.76f, 0.81f); + + + glLineWidth(1); + int len = m_dBmScale.mainPointPositions.length(); + + if (len > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_dBmScaleDistancePanRect.left(), m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(m_dBmScaleDistancePanRect.left() + 4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + for (int i = 0; i < len; i++) { + + textRect.moveTop(m_dBmScale.mainPointPositions.at(i) + textRect.height()/3); + + QString str; + if (textRect.y() >= yOld && + textRect.bottom() <= (m_dBmScaleDistancePanRect.top() + m_dBmScaleDistancePanRect.height() - textRect.height()) && + m_dBmScale.mainPointPositions.at(i) > 10 + m_dBmScaleDistancePanRect.top()) + { + str = QString::number(m_dBmScale.mainPoints.at(i), 'f', 1); + QByteArray ba = str.toLatin1(); + //char *cstr = ba.data(); + glRasterPos3f(textRect.right() + m_dBmScaleDistancePanRect.left(), textRect.y(), 0.0); + //writeBitmapString(GLUT_BITMAP_TIMES_ROMAN_10, cstr); + yOld = textRect.bottom(); + } + + if (qRound(m_dBmScale.mainPoints.at(i)) == 0 && m_showZerodBmLine) { + + int zerodBmLine = m_dBmScale.mainPointPositions.at(i); + if (zerodBmLine > m_dBmScaleDistancePanRect.top() && zerodBmLine < m_dBmScaleDistancePanRect.bottom()) { + + glColor3f(0.2f, 0.87f, 0.87f); + glBegin(GL_LINES); + glVertex3f(m_distanceSpectrumRect.left(), zerodBmLine, 0.0f); // origin of the line + glVertex3f(m_distanceSpectrumRect.width() - m_dBmScaleDistancePanRect.width() + 4, zerodBmLine, 0.0f); // ending point of the line + glEnd(); + + if (m_mouseRegion == dBmScaleDistancePanRegion) + glColor3f(0.8f, 0.92f, 0.97f); + else + glColor3f(0.65f, 0.76f, 0.81f); + } + } + } + } + + if (m_mouseRegion == dBmScaleDistancePanRegion) + glColor3f(0.5f, 0.62f, 0.67f); + else + glColor3f(0.35f, 0.46f, 0.51f); + + if (m_dBmScale.subPointPositions.length() > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < m_dBmScale.subPointPositions.length(); i++) { + + glVertex3f(m_dBmScaleDistancePanRect.left(), m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(m_dBmScaleDistancePanRect.left() + 2, m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + //char* s = "dBm"; + textRect.moveTop(m_dBmScaleDistancePanRect.top() + m_dBmScaleDistancePanRect.height() - textRect.height()); + glColor3f(0.94f, 0.22f, 0.43f); + //glRasterPos3f(textRect.left(), textRect.center().y(), 0.0); + //glRasterPos3f(textRect.right() + right, textRect.center().y(), 0.0); + glRasterPos3f(textRect.right() + m_dBmScaleDistancePanRect.left(), textRect.center().y(), 0.0); + //writeBitmapString(GLUT_BITMAP_HELVETICA_10, s); + + //glPushMatrix(); + // glTranslatef(0.0, 0.0, 0.0); + // //glRotatef(45.0, 0.0, 0.0, 1.0); + // glScalef(0.25, 0.25, 0.25); + // writeStrokeString(GLUT_STROKE_ROMAN, s); + //glPopMatrix(); +} + +//********************************************************************************************** +// The algorithms of the scale functions renderPanVerticalScale() and renderPanHorizontalScale() +// are taken from SDRMAXIII (c) Catherine Moss, with permission. + +void QGLDistancePanel::renderPanVerticalScale() { + + QString str; + //QFontMetrics d_fm(m_smallFont); + //QFontMetrics d_fm(m_normalFont); + + int spacing = 7; + int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing; + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width(); + + GLint width = m_dBmScalePanRect.width(); + GLint height = m_dBmScalePanRect.height(); + + qreal unit = (qreal)(m_dBmScalePanRect.height() / qAbs(m_dBmPanMax - m_dBmPanMin)); + + m_dBmScale = getYRuler2(m_dBmScalePanRect, fontHeight, unit, m_dBmPanMin, m_dBmPanMax); + + glClear(GL_COLOR_BUFFER_BIT); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + textRect.moveLeft(3); + int yOld = -textRect.height(); + + int len = m_dBmScale.mainPointPositions.length(); + int sublen = m_dBmScale.subPointPositions.length(); + + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, width, height), QColor(30, 30, 30, 180)); + + if (len > 0) { + + glColor3f(0.65f, 0.76f, 0.81f); + glLineWidth(1); + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(width, m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + glColor3f(0.45f, 0.56f, 0.61f); + if (sublen > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < sublen; i++) { + + glVertex3f(width, m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 2, m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + glColor3f(0.75f, 0.86f, 0.91f); + for (int i = 0; i < len; i++) { + + textRect.moveBottom(m_dBmScale.mainPointPositions.at(i) + textRect.height()/2); + + if (textRect.y() >= yOld && textRect.bottom() <= (m_dBmScalePanRect.height() - textRect.height())) { + + str = QString::number(m_dBmScale.mainPoints.at(i), 'f', 1); + m_oglTextSmall->renderText(textRect.x() + fontMaxWidth - m_fonts.smallFontMetrics->tightBoundingRect(str).width(), textRect.y(), str); + yOld = textRect.bottom(); + } + } + } + + textRect.moveTop(m_dBmScalePanRect.height() - textRect.height()); + glColor3f(0.94f, 0.22f, 0.43f); + + str = QString("dBm"); + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); +} + +void QGLDistancePanel::renderPanHorizontalScale() { + + //GRAPHICS_DEBUG << "render frequency scale"; + //QFontMetrics d_fm(m_smallFont); + int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kMGHz").height(); + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.000.0").width(); + + qreal freqSpan = (qreal)(m_sampleRate * m_freqScaleZoomFactor); + qreal lowerFreq = (qreal)m_frequency - freqSpan / 2; + qreal upperFreq = (qreal)m_frequency + freqSpan / 2; + qreal unit = (qreal)(m_freqScalePanRect.width() / freqSpan); + + m_frequencyScale = getXRuler(m_freqScalePanRect, fontMaxWidth, unit, lowerFreq, upperFreq); + + // draw the frequency scale + int offset_X = -1; + int textOffset_y = 5; + double freqScale = 1; + + QString fstr = QString(" Hz "); + if (upperFreq >= 1e6) { freqScale = 1e6; fstr = QString(" MHz "); } + else + if (upperFreq >= 1e3) { freqScale = 1e3; fstr = QString(" kHz "); } + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, m_freqScalePanRect.width(), m_freqScalePanRect.height()), QColor(0, 0, 0, 255)); + + QRect scaledTextRect(0, textOffset_y, 1, m_freqScalePanRect.height()); + scaledTextRect.setWidth(m_fonts.smallFontMetrics->width(fstr)); + scaledTextRect.moveLeft(m_freqScalePanRect.width() - scaledTextRect.width()); + + glColor3f(0.65f, 0.76f, 0.81f); + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + glLineWidth(3); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 4.0f, 0.0f); + } + glEnd(); + + for (int i = 0; i < len; i++) { + + QString str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 3); + + if (i > 0) { + + double delta = m_frequencyScale.mainPoints.at(i) - m_frequencyScale.mainPoints.at(i-1); + if (delta < 1000.0) + str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 4); + else + if (freqScale == 1e3) + while (str.endsWith('0')) str.remove(str.size() - 1, 1); + } + if (str.endsWith('.')) str.remove(str.size() - 1, 1); + + int text_width = m_fonts.smallFontMetrics->width(str); + QRect textRect(m_frequencyScale.mainPointPositions.at(i) + offset_X - (text_width / 2), textOffset_y, text_width, fontHeight); + + if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue; + + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + } + } + + if (m_frequencyScale.subPointPositions.length() > 0) { + + glLineWidth(1); + glBegin(GL_LINES); + for (int i = 0; i < m_frequencyScale.subPointPositions.length(); i++) { + + glVertex3f(m_frequencyScale.subPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.subPointPositions.at(i), 3.0f, 0.0f); + } + glEnd(); + } + + glColor3f(0.94f, 0.22f, 0.43f); + m_oglTextSmall->renderText(m_freqScalePanRect.width() - 30, textOffset_y, fstr); +} + +void QGLDistancePanel::renderPanadapterGrid() { + + //GRAPHICS_DEBUG << "render panadapter grid"; + //glLineStipple(1, 0xCCCC); + glClear(GL_COLOR_BUFFER_BIT); + glLineStipple(1, 0x9999); + glEnable(GL_LINE_STIPPLE); + glLineWidth(1.0f); + + // vertical lines + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + GLint x1 = m_panRect.left(); + GLint x2 = 1; + if (m_dBmScalePanRect.isValid()) x2 += m_dBmScalePanRect.width(); + + //GLint y1 = rect.top() + 1; + GLint y1 = 1; + GLint y2 = m_panRect.bottom() - 1; + + TGL2int *vertexArray = new TGL2int[len * 2]; + int vertexArrayLen = 0; + + TGL2int point1, point2; + point1.y = y1; + point2.y = y2; + for (int i = 0; i < len; i++) { + + GLint x = m_frequencyScale.mainPointPositions.at(i); + if (x < x2) continue; + x += x1; + point1.x = x; + point2.x = x; + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_INT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + } + + // horizontal lines + len = m_dBmScale.mainPointPositions.length(); + if (len > 0) { + + TGL2float *vertexArray = new TGL2float[len * 2]; + int vertexArrayLen = 0; + + TGL2float point1, point2; + point1.x = m_panRect.left() + m_dBmScalePanRect.width(); + point2.x = m_panRect.right(); + + for (int i = 0; i < len; i++) { + + GLfloat y = m_dBmScale.mainPointPositions.at(i); + + point1.y = y; + point2.y = y; + + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + + } + glDisable(GL_LINE_STIPPLE); +} + + +//******************************************************************** + +void QGLDistancePanel::getRegion(QPoint p) { + + QRect mouse_rect(0, 0, 100, 100); + mouse_rect.moveCenter(p); + + if (m_freqScalePanRect.contains(p)) { + + m_mouseRegion = freqScalePanadapterRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else if (m_dBmScalePanRect.contains(p)) { + + m_mouseRegion = dBmScalePanadapterRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else if (abs(p.x() - m_filterRect.left()) < m_snapMouse && + m_panRect.contains(p) + ) { + m_mouseRegion = filterRegionLow; + m_mouseDownFilterFrequencyLo = m_filterLowerFrequency; + } + + else if (abs(p.x() - m_filterRect.right()) < m_snapMouse && + m_panRect.contains(p) + ) { + m_mouseRegion = filterRegionHigh; + m_mouseDownFilterFrequencyHi = m_filterUpperFrequency; + } + + else if (m_panRect.contains(p)) { + + m_mouseRegion = panadapterRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + + else if (m_freqScaleDistancePanRect.contains(p)) { + + m_mouseRegion = freqScaleDistancePanRegion; + m_distRulerUpdate = true; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + + else if (m_dBmScaleDistancePanRect.contains(p)) { + + m_mouseRegion = dBmScaleDistancePanRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else if (m_distanceSpectrumRect.contains(p)) { + + m_mouseRegion = distancePanRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else + m_mouseRegion = elsewhere; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + updateGL(); + update(); + }*/ + //GRAPHICS_DEBUG << "region" << m_mouseRegion; +} + +void QGLDistancePanel::resizeGL(int iWidth, int iHeight) { + + int width = (int)(iWidth/2) * 2; + int height = iHeight; + + if (width != m_oldWidth) { + + m_freqScalePanadapterRenew = true; + m_panGridRenew = true; + + m_oldWidth = width; + } + + m_spectrumVertexColorUpdate = true; + //m_displayData.size = QSize(width, height); + + glFinish(); + + m_resizeTime.restart(); + setupDisplayRegions(QSize(width, height)); + glViewport(0, 0, (GLsizei)width, (GLsizei)height); + + setProjectionOrthographic(width, height); +} + +void QGLDistancePanel::setupDisplayRegions(QSize size) { + + m_displayTop = 0; + int freqScaleRectHeight = 20; + int dBmScaleWidth = 45; + int distScaleRectHeight = 20; + + m_freqScalePanRect = QRect( + 0, + m_displayTop + qRound((size.height() - m_displayTop - freqScaleRectHeight) * m_freqRulerPosition), + size.width(), + freqScaleRectHeight); + + m_panRect = QRect( + 0, + m_displayTop, + size.width(), + m_freqScalePanRect.top() - m_displayTop); + + if (m_panRect.height() != m_oldPanRectHeight) { + + m_dBmScalePanadapterRenew = true; + m_panGridRenew = true; + } + + m_oldPanRectHeight = m_panRect.height(); + m_panRectWidth = (GLint)m_panRect.width(); + + m_freqScaleDistancePanRect = QRect( + 0, + size.height() - m_displayTop - distScaleRectHeight + 1, + size.width(), + distScaleRectHeight); + + m_distanceSpectrumRect = QRect( + m_freqScalePanRect.left(), + m_freqScalePanRect.bottom(), + m_freqScalePanRect.width(), + size.height() - m_displayTop - m_freqScalePanRect.bottom() - distScaleRectHeight + 1); + + m_distancePanRect = QRect( + m_freqScalePanRect.left(), + m_freqScalePanRect.bottom(), + m_freqScalePanRect.width(), + size.height() - m_displayTop - m_freqScalePanRect.bottom() - distScaleRectHeight + 1); + + m_dBmScaleDistancePanRect = QRect( + m_distanceSpectrumRect.right() - dBmScaleWidth, + m_freqScalePanRect.bottom(), + dBmScaleWidth, + size.height() - m_displayTop - m_freqScalePanRect.bottom() - distScaleRectHeight + 1); + + m_dBmScalePanRect = QRect( + m_panRect.left(), + m_displayTop, + 45, + m_panRect.height()); + + m_freqScalePanadapterUpdate = true; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + + //*************************************************************************** + /*GRAPHICS_DEBUG << "***************************************************************************"; + GRAPHICS_DEBUG << "total size" << size.height(); + GRAPHICS_DEBUG << "sizes (top, bottom, height):"; + GRAPHICS_DEBUG << "panRect: " << m_panRect.top() << " " << m_panRect.bottom() << " " << m_panRect.height(); + GRAPHICS_DEBUG << "freqScalePanRect: " << m_freqScalePanRect.top() << " " << m_freqScalePanRect.bottom() << " " << m_freqScalePanRect.height(); + GRAPHICS_DEBUG << "dBmScalePanRect: " << m_dBmScalePanRect.top() << " " << m_dBmScalePanRect.bottom() << " " << m_dBmScalePanRect.height(); + GRAPHICS_DEBUG << "m_distanceSpectrumRect: " << m_distanceSpectrumRect.top() << " " << m_distanceSpectrumRect.bottom() << " " << m_distanceSpectrumRect.height(); + GRAPHICS_DEBUG << "m_freqScaleDistancePanRect: " << m_freqScaleDistancePanRect.top() << " " << m_freqScaleDistancePanRect.bottom() << " " << m_freqScaleDistancePanRect.height(); + GRAPHICS_DEBUG << "m_dBmScaleDistancePanRect: " << m_dBmScaleDistancePanRect.top() << " " << m_dBmScaleDistancePanRect.bottom() << " " << m_dBmScaleDistancePanRect.height(); + GRAPHICS_DEBUG << "";*/ +} + +void QGLDistancePanel::saveGLState() { + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); +} + +void QGLDistancePanel::restoreGLState() { + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glPopAttrib(); +} + +//******************************************************************** +// HMI control + +void QGLDistancePanel::enterEvent(QEvent *event) { + + setFocus(Qt::MouseFocusReason); + + m_mousePos = QPoint(-1, -1); + m_mouseRegion = elsewhere; + update(); + + QGLWidget::enterEvent(event); +} + +void QGLDistancePanel::leaveEvent(QEvent *event) { + + m_mousePos = QPoint(-1, -1); + m_mouseRegion = elsewhere; + update(); + + QGLWidget::leaveEvent(event); +} + +void QGLDistancePanel::wheelEvent(QWheelEvent* event) { + + //GRAPHICS_DEBUG << "wheelEvent"; + QPoint pos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + double freqStep = set->getMouseWheelFreqStep(0); + + switch (m_mouseRegion) { + + case panadapterRegion: + + double delta = 0; + if (event->delta() < 0) delta = -freqStep; + else + if (event->delta() > 0) delta = freqStep; + + if (m_frequency + delta > MAXFREQUENCY) + m_frequency = MAXFREQUENCY; + else + if (m_frequency + delta < 0) + m_frequency = 0; + else + // snap to the frequency step + m_frequency = (long)(qRound((m_frequency + delta) / qAbs(freqStep)) * qAbs(freqStep)); + + //set->setFrequency(this, true, 0, m_frequency); + set->setVFOFrequency(this, 0, 0, m_frequency); + + /*if (m_spectrumAveragingOld) { + + m_spectrumAveragingOld = true; + m_spectrumAveraging = false; + + freqChangeTimer.restart(); + }*/ + break; + } + + //updateGL(); + update(); +} + +void QGLDistancePanel::mousePressEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mousePressEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == panadapterRegion) { + + if (event->buttons() == Qt::RightButton) { + + if (m_crossHairCursor) { + + m_crossHairCursor = false; + setCursor(Qt::ArrowCursor); + } + else { + + m_crossHairCursor = true; + setCursor(Qt::BlankCursor); + } + } + else if (event->buttons() == Qt::LeftButton && m_crossHairCursor) { + + double freqStep = set->getMouseWheelFreqStep(0); + int dx = m_panRect.width()/2 - m_mousePos.x(); + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + m_frequency -= unit * dx; + + m_frequency = (long)(qRound(m_frequency / qAbs(freqStep)) * qAbs(freqStep)); + + //set->setFrequency(this, true, 0, m_frequency); + set->setVFOFrequency(this, 0, 0, m_frequency); + update(); + } + } + else if (m_mouseRegion == freqScalePanadapterRegion) { + + m_rulerMouseDownPos = m_freqScalePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor); + update(); + + return; + } + else if (m_mouseRegion == freqScaleDistancePanRegion) { + + m_rulerMouseDownPos = m_freqScaleDistancePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor); + update(); + + return; + } + else if (m_mouseRegion == dBmScalePanadapterRegion) { + + m_rulerMouseDownPos = m_dBmScaleDistancePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitVCursor); + update(); + + return; + } + else if (m_mouseRegion == dBmScaleDistancePanRegion) { + + m_rulerMouseDownPos = m_dBmScaleDistancePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitVCursor); + update(); + + return; + } + + update(); +} + +void QGLDistancePanel::mouseReleaseEvent(QMouseEvent *event) { + + //GRAPHICS_DEBUG << "mouseReleaseEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == freqScalePanadapterRegion) { + + return; + } + else if (m_mouseRegion == freqScaleDistancePanRegion) { + + return; + } + else if (m_mouseRegion == dBmScaleDistancePanRegion) { + + if (event->button() == Qt::LeftButton && m_showZerodBmLine) { + + m_showZerodBmLine = false; + } + else if (event->button() == Qt::RightButton) { + } + update(); + return; + } + update(); +} + +void QGLDistancePanel::mouseMoveEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mouseMoveEvent"; + QPoint pos = event->pos(); + m_mousePos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + switch (m_mouseRegion) { + + case distancePanRegion: + //GRAPHICS_DEBUG << "distancePanRegion"; + setCursor(Qt::ArrowCursor); + //update(); + break; + + case panadapterRegion: + //GRAPHICS_DEBUG << "panadapterRegion Rx:" << m_receiver; + if (m_crossHairCursor) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_freqScalePanRect.width()); + qreal deltaFreq = unit * dPos.x(); + + long newFrequency = m_frequency + deltaFreq; + if (newFrequency > MAXFREQUENCY) + newFrequency = MAXFREQUENCY; + else + if (newFrequency + deltaFreq < 0) + newFrequency = 0; + else + m_frequency += deltaFreq; + + //set->setFrequency(this, true, 0, m_frequency); + set->setVFOFrequency(this, 0, 0, m_frequency); + m_mouseDownPos = pos; + } + //update(); + break; + + case dBmScalePanadapterRegion: + //GRAPHICS_DEBUG << "dBmScalePanadapterRegion"; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal unit = (qreal)(qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height()); + + qreal newMin = m_dBmPanMin - unit * dPos.y(); + qreal newMax = m_dBmPanMax - unit * dPos.y(); + + if (newMin > MINDBM && newMax < MAXDBM) { + + m_dBmPanMin = newMin; + m_dBmPanMax = newMax; + + set->setdBmPanScaleMin(0, m_dBmPanMin); + set->setdBmPanScaleMax(0, m_dBmPanMax); + } + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + } + else + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmPanDelta = 1.0; + else if (dPos.y() < 0) + m_dBmPanDelta = -1.0f; + + m_dBmPanMin += m_dBmPanDelta; + m_dBmPanMax -= m_dBmPanDelta; + + if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) { + + m_dBmPanMin -= m_dBmPanDelta; + m_dBmPanMax += m_dBmPanDelta; + } + if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM; + if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM; + + set->setdBmPanScaleMin(0, m_dBmPanMin); + set->setdBmPanScaleMax(0, m_dBmPanMax); + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + } + else + setCursor(Qt::ArrowCursor); + + //update(); + break; + + case dBmScaleDistancePanRegion: + //GRAPHICS_DEBUG << "dBmScaleDistancePanRegion"; + if (event->buttons() == Qt::LeftButton && + event->modifiers() == Qt::ControlModifier) { + + m_showZerodBmLine = true; + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)(qAbs(m_dBmDistScaleMax - m_dBmDistScaleMin) / m_distanceSpectrumRect.height()); + + qreal newMin = m_dBmDistScaleMin - unit * dPos.y(); + qreal newMax = m_dBmDistScaleMax - unit * dPos.y(); + + if (newMin > MINDISTDBM && newMax < MAXDISTDBM) { + + m_dBmDistScaleMin = newMin; + m_dBmDistScaleMax = newMax; + } + m_mouseDownPos = pos; + } + else + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)(qAbs(m_dBmDistMax - m_dBmDistMin) / m_distanceSpectrumRect.height()); + + qreal newMin = m_dBmDistMin - unit * dPos.y(); + qreal newMax = m_dBmDistMax - unit * dPos.y(); + + if (newMin > MINDISTDBM && newMax < MAXDISTDBM) { + + m_dBmDistMin = newMin; + m_dBmDistMax = newMax; + } + m_mouseDownPos = pos; + + m_dBmDistScaleMin = m_dBmDistMin; + m_dBmDistScaleMax = m_dBmDistMax; + } + else + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmDistDelta = 1.0; + else if (dPos.y() < 0) + m_dBmDistDelta = -1.0f; + + m_dBmDistMin += m_dBmDistDelta; + m_dBmDistMax -= m_dBmDistDelta; + + if (qAbs(m_dBmDistMax - m_dBmDistMin) < 10) { + + m_dBmDistMin -= m_dBmDistDelta; + m_dBmDistMax += m_dBmDistDelta; + } + if (m_dBmDistMin < MINDISTDBM) m_dBmDistMin = MINDISTDBM; + if (m_dBmDistMax > MAXDISTDBM) m_dBmDistMax = MAXDISTDBM; + + m_dBmDistScaleMin = m_dBmDistMin; + m_dBmDistScaleMax = m_dBmDistMax; + + m_mouseDownPos = pos; + } + else + setCursor(Qt::ArrowCursor); + //update(); + break; + + case freqScalePanadapterRegion: + //GRAPHICS_DEBUG << "freqScalePanadapterRegion Rx" << m_receiver; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + int bottom_y = height() - m_freqScalePanRect.height(); + int new_y = m_rulerMouseDownPos.y() - dPos.y(); + + if (new_y < m_panRect.top() + m_panSpectrumMinimumHeight) + new_y = m_panRect.top() + m_panSpectrumMinimumHeight; + if (new_y > bottom_y) + new_y = bottom_y; + + m_freqRulerPosition = (float)(new_y - m_panRect.top()) / (bottom_y - m_panRect.top()); + set->setFreqRulerPosition(this, 0, m_freqRulerPosition); + } + else + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.x() > 0) + m_freqScaleZoomFactor += 0.01; + else if (dPos.x() < 0) + m_freqScaleZoomFactor -= 0.01; + + if (m_freqScaleZoomFactor > 1.0) m_freqScaleZoomFactor = 1.0; + //if (m_freqScaleZoomFactor < 0.05) m_freqScaleZoomFactor = 0.05; + if (m_freqScaleZoomFactor < 0.15) m_freqScaleZoomFactor = 0.15; + + m_mouseDownPos = pos; + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + } + else + setCursor(Qt::ArrowCursor); + + //update(); + break; + + case freqScaleDistancePanRegion: + //GRAPHICS_DEBUG << "freqScaleDistancePanRegion"; + if (event->buttons() == Qt::LeftButton) { + + if (m_distScaleZoomFactor < 1.0) { + QPoint dPos = m_mouseDownPos - pos; + if (dPos.x() > 0) + m_distRulerDisplayDelta += m_distRulerDisplayDeltaStep; + else if (dPos.x() < 0) + m_distRulerDisplayDelta -= m_distRulerDisplayDeltaStep; + + if (m_distRulerDisplayDelta < 0) + m_distRulerDisplayDelta = 0.0; + + if (m_distRulerDisplayDelta > m_chirpBufferLength * m_kilometersPerGate) + m_distRulerDisplayDelta -= m_distRulerDisplayDeltaStep; + + m_mouseDownPos = pos; + } + else + m_distRulerDisplayDelta = 0.0; + } + else if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.x() > 0) + m_distScaleZoomFactor += 0.005; + else if (dPos.x() < 0) + m_distScaleZoomFactor -= 0.005; + + if (m_distScaleZoomFactor > 1.0) m_distScaleZoomFactor = 1.0; + if (m_distScaleZoomFactor < 0.1) m_distScaleZoomFactor = 0.1; + + m_mouseDownPos = pos; + } + else + setCursor(Qt::ArrowCursor); + + //update(); + break; + + case filterRegionLow: + + setCursor(Qt::SizeHorCursor); + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterLowerFrequency = qRound(m_mouseDownFilterFrequencyLo - dFreq); + set->setRXFilter(this, 0, m_filterLowerFrequency, m_filterUpperFrequency); + } + break; + + case filterRegionHigh: + + setCursor(Qt::SizeHorCursor); + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterUpperFrequency = qRound(m_mouseDownFilterFrequencyHi - dFreq); + set->setRXFilter(this, 0, m_filterLowerFrequency, m_filterUpperFrequency); + } + break; + + case elsewhere: + //GRAPHICS_DEBUG << "elsewhere"; + + //update(); + break; + } + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + //setupDisplayRegions(size()); + //update(); + + //locker.unlock(); +} + +void QGLDistancePanel::keyPressEvent(QKeyEvent* event) { + + //GRAPHICS_DEBUG << "keyPressEvent"; + if (event->key() == Qt::Key_Control) { + + //m_keyCTRLpressed = true; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //printf("Ry %f\n",ry); + //ry+=10.0f; + } + else if (event->key() == Qt::Key_T) { + + //printf("Ry %f\n",ry); + //ry-=10.0f; + } + else if (event->key() == Qt::Key_P) { + + //drawTeapot = !drawTeapot; + } + else if (event->key() == Qt::Key_W) { + + //approach -= 0.1f; + } + else if (event->key() == Qt::Key_S) { + + //approach += 0.1f; + } + else { + + //m_keyCTRLpressed = false; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //event->ignore(); + } + + QWidget::keyPressEvent(event); + //updateGL(); + update(); +} + +void QGLDistancePanel::timerEvent(QTimerEvent *) { + + update(); +} + +//******************************************************************** + +void QGLDistancePanel::setFrequency(QObject *sender, bool value, long freq) { + + Q_UNUSED(sender) + Q_UNUSED(value) + + m_frequency = freq; + //m_displayData.frequency = freq; + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + + //updateGL(); + update(); +} + +void QGLDistancePanel::setFilterFrequencies(QObject *sender, int rx, qreal lo, qreal hi) { + + Q_UNUSED(sender) + + if (rx == 0) { + + m_filterLowerFrequency = lo; + m_filterUpperFrequency = hi; + } + + update(); +} + +void QGLDistancePanel::freqRulerPositionChanged(float pos, int rx) { + + if (rx == 0) { + + m_freqRulerPosition = pos; + + setupDisplayRegions(size()); + update(); + } +} + +void QGLDistancePanel::setSpectrumBuffer(const float *buffer) { + + if (m_spectrumAveraging) { + + QVector m_specBuf(SAMPLE_BUFFER_SIZE); + + //spectrumBufferMutex.lock(); + + memcpy( + (float *) m_specBuf.data(), + (float *) &buffer[0], + SAMPLE_BUFFER_SIZE * sizeof(float)); + + specAv_queue.enqueue(m_specBuf); + if (specAv_queue.size() <= m_specAveragingCnt) { + + for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) + m_tmpBuf[i] += specAv_queue.last().data()[i]; + + //spectrumBufferMutex.unlock(); + return; + } + + for (int i = 0; i < SAMPLE_BUFFER_SIZE; i++) { + + m_tmpBuf[i] -= specAv_queue.first().at(i); + m_tmpBuf[i] += specAv_queue.last().at(i); + m_avgBuf[i] = m_tmpBuf[i] * m_scale; + } + + computeDisplayBins(m_avgBuf); + specAv_queue.dequeue(); + + //spectrumBufferMutex.unlock(); + } + else + computeDisplayBins(buffer); +} + +void QGLDistancePanel::computeDisplayBins(const float *panBuffer) { + + int newSampleSize = 0; + int deltaSampleSize = 0; + int idx = 0; + int lIdx = 0; + int rIdx = 0; + qreal localMax; + + if (m_serverMode == QSDR::ChirpWSPRFile) { + + newSampleSize = (int)floor(2 * BUFFER_SIZE * m_freqScaleZoomFactor); + deltaSampleSize = 2 * BUFFER_SIZE - newSampleSize; + } + else { + + newSampleSize = (int)floor(4 * BUFFER_SIZE * m_freqScaleZoomFactor); + deltaSampleSize = 4 * BUFFER_SIZE - newSampleSize; + } + + /*if (deltaSampleSize%2 != 0) { + deltaSampleSize += 1; + newSampleSize -= 1; + }*/ + + m_panScale = (qreal)(1.0 * newSampleSize / m_panRectWidth); + m_scaleMultOld = m_scaleMult; + + if (m_panScale < 0.125) { + m_scaleMult = 0.0625; + } + else if (m_panScale < 0.25) { + m_scaleMult = 0.125; + } + else if (m_panScale < 0.5) { + m_scaleMult = 0.25; + } + else if (m_panScale < 1.0) { + m_scaleMult = 0.5; + } + else { + m_scaleMult = 1.0; + } + + m_panSpectrumBinsLength = (GLint)(m_scaleMult * m_panRectWidth); + + /*if (bins != binsOld) { + + GRAPHICS_DEBUG << "newSampleSize" << newSampleSize; + GRAPHICS_DEBUG << "m_panScale" << m_panScale; + GRAPHICS_DEBUG << "bins:" << bins; + }*/ + + m_panadapterBins.clear(); + + for (int i = 0; i < m_panSpectrumBinsLength; i++) { + + idx = 0; + lIdx = (int)floor((qreal)(i * m_panScale / m_scaleMult)); + rIdx = (int)floor((qreal)(i * m_panScale / m_scaleMult) + m_panScale / m_scaleMult); + + // max value; later we try mean value also! + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + + if (panBuffer[j] > localMax) { + + localMax = panBuffer[j]; + idx = j; + } + } + idx += deltaSampleSize/2; + + m_panadapterBins << panBuffer[idx] - m_dBmPanMin - m_dBmPanLogGain; + } + update(); +} + +void QGLDistancePanel::setDistanceSpectrumBuffer(int sampleRate, qint64 length, const float *buffer) { + + Q_UNUSED(sampleRate) + Q_UNUSED(length) + Q_UNUSED(buffer) +} + +void QGLDistancePanel::distanceSpectrumBufferChanged(int sampleRate, qint64 length, const float *buffer) { + + Q_UNUSED(sampleRate) + + distanceSpectrumBufferMutex.lock(); + m_kilometersPerGate = 1.0f * 3E5 / sampleRate; + //m_kilometersPerGate = 0.5f * 3E5 / 12000; + m_chirpBufferLength = length; + memcpy(m_distanceSpectrumBuffer, buffer, m_chirpBufferLength * sizeof(float)); + distanceSpectrumBufferMutex.unlock(); + + update(); +} + +// get waterfall colors - taken from PowerSDR/KISS Konsole +//QColor QGLDistancePanel::getWaterfallColorAtPixel(qreal value) { +// +// QColor color; +// //int r = 0; int g = 0; int b = 0; +// int r, g, b; +// int lowerThreshold = (int)m_dBmPanMin - m_waterfallOffsetLo; +// int upperThreshold = (int)m_dBmPanMax + m_waterfallOffsetHi; +// +// float offset; +// float globalRange; +// float localRange; +// float percent; +// +// switch (m_waterColorScheme) { +// +// case QSDRGraphics::simple: +// +// if (value <= lowerThreshold) +// color = m_waterfallLoColor; +// else +// if (value >= upperThreshold) +// color = QColor(255, 255, 255);//m_waterfallHiColor; +// else { +// +// percent = (value - lowerThreshold) / (upperThreshold - lowerThreshold); +// if (percent <= 0.5) { // use a gradient between low and mid colors +// +// percent *= 2; +// +// r = (int)((1 - percent) * m_waterfallLoColor.red() + percent * m_waterfallMidColor.red()); +// g = (int)((1 - percent) * m_waterfallLoColor.green() + percent * m_waterfallMidColor.green()); +// b = (int)((1 - percent) * m_waterfallLoColor.blue() + percent * m_waterfallMidColor.blue()); +// } +// else { // use a gradient between mid and high colors +// +// percent = (float)(percent - 0.5) * 2; +// +// r = (int)((1 - percent) * m_waterfallMidColor.red() + percent * 255);//m_waterfallHiColor.red()); +// g = (int)((1 - percent) * m_waterfallMidColor.green() + percent * 255);//m_waterfallHiColor.green()); +// b = (int)((1 - percent) * m_waterfallMidColor.blue() + percent * 255);//m_waterfallHiColor.blue()); +// } +// +// if (r > 255) r = 255; +// if (g > 255) g = 255; +// if (b > 255) b = 255; +// color = QColor(r, g, b, m_waterfallAlpha); +// } +// +// break; +// +// case QSDRGraphics::enhanced: +// +// if (value <= lowerThreshold) +// color = m_waterfallLoColor; +// else +// if (value >= upperThreshold) +// color = m_waterfallHiColor; +// else { +// +// offset = value - lowerThreshold; +// globalRange = offset / m_waterfallColorRange; // value from 0.0 to 1.0 where 1.0 is high and 0.0 is low. +// +// if (globalRange < (float)2/9) { // background to blue +// +// localRange = globalRange / ((float)2/9); +// r = (int)((1.0 - localRange) * m_waterfallLoColor.red()); +// g = (int)((1.0 - localRange) * m_waterfallLoColor.green()); +// b = (int)(m_waterfallLoColor.blue() + localRange * (255 - m_waterfallLoColor.blue())); +// } +// else +// if (globalRange < (float)3/9) { // blue to blue-green +// +// localRange = (globalRange - (float)2/9) / ((float)1/9); +// r = 0; +// g = (int)(localRange * 255); +// b = 255; +// } +// else +// if (globalRange < (float)4/9) { // blue-green to green +// +// localRange = (globalRange - (float)3/9) / ((float)1/9); +// r = 0; +// g = 255; +// b = (int)((1.0 - localRange) * 255); +// } +// else +// if (globalRange < (float)5/9) { // green to red-green +// +// localRange = (globalRange - (float)4/9) / ((float)1/9); +// r = (int)(localRange * 255); +// g = 255; +// b = 0; +// } +// else +// if (globalRange < (float)7/9) { // red-green to red +// +// localRange = (globalRange - (float)5/9) / ((float)2/9); +// r = 255; +// g = (int)((1.0 - localRange) * 255); +// b = 0; +// } +// else +// if (globalRange < (float)8/9) { // red to red-blue +// +// localRange = (globalRange - (float)7/9) / ((float)1/9); +// r = 255; +// g = 0; +// b = (int)(localRange * 255); +// } +// else { // red-blue to purple end +// +// localRange = (globalRange - (float)8/9) / ((float)1/9); +// r = (int)((0.75 + 0.25 * (1.0 - localRange)) * 255); +// g = (int)(localRange * 255 * 0.5); +// b = 255; +// } +// if (r > 255) r = 255; +// if (g > 255) g = 255; +// if (b > 255) b = 255; +// if (r < 0) r = 0; +// if (g < 0) g = 0; +// if (b < 0) b = 0; +// color = QColor(r, g, b, m_waterfallAlpha); +// } +// +// break; +// +// case QSDRGraphics::spectran: +// +// break; +// } +// +// return color; +//} + +void QGLDistancePanel::setChirpFFTShow(bool value) { + + distanceSpectrumBufferMutex.lock(); + m_showChirpFFT = value; + distanceSpectrumBufferMutex.unlock(); + + update(); +} + +void QGLDistancePanel::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + Q_UNUSED (hwmode) + Q_UNUSED (state) + + if (m_dataEngineState != state) + m_dataEngineState = state; + + if (m_serverMode != mode) { + + //memset(m_wbSpectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float)); + memset(m_spectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float)); + memset(m_distanceSpectrumBuffer, -10000, 16 * BUFFER_SIZE * sizeof(float)); + m_serverMode = mode; + } + + //resizeGL(width(), height()); + m_displayTime.restart(); + + update(); +} + + +void QGLDistancePanel::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode colorScheme) +{ + Q_UNUSED (sender) + Q_UNUSED (colorScheme) + Q_UNUSED (rx) + + if (m_panMode != panMode) + m_panMode = panMode; + + /*if (m_waterColorScheme != colorScheme) { + + m_waterColorScheme = colorScheme; + change = true; + }*/ + + //if (!change) return; + + update(); +} + + void QGLDistancePanel::setSpectrumAveraging(bool value) { + + spectrumBufferMutex.lock(); + + if (m_spectrumAveraging == value) + return; + else + m_spectrumAveraging = value; + + spectrumBufferMutex.unlock(); + } + +void QGLDistancePanel::setSpectrumAveragingCnt(int value) { + + spectrumBufferMutex.lock(); + + memset(m_tmpBuf, 0, SAMPLE_BUFFER_SIZE * sizeof(float)); + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); + + m_specAveragingCnt = value; + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + + spectrumBufferMutex.unlock(); +} + +void QGLDistancePanel::setPanGridStatus(bool value) { + + spectrumBufferMutex.lock(); + + if (m_panGrid == value) + return; + else + m_panGrid = value; + + spectrumBufferMutex.unlock(); + + update(); +} + +void QGLDistancePanel::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; + update(); +} + +void QGLDistancePanel::setPanadapterColors() { + + m_spectrumColorsChanged = true; + + mutex.lock(); + /*m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0);*/ + + /*if (m_bkgRed * 1.2 > 1.0) m_bkgRed = 1.0f; + if (m_bkgGreen * 1.2 > 1.0) m_bkgGreen = 1.0f; + if (m_bkgBlue * 1.2 > 1.0) m_bkgBlue = 1.0f; + + if (m_bkgRed * 1.6 > 1.0) m_bkgRed = 1.0f; + if (m_bkgGreen * 1.6 > 1.0) m_bkgGreen = 1.0f; + if (m_bkgBlue * 1.6 > 1.0) m_bkgBlue = 1.0f;*/ + + m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0); + m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0); + m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0); + + m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + mutex.unlock(); + + update(); +} + +//void QGLDistancePanel::setWaterfallTime(int rx, int value) { +// +// if (rx == 0) +// m_waterfallTime = value; +//} + +//void QGLDistancePanel::setWaterfallOffesetLo(int rx, int value) { +// +// if (rx == 0) +// m_waterfallOffsetLo = value; +// +// update(); +//} +// +//void QGLDistancePanel::setWaterfallOffesetHi(int rx, int value) { +// +// if (rx = 0) +// m_waterfallOffsetHi = value; +// +// update(); +//} + +void QGLDistancePanel::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void QGLDistancePanel::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} diff --git a/Source/src/GL/cusdr_oglDistancePanel.h b/Source/src/GL/cusdr_oglDistancePanel.h new file mode 100644 index 0000000..d8fc3f0 --- /dev/null +++ b/Source/src/GL/cusdr_oglDistancePanel.h @@ -0,0 +1,318 @@ +/** +* @file cusdr_oglDistancePanel.h +* @brief distance panel header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-14 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_QGL_DISTANCEPANEL_H +#define _CUSDR_QGL_DISTANCEPANEL_H + +#include "cusdr_oglUtils.h" +#include "cusdr_oglInfo.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" +#include "cusdr_oglText.h" + +//#include +//#include +//#include +#include +//#include +//#include + + + +class QGLDistancePanel : public QGLWidget { + + Q_OBJECT + +public: + QGLDistancePanel(QWidget *parent = 0); + ~QGLDistancePanel(); + +public slots: + //QSize minimumSizeHint() const; + QSize sizeHint() const; + + void setSpectrumBuffer(const float *buffer); + void distanceSpectrumBufferChanged(int sampleRate, qint64 length, const float *buffer); + void setFrequency(QObject *sender, bool value, long freq); + +protected: + void initializeGL(); + void resizeGL(int iWidth, int iHeight); + void paintGL(); + + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event ); + void keyPressEvent(QKeyEvent* event); + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void timerEvent(QTimerEvent *); + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + PanGraphicsMode m_panMode; + + QTime m_displayTime; + QTime m_resizeTime; + QTime freqChangeTimer; + + CFonts *fonts; + + TScale m_frequencyScale; + TScale m_dBmScale; + TScale m_distanceScale; + TScale m_dBmDistScale; + TFonts m_fonts; + + QList m_rxDataList; + + QVector m_panadapterBins; + QQueue > specAv_queue; + + QGLFramebufferObject* m_frequencyScaleFBO; + QGLFramebufferObject* m_dBmScaleFBO; + QGLFramebufferObject* m_panadapterGridFBO; + QGLFramebufferObject* m_textureFBO; + + QRect m_panRect; + QRect m_dBmScalePanRect; + QRect m_freqScalePanRect; + QRect m_distancePanRect; + QRect m_freqScaleDistancePanRect; + QRect m_dBmScaleDistancePanRect; + QRect m_filterRect; + QRect m_freqScaleWideBandPanRect; + QRect m_dBmScaleWideBandPanRect; + QRect m_distanceSpectrumRect; + + OGLText* m_oglTextTiny; + OGLText* m_oglTextSmall; + OGLText* m_oglTextNormal; + + QPoint m_mousePos; + QPoint m_oldMousePos; + QPoint m_mouseLastPos; + QPoint m_mouseDownPos; + QPoint m_rulerMouseDownPos; + + enum Region { + + freqScalePanadapterRegion, + freqScaleDistancePanRegion, + panadapterRegion, + dBmScalePanadapterRegion, + dBmScaleDistancePanRegion, + distancePanRegion, + filterRegion, + filterRegionLow, + filterRegionHigh, + elsewhere, + out + }; + + long m_frequency; + long m_oldFreq; + + float m_spectrumBuffer[4*BUFFER_SIZE]; + float m_distanceSpectrumBuffer[16*BUFFER_SIZE]; + + float m_scale; + float m_tmpBuf[SAMPLE_BUFFER_SIZE]; + float m_avgBuf[SAMPLE_BUFFER_SIZE]; + + float m_distMax; + + QMutex mutex; + QMutex spectrumBufferMutex; + QMutex distanceSpectrumBufferMutex; + + int m_oldWidth; + int m_oldPanRectHeight; + int m_smallFontHeight; + int m_cnt; + int m_specAveragingCnt; + int m_freqRulerDisplayWidth; + int m_displayTop; + int m_dBmPanLogGain; + int m_panSpectrumMinimumHeight; + + unsigned int timer; + + GLint m_panRectWidth; + GLint m_panSpectrumBinsLength; + + bool m_spectrumUpdate; + bool m_showZerodBmLine; + bool m_spectrumVertexColorUpdate; + bool m_dBmScalePanadapterRenew; + bool m_dBmScalePanadapterUpdate; + bool m_freqScalePanadapterRenew; + bool m_freqScalePanadapterUpdate; + bool m_panGridRenew; + bool m_panGridUpdate; + bool m_distRulerUpdate; + bool m_newWidebandPanFreqRuler; + bool m_spectrumColorsChanged; + bool m_showChirpFFT; + bool m_spectrumAveraging; + bool m_spectrumAveragingOld; + bool m_crossHairCursor; + bool m_panGrid; + + float m_freqRulerPosition; + float m_wideBandZoomFactor; + double m_distRulerKilometerSpan; + double m_distRulerDisplayDelta; + double m_distRulerDisplayDeltaStep; + double m_distRulerMaxDist; + + qreal m_panFrequencyScale; + qreal m_freqScaleZoomFactor; + qreal m_distScaleZoomFactor; + qreal m_dBmPanMin; + qreal m_dBmPanMax; + qreal m_dBmPanDelta; + qreal m_panScale; + qreal m_scaleMult; + qreal m_scaleMultOld; + qreal m_filterLowerFrequency; + qreal m_filterUpperFrequency; + qreal m_mouseDownFilterFrequencyLo; + qreal m_mouseDownFilterFrequencyHi; + qreal m_dBmDistScaleMin; + qreal m_dBmDistScaleMax; + qreal m_dBmDistMin; + qreal m_dBmDistMax; + qreal m_dBmDistDelta; + + int m_mouseRegion; + int m_oldMouseRegion; + int m_snapMouse; + int m_panDisplayMode; + int m_sampleRate; + int m_downRate; + + + double m_kilometersPerGate; + qint64 m_chirpBufferLength; + + GLfloat m_bkgRed; + GLfloat m_bkgGreen; + GLfloat m_bkgBlue; + + GLfloat m_red; + GLfloat m_green; + GLfloat m_blue; + + GLfloat m_redF; + GLfloat m_greenF; + GLfloat m_blueF; + + + GLfloat m_redST; + GLfloat m_greenST; + GLfloat m_blueST; + + GLfloat m_redSB; + GLfloat m_greenSB; + GLfloat m_blueSB; + + GLfloat m_redD; + GLfloat m_greenD; + GLfloat m_blueD; + + //****************************************************************** + //QColor getWaterfallColorAtPixel(qreal value); + + void saveGLState(); + void restoreGLState(); + + // drawing + void paintReceiverDisplay(); + void paintChirpWSPRDisplay(); + + void drawPanadapter(); + void drawPanVerticalScale(); + void drawPanHorizontalScale(); + void drawPanadapterGrid(); + void drawPanFilter(); + void drawCrossHair(); + + void drawDistanceSpectrum(); + void drawDistHorizontalScale(); + void drawDistVerticalScale(); + + void renderPanVerticalScale(); + void renderPanHorizontalScale(); + void renderPanadapterGrid(); + + void computeDisplayBins(const float *panBuffer); + +private slots: + + void systemStateChanged( + QObject* sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject* sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setupConnections(); + void setFilterFrequencies(QObject *sender, int rx, qreal lo, qreal hi); + void setupDisplayRegions(QSize size); + + void setDistanceSpectrumBuffer(int sampleRate, qint64 length, const float *buffer); + void setSpectrumAveraging(bool value); + void setSpectrumAveragingCnt(int value); + void setPanGridStatus(bool value); + void setPanadapterColors(); + void getRegion(QPoint p); + void freqRulerPositionChanged(float pos, int rx); + void sampleRateChanged(QObject *sender, int value); + void setChirpFFTShow(bool value); + +signals: + void showEvent(QObject* sender); + void closeEvent(QObject* sender); + void messageEvent(QString msg); + void coordChanged(int x,int y); +}; + +#endif // _CUSDR_QGL_DISTANCEPANEL_H diff --git a/Source/src/GL/cusdr_oglInfo.cpp b/Source/src/GL/cusdr_oglInfo.cpp new file mode 100644 index 0000000..8044a3e --- /dev/null +++ b/Source/src/GL/cusdr_oglInfo.cpp @@ -0,0 +1,180 @@ +/** +* @file cusdr_oglInfo.cpp +* @brief OpenGL info class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-11-10 +*/ + +/* + * adapted from glInfo.h of Song Ho Ahn (song.ahn@gmail.com) + * Copyright (c) 2005 Song Ho Ahn + * + * (C) 2011 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#include +#include "cusdr_oglUtils.h" +#include "cusdr_oglInfo.h" + +QOpenGLInfo::QOpenGLInfo(QObject *parent) + : QObject(parent) + , set(Settings::instance()) +{ + m_glInfo.redBits = 0; + m_glInfo.greenBits = 0; + m_glInfo.blueBits = 0; + m_glInfo.alphaBits = 0; + m_glInfo.depthBits = 0; + m_glInfo.stencilBits = 0; + m_glInfo.maxTextureSize = 0; + m_glInfo.maxLights = 0; + m_glInfo.maxAttribStacks = 0; + m_glInfo.maxModelViewStacks = 0; + m_glInfo.maxClipPlanes = 0; + m_glInfo.maxTextureStacks = 0; +} + +QOpenGLInfo::~QOpenGLInfo() { +} + +bool QOpenGLInfo::getInfo() { + + QString str; + + // get vendor string + str = QLatin1String(reinterpret_cast(glGetString(GL_EXTENSIONS))); + if(!str.isNull()) + m_glInfo.vendor = str; + else + return false; + + // get renderer string + str = QLatin1String(reinterpret_cast(glGetString(GL_RENDERER))); + //str = (char*)glGetString(GL_RENDERER); + if(!str.isNull()) + m_glInfo.renderer = str; + else + return false; + + // get version string + str = QLatin1String(reinterpret_cast(glGetString(GL_VERSION))); + str = (char*)glGetString(GL_VERSION); + if(!str.isNull()) + m_glInfo.version = str; + else + return false; + + // get all extensions as a string + str = QLatin1String(reinterpret_cast(glGetString(GL_EXTENSIONS))); + //str = (char*)glGetString(GL_EXTENSIONS); + + // split extensions + if(!str.isNull()) { + + m_glInfo.extensions = str.split(' '); + m_glInfo.extensions.sort(); + } + else + return false; + + // get number of color bits + glGetIntegerv(GL_RED_BITS, &m_glInfo.redBits); + glGetIntegerv(GL_GREEN_BITS, &m_glInfo.greenBits); + glGetIntegerv(GL_BLUE_BITS, &m_glInfo.blueBits); + glGetIntegerv(GL_ALPHA_BITS, &m_glInfo.alphaBits); + + // get depth bits + glGetIntegerv(GL_DEPTH_BITS, &m_glInfo.depthBits); + + // get stecil bits + glGetIntegerv(GL_STENCIL_BITS, &m_glInfo.stencilBits); + + // get max number of lights allowed + glGetIntegerv(GL_MAX_LIGHTS, &m_glInfo.maxLights); + + // get max texture resolution + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &m_glInfo.maxTextureSize); + + // get max number of clipping planes + glGetIntegerv(GL_MAX_CLIP_PLANES, &m_glInfo.maxClipPlanes); + + // get max modelview and projection matrix stacks + glGetIntegerv(GL_MAX_MODELVIEW_STACK_DEPTH, &m_glInfo.maxModelViewStacks); + glGetIntegerv(GL_MAX_PROJECTION_STACK_DEPTH, &m_glInfo.maxProjectionStacks); + glGetIntegerv(GL_MAX_ATTRIB_STACK_DEPTH, &m_glInfo.maxAttribStacks); + + // get max texture stacks + glGetIntegerv(GL_MAX_TEXTURE_STACK_DEPTH, &m_glInfo.maxTextureStacks); + + return true; +} + +bool QOpenGLInfo::isExtensionSupported(const QString &extension) { + + for (int i = 0; i < m_glInfo.extensions.size(); ++i) { + + if (extension == m_glInfo.extensions.at(i)) + return true; + } + return false; +} + +void QOpenGLInfo::printSelf() { + + //std::stringstream ss; + + qDebug() << ""; + qDebug() << "OpenGL Driver Info"; + qDebug() << "=================="; + qDebug() << "Vendor: " << m_glInfo.vendor; + qDebug() << "Version: " << m_glInfo.version; + qDebug() << "Renderer: " << m_glInfo.renderer; + + qDebug() << ""; + qDebug() << "Color Bits(R,G,B,A): (" + << m_glInfo.redBits + << ", " << m_glInfo.greenBits + << ", " << m_glInfo.blueBits + << ", " << m_glInfo.alphaBits + << ")\n"; + + qDebug() << "Depth Bits: " << m_glInfo.depthBits; + qDebug() << "Stencil Bits: " << m_glInfo.stencilBits; + + qDebug() << ""; + qDebug() << "Max Texture Size: " + << m_glInfo.maxTextureSize + << "x" + << m_glInfo.maxTextureSize; + + qDebug() << "Max Lights: " << m_glInfo.maxLights; + qDebug() << "Max Clip Planes: " << m_glInfo.maxClipPlanes; + qDebug() << "Max Modelview Matrix Stacks: " << m_glInfo.maxModelViewStacks; + qDebug() << "Max Projection Matrix Stacks: " << m_glInfo.maxProjectionStacks; + qDebug() << "Max Attribute Stacks: " << m_glInfo.maxAttribStacks; + qDebug() << "Max Texture Stacks: " << m_glInfo.maxTextureStacks; + + qDebug() << ""; + qDebug() << "Total Number of Extensions: " << m_glInfo.extensions.size(); + qDebug() << "=============================="; + + for(int i = 0; i < m_glInfo.extensions.size(); ++i) + qDebug() << m_glInfo.extensions.at(i); + + qDebug() << "======================================================================"; +} diff --git a/Source/src/GL/cusdr_oglInfo.h b/Source/src/GL/cusdr_oglInfo.h new file mode 100644 index 0000000..27c8ed8 --- /dev/null +++ b/Source/src/GL/cusdr_oglInfo.h @@ -0,0 +1,82 @@ +/** +* @file cusdr_oglInfo.h +* @brief OpenGL info header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-11-10 +*/ + +/* + * adapted from glInfo.h of Song Ho Ahn (song.ahn@gmail.com) + * Copyright (c) 2005 Song Ho Ahn + * + * (C) 2011 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_OGLINFO_H +#define _CUSDR_OGLINFO_H + +//#include +//#include +//#include + +#include "cusdr_settings.h" + +// struct variable to store OpenGL info +typedef struct _glinfo { + + QString vendor; + QString renderer; + QString version; + QStringList extensions; + + int redBits; + int greenBits; + int blueBits; + int alphaBits; + int depthBits; + int stencilBits; + int maxTextureSize; + int maxLights; + int maxAttribStacks; + int maxModelViewStacks; + int maxProjectionStacks; + int maxClipPlanes; + int maxTextureStacks; + +} t_glinfo; + + +class QOpenGLInfo : public QObject { + + Q_OBJECT + +public: + QOpenGLInfo(QObject *parent = 0); + ~QOpenGLInfo(); + + bool getInfo(); + void printSelf(); + bool isExtensionSupported(const QString &extension); + +private: + Settings* set; + + t_glinfo m_glInfo; +}; + +#endif // _CUSDR_OGLINFO_H diff --git a/Source/src/GL/cusdr_oglReceiverPanel.cpp b/Source/src/GL/cusdr_oglReceiverPanel.cpp new file mode 100644 index 0000000..be79f11 --- /dev/null +++ b/Source/src/GL/cusdr_oglReceiverPanel.cpp @@ -0,0 +1,4486 @@ +/** +* @file cusdr_oglReceiverPanel.cpp +* @brief Receiver panel class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-03-14 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_GRAPHICS + +// use: GRAPHICS_DEBUG + +#include "cusdr_oglReceiverPanel.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809D +#endif + +#define btn_height 14 +#define btn_width 60 +#define btn_widthb 70 +#define btn_widths 34 + +QGLReceiverPanel::QGLReceiverPanel(QWidget *parent, int rx) + : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent) + + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_mousePos(QPoint(-1, -1)) + , m_mouseDownPos(QPoint(-1, -1)) + , m_panSpectrumBinsLength(0) + , m_filterLeft(0) + , m_filterRight(0) + , m_filterTop(0) + , m_filterBottom(0) + , m_receiver(rx) + //, m_frequencyRxOnRx(0) + , m_spectrumSize(set->getSpectrumSize()) + , m_sampleSize(0) + , m_oldSampleSize(0) + , m_specAveragingCnt(set->getSpectrumAveragingCnt(m_receiver)) + , m_currentReceiver(set->getCurrentReceiver()) + , m_waterfallAlpha(255) + , m_freqRulerDisplayWidth(0) + , m_oldWaterfallWidth(0) + , m_panSpectrumMinimumHeight(0) + , m_snapMouse(3) + , m_sampleRate(set->getSampleRate()) + , m_downRate(set->getChirpDownSampleRate()) + , m_adcStatus(0) + , m_fftMult(1) + , m_smallSize(true) + , m_spectrumVertexColorUpdate(false) + , m_spectrumColorsChanged(true) + , m_spectrumAveraging(set->getSpectrumAveraging(m_receiver)) + //, m_spectrumAveragingOld(m_spectrumAveraging) + , m_crossHair(set->getHairCrossStatus(m_receiver)) + , m_crossHairCursor(false) + , m_panGrid(set->getPanGridStatus(m_receiver)) + , m_peakHold(false) + , m_filterChanged(true) + , m_showFilterLeftBoundary(false) + , m_showFilterRightBoundary(false) + , m_highlightFilter(false) + , m_peakHoldBufferResize(true) + , m_dragMouse(false) + , m_panLocked(set->getPanLockedStatus(m_receiver)) + , m_clickVFO(set->getClickVFOStatus(m_receiver)) + , m_freqScaleZoomFactor(1.0f) + , m_scaleMult(1.0f) + , m_filterLowerFrequency(-3050.0) + , m_filterUpperFrequency(-150.0) + //, m_freqRulerPosition(0.5) +{ +// QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + setAutoBufferSwap(true); + setAutoFillBackground(false); + + setMouseTracking(true); + setFocusPolicy(Qt::StrongFocus); + + //GRAPHICS_DEBUG << "set spectrum buffer size to: " << m_spectrumSize; + + m_bigHeight = 600; + m_bigWidth = 1000; + + setupDisplayRegions(size()); + m_oldWidth = size().width(); + + m_rxDataList = set->getReceiverDataList(); + m_freqRulerPosition = m_rxDataList.at(m_receiver).freqRulerPosition; + m_centerFrequency = m_rxDataList.at(m_receiver).ctrFrequency; + m_vfoFrequency = m_rxDataList.at(m_receiver).vfoFrequency; + + if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + else + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + m_dBmScalePanadapterRenew = true; + m_dBmScalePanadapterUpdate = true; + m_freqScalePanadapterRenew = true; + m_freqScalePanadapterUpdate = true; + m_panGridRenew = true; + m_panGridUpdate = true; + m_waterfallUpdate = true; + m_secScaleWaterfallUpdate = true; + m_secScaleWaterfallRenew = true; + m_waterfallDisplayUpdate = true; + + m_panMode = m_rxDataList.at(m_receiver).panMode; + m_waterfallMode = m_rxDataList.at(m_receiver).waterfallMode; + + HamBand band = m_rxDataList.at(m_receiver).hamBand; + + m_dBmPanMin = m_rxDataList.at(m_receiver).dBmPanScaleMinList.at(band); + m_dBmPanMax = m_rxDataList.at(m_receiver).dBmPanScaleMaxList.at(band); + + m_waterfallOffsetLo = m_rxDataList.at(m_receiver).waterfallOffsetLo; + m_waterfallOffsetHi = m_rxDataList.at(m_receiver).waterfallOffsetHi; + + m_secWaterfallMin = 0.0; + m_secWaterfallMax = 0.0; + + m_filterLowerFrequency = m_rxDataList.at(m_receiver).filterLo; + m_filterUpperFrequency = m_rxDataList.at(m_receiver).filterHi; + m_filterWidth = qAbs((int)(m_filterUpperFrequency - m_filterLowerFrequency)); + + m_mouseWheelFreqStep = m_rxDataList.at(m_receiver).mouseWheelFreqStep; + + m_agcMode = m_rxDataList.at(m_receiver).agcMode; + m_agcModeString = set->getAGCModeString(m_receiver); + m_agcFixedGain = m_rxDataList.at(m_receiver).agcFixedGain_dB; + + m_dspModeString = set->getDSPModeString(m_rxDataList.at(m_receiver).dspModeList.at(m_receiver)); +// m_agcThresholdOld = m_rxDataList.at(m_receiver).acgThreshold; +// m_agcThresholdNew = m_agcThresholdOld; +// m_agcHangLevelOld = m_rxDataList.at(m_receiver).agcHangLevel; +// m_agcHangLevelNew = m_agcHangLevelOld; + + m_agcHangEnabled = m_rxDataList.at(m_receiver).hangEnabled; + m_showAGCLines = m_rxDataList.at(m_receiver).agcLines; + + averager = new DualModeAverager(m_receiver, m_spectrumSize); + radioPopup = new RadioPopupWidget(this, m_receiver); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_fonts.smallFont.setBold(true); + m_fonts.bigFont1.setBold(false); + m_fonts.bigFont2.setBold(false); + + m_oglTextTiny = new OGLText(m_fonts.tinyFont); + m_oglTextSmall = new OGLText(m_fonts.smallFont); + m_oglTextNormal = new OGLText(m_fonts.normalFont); + m_oglTextFreq1 = new OGLText(m_fonts.freqFont1); + m_oglTextFreq2 = new OGLText(m_fonts.freqFont2); + m_oglTextBig1 = new OGLText(m_fonts.bigFont1); + m_oglTextBig2 = new OGLText(m_fonts.bigFont2); + m_oglTextHuge = new OGLText(m_fonts.hugeFont); + + timer = 0; + + setupConnections(); + + m_displayTime.start(); + m_resizeTime.start(); + peakHoldTimer.start(); + //freqChangeTimer.start(); + + m_fps = set->getFramesPerSecond(m_receiver); + m_secWaterfallMin = -(1.0/m_fps) * m_secScaleWaterfallRect.height(); + + + m_dBmPanLogGain = 47;//49;//69 // allow user to calibrate this value + + m_cameraDistance = 0; + m_cameraAngle = QPoint(0, 0); + + m_mousePos = QPoint(-100, -100); + + m_gridColor = set->getPanadapterColors().gridLineColor; + m_darkColor = QColor(150, 150, 150, 100); + + m_redGrid = (GLfloat)(m_gridColor.red()/256.0); + m_greenGrid = (GLfloat)(m_gridColor.green()/256.0); + m_blueGrid = (GLfloat)(m_gridColor.blue()/256.0); + + m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0); + + m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0); + m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0); + m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0); + + m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + m_waterfallLoColor = QColor(0, 0, 0, m_waterfallAlpha); + m_waterfallHiColor = QColor(192, 124, 255, m_waterfallAlpha); + m_waterfallMidColor = set->getPanadapterColors().waterfallColor.toRgb(); + m_waterfallColorRange = (int)(m_dBmPanMax - m_dBmPanMin); + + m_frequencyScaleFBO = 0; + m_dBmScaleFBO = 0; + m_panadapterGridFBO = 0; + m_textureFBO = 0; + m_waterfallLineFBO = 0; + m_waterfallFBO = 0; + m_secScaleWaterfallFBO = 0; + + m_waterfallLineCnt = 0; + + m_haircrossOffsetRight = 30; + m_haircrossOffsetLeft = 116; + m_haircrossMaxRight = 110; + m_haircrossMinTop = 40; + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + +} + +QGLReceiverPanel::~QGLReceiverPanel() { + + disconnect(set, 0, this, 0); + + makeCurrent(); + glFinish(); + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + if (m_waterfallLineFBO) { + + delete m_waterfallLineFBO; + m_waterfallLineFBO = 0; + } + + if (m_waterfallFBO) { + + delete m_waterfallFBO; + m_waterfallFBO = 0; + } + + if (m_textureFBO) { + + delete m_textureFBO; + m_textureFBO = 0; + } + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + + if (m_panadapterGridFBO) { + + delete m_panadapterGridFBO; + m_panadapterGridFBO = 0; + } + + if (m_secScaleWaterfallFBO) { + + delete m_secScaleWaterfallFBO; + m_secScaleWaterfallFBO = 0; + } + + if (averager) + delete averager; + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); +} + +QSize QGLReceiverPanel::minimumSizeHint() const { + + if (m_receiver == 0) + return QSize(width(), 250); + else + return QSize(250, 120); + //return QSize(width(), height()); +} + +QSize QGLReceiverPanel::sizeHint() const { + + return QSize(width(), height()); +} + +void QGLReceiverPanel::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(spectrumSizeChanged(QObject *, int)), +// this, +// SLOT(setSpectrumSize(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(freqRulerPositionChanged(QObject *, int, float)), + this, + SLOT(freqRulerPositionChanged(QObject *, int, float))); + + CHECKED_CONNECT( + set, + SIGNAL(ctrFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setCtrFrequency(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setVFOFrequency(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(hamBandChanged(QObject *, int, bool, HamBand)), + this, + SLOT(setHamBand(QObject *, int, bool, HamBand))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)), + this, + SLOT(setFilterFrequencies(QObject *, int, qreal, qreal))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(waterfallTimeChanged(int, int)), +// this, +// SLOT(setWaterfallTime(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallOffesetLoChanged(int, int)), + this, + SLOT(setWaterfallOffesetLo(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(waterfallOffesetHiChanged(int, int)), + this, + SLOT(setWaterfallOffesetHi(int, int))); + + CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingChanged(QObject *, int, bool)), + this, + SLOT(setSpectrumAveraging(QObject *, int, bool))); + + /*CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingCntChanged(int)), + this, + SLOT(setSpectrumAveragingCnt(int)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(spectrumBufferChanged(int, const qVectorFloat&)), + this, + SLOT(setSpectrumBuffer(int, const qVectorFloat&))); + + CHECKED_CONNECT( + set, + SIGNAL(panGridStatusChanged(bool, int)), + this, + SLOT(setPanGridStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(peakHoldStatusChanged(bool, int)), + this, + SLOT(setPeakHoldStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(panLockedStatusChanged(bool, int)), + this, + SLOT(setPanLockedStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(clickVFOStatusChanged(bool, int)), + this, + SLOT(setClickVFOStatus(bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(hairCrossStatusChanged(bool, int)), + this, + SLOT(setHairCrossStatus(bool, int))); + + /*CHECKED_CONNECT( + set, + SIGNAL(panadapterColorChanged()), + this, + SLOT(setSimpleWaterfallColor()));*/ + + CHECKED_CONNECT( + set, + SIGNAL(panadapterColorChanged()), + this, + SLOT(setPanadapterColors())); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(setMercuryAttenuator(QObject *, HamBand, int))); + + CHECKED_CONNECT( + set, + SIGNAL(adcOverflowChanged(int)), + this, + SLOT(setADCStatus(int))); + + CHECKED_CONNECT( + set, + SIGNAL(framesPerSecondChanged(QObject*, int, int)), + this, + SLOT(setFramesPerSecond(QObject*, int, int))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(agcThresholdLine_dBmChanged(QObject *, int, qreal)), +// this, +// SLOT(setAGCThresholdLine_dBm(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcFixedGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCLineFixedLevel(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcLineLevelsChanged(QObject *, int, qreal, qreal)), + this, + SLOT(setAGCLineLevels(QObject *, int, qreal, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcModeChanged(QObject *, int, AGCMode, bool)), + this, + SLOT(setAGCMode(QObject *, int, AGCMode, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(showAGCLinesStatusChanged(QObject *, bool, int)), + this, + SLOT(setAGCLinesStatus(QObject *, bool, int))); + + CHECKED_CONNECT( + set, + SIGNAL(dspModeChanged(QObject *, int, DSPMode)), + this, + SLOT(setDSPMode(QObject *, int, DSPMode))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(agcHangEnabledChanged(QObject *, int, bool)), +// this, +// SLOT(setAGCHangEnabled(QObject *, int, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(mouseWheelFreqStepChanged(QObject *, int, qreal)), + this, + SLOT(setMouseWheelFreqStep(QObject *, int, qreal))); + + CHECKED_CONNECT( + radioPopup, + SIGNAL(vfoToMidBtnEvent()), + this, + SLOT(setVfoToMidFrequency())); + + CHECKED_CONNECT( + radioPopup, + SIGNAL(midToVfoBtnEvent()), + this, + SLOT(setMidToVfoFrequency())); +} + +void QGLReceiverPanel::initializeGL() { + + if (!isValid()) return; + + + /*QOpenGLInfo glInfo; + glInfo.getInfo(); + glInfo.printSelf();*/ + + //***************************************************************** + // default initialization + + //glShadeModel(GL_FLAT); + glShadeModel(GL_SMOOTH); + //glClearColor(0.0f, 0.0f, 0.0f, 0.5f); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + //glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + m_cnt = 0; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +void QGLReceiverPanel::paintGL() { + + switch (m_serverMode) { + + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + case QSDR::NoServerMode: + case QSDR::DemoMode: + + drawGLRect(QRect(0, 0, width(), height()), QColor(0, 0, 0)); + break; + + case QSDR::SDRMode: + + //if (freqChangeTimer.elapsed() > 50) m_spectrumAveraging = m_spectrumAveragingOld; + + if (m_resizeTime.elapsed() > 200 || m_dataEngineState == QSDR::DataEngineDown) + paintReceiverDisplay(); + + break; + } +} + +void QGLReceiverPanel::paintReceiverDisplay() { + + QRect mouse_rect(0, 0, 100, 100); + mouse_rect.moveCenter(m_mousePos); + + if (m_filterChanged) { + + m_filterLo = m_filterLowerFrequency / m_sampleRate; + m_filterHi = m_filterUpperFrequency / m_sampleRate; + m_filterWidth = qAbs((int)(m_filterUpperFrequency - m_filterLowerFrequency)); + + if (m_filterWidth < 1000) { + + QString str = "%1"; + m_filterWidthString = str.arg(m_filterWidth); + } + else { + + QString str = "%1k%2"; + m_filterWidthString = str.arg((int)(m_filterWidth/1000)).arg((int)((m_filterWidth%1000)/100)); + } + + m_filterChanged = false; + } + //m_displayTime.restart(); + + drawPanadapter(); + drawPanHorizontalScale(); + drawPanVerticalScale(); + drawPanadapterGrid(); + drawCenterLine(); + drawPanFilter(); + + if (m_dataEngineState == QSDR::DataEngineUp && m_showAGCLines && (m_receiver == m_currentReceiver)) + drawAGCControl(); + + if (m_panRect.width() > 300 && m_panRect.height() > 80) { + + drawVFOControl(); + drawReceiverInfo(); + } + + if (m_waterfallDisplayUpdate && m_waterfallRect.height() > 10) { + + drawWaterfall(); + drawWaterfallVerticalScale(); + m_waterfallDisplayUpdate = false; + } + + if (m_crossHair) { + + if (m_mouseRegion != freqScalePanadapterRegion && + m_mouseRegion != dBmScalePanadapterRegion && + m_mouseRegion != filterRegion && + m_mouseRegion != filterRegionLow && + m_mouseRegion != filterRegionHigh && + m_mouseRegion != agcThresholdLine && + m_mouseRegion != agcHangLine && + m_mouseRegion != agcFixedGainLine && + m_crossHairCursor) + drawCrossHair(); + } + } + +void QGLReceiverPanel::paint3DPanadapterMode() { +} + +void QGLReceiverPanel::drawPanadapter() { + + GLint vertexArrayLength = (GLint)m_panadapterBins.size(); + + GLint height = m_panRect.height(); + GLint x1 = m_panRect.left(); + GLint y1 = m_panRect.top(); + //GLint y3 = y1 - m_displayTop; + GLint x2 = x1 + m_panRect.width(); + GLint y2 = y1 + m_panRect.height(); + + // y scale + float yScale; + //float yScaleColor; + float yTop; + + qreal dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin); + + yScale = m_panRect.height() / dBmRange; + //yScaleColor = 1.0f / dBmRange; + //yScaleColor = 0.05f * yScale; + yTop = (float) y2; + + if (m_dataEngineState == QSDR::DataEngineUp) + glClear(GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_MULTISAMPLE); + glEnable(GL_LINE_SMOOTH); + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glLineWidth(1); + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) { + +// glBegin(GL_TRIANGLE_STRIP); +// glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner +// glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner +// glColor3f(0.8f * m_bkgRed, 0.8f * m_bkgGreen, 0.8f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner +// glColor3f( m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner +// glEnd(); + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.8f * m_bkgRed, 0.8f * m_bkgGreen, 0.8f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(0.6f * m_bkgRed, 0.6f * m_bkgGreen, 0.6f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + } + else { + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + } + + if (m_adcStatus == 2) { + + glBegin(GL_TRIANGLE_STRIP); + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + + QString str = "ADC Overload"; + int rectWidth = m_fonts.hugeFontMetrics->boundingRect(str).width(); + + qglColor(QColor(255, 0, 0, 155)); + m_oglTextHuge->renderText((x2-rectWidth)/2, y1+30, -3.5f, str); + } + } + else { + + drawGLRect(m_panRect, QColor(30, 30, 50, 155), -4.0f); + } + + // set a scissor box + glScissor(x1, size().height() - y2, x2, height); + glEnable(GL_SCISSOR_TEST); + + spectrumBufferMutex.lock(); + + TGL3float *vertexArray = new TGL3float[vertexArrayLength]; + TGL3float *vertexColorArray = new TGL3float[vertexArrayLength]; + + TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength]; + TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength]; + + TGL3float *vertexArrayBgPH = new TGL3float[2*vertexArrayLength]; + TGL3float *vertexColorArrayBgPH = new TGL3float[2*vertexArrayLength]; + + TGL3float *vertexArrayPH = new TGL3float[vertexArrayLength]; + TGL3float *vertexColorArrayPH = new TGL3float[vertexArrayLength]; + + switch (m_panMode) { + + case (PanGraphicsMode) FilledLine: + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + vertexColorArrayBg[2*i].x = 0.7 * m_redF; + vertexColorArrayBg[2*i].y = 0.7 * m_greenF; + vertexColorArrayBg[2*i].z = 0.7 * m_blueF; + + vertexColorArrayBg[2*i+1].x = 0.3 * m_redF; + vertexColorArrayBg[2*i+1].y = 0.3 * m_greenF; + vertexColorArrayBg[2*i+1].z = 0.3 * m_blueF; + + if (!m_peakHold) { + + vertexColorArray[i].x = m_red; + vertexColorArray[i].y = m_green; + vertexColorArray[i].z = m_blue; + + /*vertexColorArray[i].x = m_red * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].y = m_green * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].z = m_blue * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin));*/ + } + else { + + vertexColorArray[i].x = 0.7f; + vertexColorArray[i].y = 0.7f; + vertexColorArray[i].z = 0.7f; + + vertexColorArrayPH[i].x = m_red; + vertexColorArrayPH[i].y = m_green; + vertexColorArrayPH[i].z = m_blue; + + /*vertexColorArray[i].x = m_red * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].y = m_green * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].z = m_blue * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin));*/ + } + mutex.unlock(); + + vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i].z = -1.5; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + vertexArrayBg[2*i+1].z = -1.5; + + /*vertexArray[i].x = (GLfloat)(i/m_scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArray[i].z = -1.0;*/ + + if (m_peakHold) { + + vertexArrayPH[i].x = (GLfloat)(i/m_scaleMult); + vertexArrayPH[i].y = (GLfloat)(yTop - yScale * m_panPeakHoldBins.at(i)); + vertexArrayPH[i].z = -0.5; + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*vertexArrayLength); + + if (m_peakHold) { + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayPH); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayPH); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + } + else { + + glVertexPointer(3, GL_FLOAT, 6*sizeof(float), vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + break; + + case (PanGraphicsMode) Line: + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + if (!m_peakHold) { + + vertexColorArray[i].x = m_red; + vertexColorArray[i].y = m_green; + vertexColorArray[i].z = m_blue; + + /*vertexColorArray[i].x = m_red * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].y = m_green * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin)); + vertexColorArray[i].z = m_blue * (yScaleColor * (m_panadapterBins.at(i) - m_dBmPanMin));*/ + + /*vertexColorArray[i].x = m_red * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].y = m_green * (yScaleColor * m_panadapterBins.at(i)); + vertexColorArray[i].z = m_blue * (yScaleColor * m_panadapterBins.at(i));*/ + } + else { + + vertexColorArray[i].x = 0.6f; + vertexColorArray[i].y = 0.6f; + vertexColorArray[i].z = 0.6f; + + vertexColorArrayPH[i].x = m_red; + vertexColorArrayPH[i].y = m_green; + vertexColorArrayPH[i].z = m_blue; + } + mutex.unlock(); + + vertexArray[i].x = (GLfloat)(i/m_scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArray[i].z = -1.0; + + if (m_peakHold) { + + vertexArrayPH[i].x = (GLfloat)(i/m_scaleMult); + vertexArrayPH[i].y = (GLfloat)(yTop - yScale * m_panPeakHoldBins.at(i)); + vertexArrayPH[i].z = -0.5; + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + if (m_peakHold) { + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayPH); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayPH); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + break; + + case (PanGraphicsMode) Solid: + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + for (int i = 0; i < vertexArrayLength; i++) { + + mutex.lock(); + if (!m_peakHold) { + + vertexColorArrayBg[2*i].x = m_redST; + vertexColorArrayBg[2*i].y = m_greenST; + vertexColorArrayBg[2*i].z = m_blueST; + + vertexColorArrayBg[2*i+1].x = m_redSB; + vertexColorArrayBg[2*i+1].y = m_greenSB; + vertexColorArrayBg[2*i+1].z = m_blueSB; + } + else { + + vertexColorArrayBg[2*i].x = m_redSB; + vertexColorArrayBg[2*i].y = m_greenSB; + vertexColorArrayBg[2*i].z = m_blueSB; + + vertexColorArrayBg[2*i+1].x = m_redSB; + vertexColorArrayBg[2*i+1].y = m_greenSB; + vertexColorArrayBg[2*i+1].z = m_blueSB; + + vertexColorArrayBgPH[2*i].x = 0.9f;//m_redST; + vertexColorArrayBgPH[2*i].y = 0.9f;//m_greenST; + vertexColorArrayBgPH[2*i].z = 0.9f;//m_blueST; + + vertexColorArrayBgPH[2*i+1].x = 0.9f;// * m_redSB; + vertexColorArrayBgPH[2*i+1].y = 0.9f;// * m_greenSB; + vertexColorArrayBgPH[2*i+1].z = 0.9f;// * m_blueSB; + } + mutex.unlock(); + + vertexArrayBg[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i].z = -1.0f; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + //vertexArrayBg[2*i+1].y = (GLfloat)(m_panRect.bottom()); + //vertexArrayBg[2*i].y = (GLfloat)(yScale * m_panadapterBins.at(i)); + vertexArrayBg[2*i+1].z = -1.0f; + + if (m_peakHold) { + + vertexArrayBgPH[2*i].x = (GLfloat)(i/m_scaleMult); + vertexArrayBgPH[2*i].y = (GLfloat)(yTop - yScale * m_panPeakHoldBins.at(i)); + vertexArrayBgPH[2*i].z = -2.0f; + + vertexArrayBgPH[2*i+1].x = (GLfloat)(i/m_scaleMult); + vertexArrayBgPH[2*i+1].y = (GLfloat)yTop; + vertexArrayBgPH[2*i+1].z = -2.0f; + } + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + //glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength); + glDrawArrays(GL_LINES, 0, 2*vertexArrayLength); + + if (m_peakHold) { + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBgPH); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBgPH); + glDrawArrays(GL_LINES, 0, 2*vertexArrayLength); + } + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + break; + } + spectrumBufferMutex.unlock(); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + delete[] vertexArrayBgPH; + delete[] vertexColorArrayBgPH; + delete[] vertexArrayPH; + delete[] vertexColorArrayPH; + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + // disable scissor box + glDisable(GL_SCISSOR_TEST); +} + +void QGLReceiverPanel::drawPanVerticalScale() { + + if (!m_dBmScalePanRect.isValid()) return; + + int width = m_dBmScalePanRect.width(); + int height = m_dBmScalePanRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_dBmScaleFBO || m_dBmScalePanadapterUpdate || m_dBmScalePanadapterRenew) { + + if (!m_dBmScaleFBO || m_dBmScalePanadapterRenew) { + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + m_dBmScaleFBO = new QGLFramebufferObject(width, height); + //if (m_dBmScaleFBO) + // GRAPHICS_DEBUG << "m_dBmScaleFBO generated."; + + } + + m_dBmScaleFBO->bind(); + renderPanVerticalScale(); + m_dBmScaleFBO->release(); + + m_dBmScalePanadapterUpdate = false; + m_dBmScalePanadapterRenew = false; + } + + renderTexture(m_dBmScalePanRect, m_dBmScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLReceiverPanel::drawPanHorizontalScale() { + + if (!m_freqScalePanRect.isValid()) return; + + int width = m_freqScalePanRect.width(); + int height = m_freqScalePanRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_frequencyScaleFBO || m_freqScalePanadapterUpdate || m_freqScalePanadapterRenew) { + + if (!m_frequencyScaleFBO || m_freqScalePanadapterRenew) { + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + m_frequencyScaleFBO = new QGLFramebufferObject(width, height); + //if (m_frequencyScaleFBO) + // GRAPHICS_DEBUG << "m_frequencyScaleFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_frequencyScaleFBO->bind(); + renderPanHorizontalScale(); + m_frequencyScaleFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + m_freqScalePanadapterUpdate = false; + m_freqScalePanadapterRenew = false; + } + + renderTexture(m_freqScalePanRect, m_frequencyScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLReceiverPanel::drawPanadapterGrid() { + + if (!m_panGrid) return; + + int width = m_panRect.width(); + int height = m_panRect.height(); + + //glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_BLEND); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + + if (m_receiver == m_currentReceiver) + glColor4f(m_redGrid, m_greenGrid, m_blueGrid, 1.0f); + else + glColor4f(m_redGrid, m_greenGrid, m_blueGrid, 0.8f); + + + glDisable(GL_MULTISAMPLE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_panadapterGridFBO || m_panGridUpdate || m_panGridRenew) { + + if (!m_panadapterGridFBO || m_panGridRenew) { + + if (m_panadapterGridFBO) { + + delete m_panadapterGridFBO; + m_panadapterGridFBO = 0; + } + + m_panadapterGridFBO = new QGLFramebufferObject(width, height); + //if (m_panadapterGridFBO) + // GRAPHICS_DEBUG << "m_panadapterGridFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_panadapterGridFBO->bind(); + renderPanadapterGrid(); + m_panadapterGridFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + m_panGridUpdate = false; + m_panGridRenew = false; + } + + renderTexture(m_panRect, m_panadapterGridFBO->texture(), -3.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); + glEnable(GL_MULTISAMPLE); +} + +void QGLReceiverPanel::drawCenterLine() { + + // draw a line for the center frequency + GLint y1, y2; + + y1 = m_panRect.top(); + y2 = m_displayCenterlineHeight; + + if (y2 > y1 + 3) { + + GLint x = m_panRect.width()/2; + GLint y = m_panRect.top() + m_panRect.height() - 1; + //GLint y = m_panRect.top() + m_panRect.height() + m_freqScalePanRect.height() + m_waterfallRect.height() - 1; + //color = set->getPanadapterColors().panCenterLineColor; + QColor col = QColor(80, 180, 240, 180); + + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + glColor4ub(col.red(), col.green(), col.blue(), col.alpha()); + + // center frequency line + glBegin(GL_LINES); + glVertex3f(x, y1 + 1, 3.5f); + glVertex3f(x, y - 1, 3.5f); + glEnd(); + + x = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) - m_deltaF * m_panRect.width() / m_freqScaleZoomFactor); + col = set->getPanadapterColors().panCenterLineColor; + glColor4ub(col.red(), col.green(), col.blue(), 255); + + // VFO frequency line + if (m_dragMouse && !m_panLocked) { + + //glLineWidth(3); + glBegin(GL_LINES); + glVertex3f(x, m_freqScalePanRect.bottom() + 1, 3.0f); + glVertex3f(x, m_freqScalePanRect.bottom() + m_waterfallRect.height() - 1, 3.0f); + glEnd(); + } + glBegin(GL_LINES); + glVertex3f(x, y1 + 1, 4.0f); + glVertex3f(x, y - 1, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + } + + // draw a frequency line from a different receiver + /*if (m_frequencyRxOnRx != 0) { + + y1 = m_waterfallRect.top(); + y2 = m_waterfallRect.bottom(); + + if (y2 > y1 + 3) { + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + qreal df = m_centerFrequency - m_rxDataList.at(m_frequencyRxOnRx%10 - 1).frequency; + + GLint dx = (GLint)(df/unit); + GLint x = m_panRect.width()/2 - dx; + + color = QColor(255, 255, 0, 255); + + glDisable(GL_MULTISAMPLE); + glLineWidth(2); + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + glBegin(GL_LINES); + glVertex3f(x-1, y1, 4.0f); + glVertex3f(x-1, y2, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + } + }*/ +} + +void QGLReceiverPanel::drawPanFilter() { + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + QColor color; + //QString str; + + if (m_highlightFilter) + color = QColor(150, 150, 150, 140); + else + color = QColor(150, 150, 150, 100); + + m_filterLeft = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + (m_filterLo - m_deltaF) * m_panRect.width() / m_freqScaleZoomFactor); + m_filterRight = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) + (m_filterHi - m_deltaF) * m_panRect.width() / m_freqScaleZoomFactor); + m_filterTop = m_panRect.top() + 1; + m_filterBottom = m_panRect.top() + m_panRect.height() - 1; + //m_filterBottom = m_panRect.top() + m_panRect.height() + m_freqScalePanRect.height() + m_waterfallRect.height() - 1; + + m_filterRect = QRect(m_filterLeft, m_filterTop, m_filterRight - m_filterLeft, m_filterBottom - m_filterTop); + + if ((m_filterLeft >= m_panRect.left() && m_filterLeft <= m_panRect.right()) || + (m_filterRight >= m_panRect.left() && m_filterRight <= m_panRect.right()) || + (m_filterLeft < m_panRect.left() && m_filterRight > m_panRect.right())) + { + if (m_filterRect.height() > 5) drawGLRect(m_filterRect, color, 0.0f); + } + + // filter boundaries + if (m_showFilterLeftBoundary) { + + color = QColor(150, 150, 150, 230); + + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + qglColor(color); + glBegin(GL_LINES); + glVertex3f(m_filterLeft, m_filterTop, 4.0f); + glVertex3f(m_filterLeft, m_filterBottom, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + + // text + QString str1 = QString("Filter Lo"); + QString str2 = frequencyString(m_filterLowerFrequency, true); + + qglColor(QColor(0, 0, 0, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterLeft + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextSmall->renderText(m_filterLeft + 5, m_filterTop + 64, 4.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterLeft + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextBig1->renderText(m_filterLeft + 5, m_filterTop + 64, 4.0f, str2); + } + + qglColor(QColor(255, 255, 255, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterLeft + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextSmall->renderText(m_filterLeft + 3, m_filterTop + 62, 5.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterLeft + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextBig1->renderText(m_filterLeft + 3, m_filterTop + 62, 5.0f, str2); + } + } + + if (m_showFilterRightBoundary) { + + color = QColor(150, 150, 150, 230); + + glDisable(GL_MULTISAMPLE); + glLineWidth(1); + qglColor(color); + glBegin(GL_LINES); + glVertex3f(m_filterRight, m_filterTop, 4.0f); + glVertex3f(m_filterRight, m_filterBottom, 4.0f); + glEnd(); + glEnable(GL_MULTISAMPLE); + + // text + QString str1 = QString("Filter Hi"); + QString str2 = frequencyString(m_filterUpperFrequency, true); + + qglColor(QColor(0, 0, 0, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterRight + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextSmall->renderText(m_filterRight + 5, m_filterTop + 64, 4.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterRight + 5, m_filterTop + 44, 4.0f, str1); + m_oglTextBig1->renderText(m_filterRight + 5, m_filterTop + 64, 4.0f, str2); + } + + qglColor(QColor(255, 255, 255, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(m_filterRight + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextSmall->renderText(m_filterRight + 3, m_filterTop + 62, 5.0f, str2); + } + else { + + m_oglTextBig1->renderText(m_filterRight + 3, m_filterTop + 42, 5.0f, str1); + m_oglTextBig1->renderText(m_filterRight + 3, m_filterTop + 62, 5.0f, str2); + + } + } +} + +void QGLReceiverPanel::drawWaterfall() { + + if (m_waterfallRect.isEmpty()) return; + + int top = m_waterfallRect.top(); + int left = m_waterfallRect.left(); + int width = m_waterfallRect.width(); + int height = m_waterfallRect.height(); + //int height = this->size().height(); + + + glColor4f(1.0, 1.0, 1.0, 1.0); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + // check for framebuffer objects + if (set->getFBOPresence()) { + + // create the FBOs if not exist + if (!m_textureFBO || !m_waterfallLineFBO || !m_waterfallFBO || m_waterfallUpdate) { + + if (m_waterfallLineFBO) { + + delete m_waterfallLineFBO; + m_waterfallLineFBO = 0; + } + + if (m_waterfallFBO) { + + delete m_waterfallFBO; + m_waterfallFBO = 0; + } + + if (m_textureFBO) { + + delete m_textureFBO; + m_textureFBO = 0; + } + + if (QGLFramebufferObject::hasOpenGLFramebufferBlit()) { + + //QGLFramebufferObjectFormat format; + //format.setSamples(2); + //format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + + m_waterfallLineFBO = new QGLFramebufferObject(width, 1); + //if (m_waterfallLineFBO) + //GRAPHICS_DEBUG << "m_waterfallLineFBO generated."; + + m_waterfallFBO = new QGLFramebufferObject(width, height); + //if (m_waterfallFBO) + //GRAPHICS_DEBUG << "m_waterfallFBO generated."; + + m_textureFBO = new QGLFramebufferObject(width, height); + //if (m_textureFBO) + //GRAPHICS_DEBUG << "m_textureFBO generated."; + + } + else { + + GRAPHICS_DEBUG << "has no OpenGL FramebufferBlit"; + } + + m_waterfallUpdate = false; + drawGLRect(m_waterfallRect, Qt::black); + + m_waterfallLineCnt = 0; + + if (width > 0) { + + m_waterfallPixel.clear(); + m_waterfallPixel.resize(width); + + TGL_ubyteRGBA col; + col.red = 0; col.green = 0; col.blue = 0; col.alpha = 255; + + for (int i = 0; i < width; i++) + m_waterfallPixel[i] = col; + } + } + + if (m_dataEngineState == QSDR::DataEngineUp) { + + GLint oldTex; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex); + + m_waterfallLineFBO->bind(); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, m_waterfallPixel.data()); + m_waterfallLineFBO->release(); + + m_waterfallLineCnt++; + if (m_waterfallLineCnt > height) m_waterfallLineCnt = height; + + // draw the waterfall + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_waterfallFBO->texture()); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(left, top); // top left corner + glTexCoord2f(1, 1); glVertex2i(left + width, top); // top right corner + glTexCoord2f(1, 0); glVertex2i(left + width, top + height); // bottom right corner + glTexCoord2f(0, 0); glVertex2i(left, top + height); // bottom left corner + glEnd(); + glBindTexture(GL_TEXTURE_2D, oldTex); + glDisable(GL_TEXTURE_2D); + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // render to the next waterfall texture + m_textureFBO->bind(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, m_waterfallFBO->texture()); + + // the waterfall FBO + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(0, 1); // top left corner + glTexCoord2f(1, 1); glVertex2i(width, 1); // top right corner + glTexCoord2f(1, 0); glVertex2i(width, 1 + height); // bottom right corner + glTexCoord2f(0, 0); glVertex2i(0, 1 + height); // bottom left corner + glEnd(); + + // the new waterfall line + glBindTexture(GL_TEXTURE_2D, m_waterfallLineFBO->texture()); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(0, 0); // top left corner + glTexCoord2f(1, 1); glVertex2i(width, 0); // top right corner + glTexCoord2f(1, 0); glVertex2i(width, 1); // bottom right corner + glTexCoord2f(0, 0); glVertex2i(0, 1); // bottom left corner + glEnd(); + + m_textureFBO->release(); + + glDisable(GL_TEXTURE_2D); + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + if (m_waterfallLineCnt < height) { + + QRect rect(0, top + m_waterfallLineCnt, width, height - m_waterfallLineCnt); + drawGLRect(rect, QColor(0, 0, 0, 255), 3.0f); + } + + // copy the next waterfall image to the waterfall FBO + QRect copyRect(0, 0, width, height); + QGLFramebufferObject::blitFramebuffer(m_waterfallFBO, copyRect, m_textureFBO, copyRect); + } + else { + + drawGLRect(m_waterfallRect, Qt::black); + } + } + else { + } +} + +void QGLReceiverPanel::drawWaterfallVerticalScale() { + + if (!m_secScaleWaterfallRect.isValid()) return; + + int width = m_secScaleWaterfallRect.width(); + int height = m_secScaleWaterfallRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_secScaleWaterfallFBO || m_secScaleWaterfallUpdate || m_secScaleWaterfallRenew) { + + if (!m_secScaleWaterfallFBO || m_secScaleWaterfallRenew) { + + if (m_secScaleWaterfallFBO) { + + delete m_secScaleWaterfallFBO; + m_secScaleWaterfallFBO = 0; + } + m_secScaleWaterfallFBO = new QGLFramebufferObject(width, height); + //if (m_secScaleWaterfallFBO) + // GRAPHICS_DEBUG << "m_secScaleWaterfallFBO generated."; + } + + m_secScaleWaterfallFBO->bind(); + renderWaterfallVerticalScale(); + m_secScaleWaterfallFBO->release(); + + m_secScaleWaterfallUpdate = false; + m_secScaleWaterfallRenew = false; + } + + renderTexture(m_secScaleWaterfallRect, m_secScaleWaterfallFBO->texture(), 4.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLReceiverPanel::drawCrossHair() { + + QRect rect(0, m_panRect.top(), width(), height() - m_panRect.top()); + + int x = m_mousePos.x(); + int y = m_mousePos.y(); + + int textOffset = 20; + int spacing = 6; + + glDisable(GL_MULTISAMPLE); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + + qglColor(QColor(95, 95, 95, 255)); + + // set a scissor box + glScissor(rect.left(), rect.top(), rect.width() - 1, rect.height()); + glEnable(GL_SCISSOR_TEST); + + // horizontal line + glBegin(GL_LINES); + glVertex3f(m_dBmScalePanRect.right() - 2, y, 4.0f); + glVertex3f(rect.right() - 1, y, 4.0f); + glEnd(); + + // vertical line + glBegin(GL_LINES); + glVertex3f(x, rect.top() + 1, 4.0f); + glVertex3f(x, rect.bottom() - 1, 4.0f); + glEnd(); + + // cross hair + qglColor(QColor(180, 180, 180, 255)); + glBegin(GL_LINES); + glVertex3f(x , y - 20, 5.0f); + glVertex3f(x , y + 20, 5.0f); + glVertex3f(x - 20, y, 5.0f); + glVertex3f(x + 20, y, 5.0f); + glEnd(); + + // text + QString dFstr; + QString fstr; + QString dBstr; + + int dx = m_panRect.width()/2 - x; + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + qreal df = unit * dx; + qreal frequency = m_centerFrequency - df; + + dFstr = frequencyString(m_deltaFrequency - df, true); + fstr = frequencyString(frequency); + + qreal dBm = glPixelTodBm(m_panRect, m_dBmPanMax, m_dBmPanMin, y); + dBstr = QString::number(dBm, 'f', 1) + " dBm"; + + int rectWidth; + int fontHeight; + if (m_smallSize) { + + rectWidth = m_fonts.smallFontMetrics->boundingRect(fstr).width(); + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect("0").height() + spacing; + } + else { + + rectWidth = m_fonts.bigFont1Metrics->width(fstr); + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect("0").height() + spacing; + } + + m_haircrossMaxRight = rectWidth + textOffset; + m_smallSize ? m_haircrossMinTop = 40 : m_haircrossMinTop = 60; + + + int tx, ty; + if (x > m_panRect.width() - m_haircrossMaxRight) { + + tx = x - m_haircrossMaxRight; + if (y > m_haircrossMinTop) + m_smallSize ? ty = y - 42 : ty = y - 62; + else + m_smallSize ? ty = y + 10 : ty = y + 30; + } + else { + + tx = x + textOffset; + if (y > m_haircrossMinTop) + m_smallSize ? ty = y - 42 : ty = y - 62; + else + m_smallSize ? ty = y + 10 : ty = y + 30; + } + + // delta frequency and frequency + //qglColor(QColor(200, 55, 55, 255)); + qglColor(QColor(200, 200, 200, 255)); + if (m_smallSize) { + + m_oglTextSmall->renderText(tx, ty, 5.0f, dFstr); + //qglColor(QColor(200, 200, 200, 255)); + m_oglTextSmall->renderText(tx, ty + fontHeight, 5.0f, fstr); + } + else { + + m_oglTextBig1->renderText(tx, ty, 5.0f, dFstr); + //qglColor(QColor(200, 200, 200, 255)); + m_oglTextBig1->renderText(tx, ty + fontHeight, 5.0f, fstr); + } + + + // dBm value + if (m_mouseRegion == panadapterRegion) { + + if (m_smallSize) + m_oglTextSmall->renderText(tx, ty + 2*fontHeight, 5.0f, dBstr); + else + m_oglTextBig1->renderText(tx, ty + 2*fontHeight, 5.0f, dBstr); + } + + // Ham band text + /*if (m_oldMousePosX != m_mousePos.x()) { + + m_bandText = getHamBandTextString(set->getHamBandTextList(), true, frequency); + m_oldMousePosX = m_mousePos.x(); + }*/ + + glColor3f(0.94f, 0.82f, 0.43f); + if (m_smallSize) + m_oglTextSmall->renderText(tx, ty + 4*fontHeight, 5.0f, m_bandText); + else + m_oglTextBig1->renderText(tx, ty + 5*fontHeight, 5.0f, m_bandText); + + + glDisable(GL_SCISSOR_TEST); + glEnable(GL_MULTISAMPLE); +} + +void QGLReceiverPanel::drawVFOControl() { + + // lock Panadapter + QString str = "PAN LOCKED"; + int x1 = m_dBmScalePanRect.right() + 5; + int y1 = 3; + + if (m_panLocked) { + + if (m_dataEngineState == QSDR::DataEngineUp) { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(255, 170, 90, 200)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + else { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(150, 150, 150, 100)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + } + + // click VFO + x1 += m_fonts.smallFontMetrics->width(str) + 12; + str = "CLICK VFO"; + + if (m_clickVFO) { + + if (m_dataEngineState == QSDR::DataEngineUp) { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(255, 170, 90, 200)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + else { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str); + qglColor(QColor(150, 150, 150, 100)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str); + } + } + + // FFT size + if (m_receiver == 0) { + + str = "FFT: %1"; + //float res; + QString s; + + switch (m_fftMult) { + + case 1: + s = "4k"; + break; + + case 2: + s = "8k"; + break; + + case 4: + s = "16k"; + break; + + case 8: + s = "32k"; + break; + } + x1 = m_panRect.right() - m_fonts.smallFontMetrics->width(str) - 5; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(x1+3, y1, 0.0f, str.arg(s)); + qglColor(QColor(255, 170, 90, 200)); + m_oglTextSmall->renderText(x1+1, y1-2, 1.0f, str.arg(s)); + } + } + + int delta = qRound((m_deltaF * m_panRect.width())/m_freqScaleZoomFactor); + //GRAPHICS_DEBUG << "delta = " << delta; + + if (delta > m_panRect.width()/2) { + + QColor col = QColor(255, 40, 40, 255); + str = "<< VFO %1"; + str = str.arg(frequencyString(m_vfoFrequency, false)); + + int x = m_dBmScalePanRect.right(); + int y = 25; + + QRect rect = QRect(x, y, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, col, 2.0f); + qglColor(QColor(255, 255, 255, 255)); + m_oglTextSmall->renderText(x+1, y-2, 3.0f, str); + } + + if (delta < -m_panRect.width()/2) { + + QColor col = QColor(255, 40, 40, 255); + str = "%1 VFO >>"; + str = str.arg(frequencyString(m_vfoFrequency, false)); + + int x = m_panRect.right() - m_fonts.smallFontMetrics->width(str); + int y = 25; + + QRect rect = QRect(x, y, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, col, 2.0f); + qglColor(QColor(255, 255, 255, 255)); + m_oglTextSmall->renderText(x+1, y-2, 3.0f, str); + } + + //qglColor(QColor(0, 0, 0)); + //m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // set Center = VFO frequency button + /*QColor col; + x1 += m_fonts.smallFontMetrics->width(str) + 7; + str = "mid = vfo"; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) { + + if (m_panLocked) + col = QColor(1, 150, 140, 140); + else + col = QColor(1, 230, 220, 140); + } + else + col = QColor(90, 100, 90, 140); + } + else + col = m_darkColor; + + m_midToVfoButtonRect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 5, m_fonts.fontHeightSmallFont + 2); + drawGLRect(m_midToVfoButtonRect, col, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str);*/ + + + // set VFO = Center frequency button + /*x1 += m_fonts.smallFontMetrics->width(str) + 7; + str = "vfo = mid"; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) + col = QColor(1, 230, 220, 140); + else + col = QColor(90, 100, 90, 140); + } + else + col = m_darkColor; + + m_vfoToMidButtonRect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 5, m_fonts.fontHeightSmallFont + 2); + drawGLRect(m_vfoToMidButtonRect, col, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str);*/ +} + +void QGLReceiverPanel::drawReceiverInfo() { + + QString str; + + // mouse wheel freq step size + /*if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == m_currentReceiver) + col = QColor(1, 190, 180, 180); + else + col = QColor(1, 100, 90, 180); + } + else + col = m_darkColor; + + str = "%1"; + str = str.arg(set->getValue1000(m_mouseWheelFreqStep, 0, "Hz")); + + int x1 = m_panRect.width() - (m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 9); + int y1 = 3; + + rect = QRect(x1+2, y1, m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 5, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, col, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+3, y1-2, 3.0f, str);*/ + + + // AGC mode + //if (m_dataEngineState == QSDR::DataEngineUp) { + + // if (m_receiver == m_currentReceiver) { + + // if (m_showAGCLines) + // col = QColor(255, 170, 90, 180); + // else + // col = QColor(215, 130, 50, 180); + // } + // else + // col = QColor(165, 80, 1); + //} + //else + // col = m_darkColor; + + //str = "%1"; + ////str = str.arg(set->getAGCModeString(m_receiver)); + //str = str.arg(m_agcModeString); + + //x1 -= m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 7; + //y1 = 3; + + //m_agcButtonRect = QRect(x1+2, y1, m_fonts.smallFontMetrics->tightBoundingRect(str).width() + 5, m_fonts.fontHeightSmallFont + 2); + //drawGLRect(m_agcButtonRect, col, 2.0f); + //qglColor(QColor(0, 0, 0)); + //m_oglTextSmall->renderText(x1+3, y1-2, 3.0f, str); + + + // main frequency display + glDisable(GL_MULTISAMPLE); + if (m_panRect.height() > 15) { + + int fLength = m_fonts.bigFont1Metrics->width("55.555.555") + 30; + //GLint x = m_panRect.width()/2 - 65; + GLint x = m_panRect.left() + qRound((qreal)(m_panRect.width()/2.0f) - m_deltaF * m_panRect.width() / m_freqScaleZoomFactor) + 10; + if (x > m_panRect.right() - fLength) x -= fLength + 20; + + int alpha; + QColor colFlt; + QColor colAGC; + QColor colDSP; + QRect rect; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_receiver == set->getCurrentReceiver()) { + + colDSP = QColor(1, 190, 180, 180); + colFlt = QColor(200, 190, 50, 180); + if (m_showAGCLines) + colAGC = QColor(255, 170, 90, 180); + else + colAGC = QColor(215, 130, 50, 180); + + alpha = 255; + } + else { + + alpha = 155; + colFlt = QColor(110, 100, 1, 180); + colDSP = QColor(1, 100, 90, 180); + colAGC = QColor(165, 80, 1); + } + } + else { + + alpha = 100; + colFlt = m_darkColor; + colAGC = m_darkColor; + colDSP = m_darkColor; + } + + + // Filter width + str = "%1"; + str = str.arg(m_filterWidthString); + + int x1 = x; + int y1 = 3; + + rect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, colFlt, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // DSP mode + x1 += m_fonts.smallFontMetrics->width(str) + 5; + + str = "%1"; + str = str.arg(m_dspModeString); + + rect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 3, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, colDSP, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // AGC mode + x1 += m_fonts.smallFontMetrics->width(str) + 4; + + str = "%1"; + str = str.arg(m_agcModeString); + + rect = QRect(x1, y1, m_fonts.smallFontMetrics->width(str) + 4, m_fonts.fontHeightSmallFont + 2); + drawGLRect(rect, colAGC, 2.0f); + qglColor(QColor(0, 0, 0)); + m_oglTextSmall->renderText(x1+1, y1-2, 3.0f, str); + + // VFO frequency + TFrequency f; + f.freqMHz = (int)(m_vfoFrequency / 1000); + f.freqkHz = (int)(m_vfoFrequency % 1000); + + str = "%1.%2"; + int f1 = f.freqMHz; + int f2 = f.freqkHz; + + QString fstr = str.arg(f1/1000).arg(f1 - 1000 * (int)(f1/1000), 3, 10, QLatin1Char('0')); + //int fLength = m_fonts.bigFont1Metrics->width(fstr) + 55; + + qglColor(QColor(0, 0, 0, alpha)); + m_oglTextBig1->renderText(x+2, 14, 4.0f, fstr); + + qglColor(QColor(255, 255, 255, alpha)); + m_oglTextBig1->renderText(x, 12, 5.0f, fstr); + + str = "%1"; + if (f1 / 1000 < 10) { + + qglColor(QColor(0, 0, 0, alpha)); + m_oglTextBig2->renderText(x + 36, 14, 4.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 60, 14, 4.0f, "MHz"); + + qglColor(QColor(255, 255, 255, alpha)); + m_oglTextBig2->renderText(x + 34, 12, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 58, 12, 5.0f, "MHz"); + } + else { + + qglColor(QColor(0, 0, 0, alpha)); + m_oglTextBig2->renderText(x + 39, 13, 4.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 65, 13, 4.0f, "MHz"); + + qglColor(QColor(255, 255, 255, alpha)); + m_oglTextBig2->renderText(x + 41, 11, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 63, 11, 5.0f, "MHz"); + } + } + + if (m_panRect.height() > 15 && m_deltaFrequency != 0) { + + // center frequency + TFrequency f; + f.freqMHz = (int)(m_centerFrequency / 1000); + f.freqkHz = (int)(m_centerFrequency % 1000); + + str = "%1.%2"; + int f1 = f.freqMHz; + int f2 = f.freqkHz; + + QString fstr = str.arg(f1/1000).arg(f1 - 1000 * (int)(f1/1000), 3, 10, QLatin1Char('0')); + GLint x = m_panRect.width()/2 + 10; + + qglColor(QColor(80, 180, 240, 180)); + m_oglTextBig1->renderText(x, 27, 5.0f, fstr); + + str = "%1"; + if (f1 / 1000 < 10) { + + m_oglTextBig2->renderText(x + 34, 27, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 58, 27, 5.0f, "MHz"); + } + else { + + m_oglTextBig2->renderText(x + 41, 27, 5.0f, str.arg(f2, 3, 10, QLatin1Char('0'))); + m_oglTextBig1->renderText(x + 63, 27, 5.0f, "MHz"); + } + } + glEnable(GL_MULTISAMPLE); +} + +void QGLReceiverPanel::drawAGCControl() { + + glDisable(GL_MULTISAMPLE); + glLineStipple(1, 0x0C0C); + glEnable(GL_LINE_STIPPLE); + glLineWidth(1.0f); + + glScissor(m_panRect.left(), size().height() - (m_panRect.top() + m_panRect.height()), m_panRect.left() + m_panRect.width(), m_panRect.height()); + glEnable(GL_SCISSOR_TEST); + + if (m_agcMode == (AGCMode) agcOFF) { + + m_agcFixedGainLevelPixel = dBmToGLPixel(m_panRect, m_dBmPanMax, m_dBmPanMin, -m_agcFixedGain); + //GRAPHICS_DEBUG << "m_agcFixedGainLevelPixel = " << m_agcFixedGainLevelPixel; + + QString str = "AGC-F"; + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 32, m_agcFixedGainLevelPixel - 13, 4.0f, str); + qglColor(QColor(225, 125, 225, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 34, m_agcFixedGainLevelPixel - 15, 5.0f, str); + + // AGC fixed gain line + glBegin(GL_LINES); + qglColor(QColor(0, 0, 0, 255)); + glVertex3f(m_dBmScalePanRect.right() - 1, m_agcFixedGainLevelPixel + 2, 4.0f); + glVertex3f(m_panRect.right() - 1, m_agcFixedGainLevelPixel, 4.0f); + qglColor(QColor(225, 125, 225, 255)); + glVertex3f(m_dBmScalePanRect.right() - 3, m_agcFixedGainLevelPixel, 5.0f); + glVertex3f(m_panRect.right() - 1, m_agcFixedGainLevelPixel, 4.0f); + glEnd(); + + } + else { + + m_agcThresholdPixel = dBmToGLPixel(m_panRect, m_dBmPanMax, m_dBmPanMin, m_agcThresholdOld); + + if (m_agcHangEnabled) + m_agcHangLevelPixel = dBmToGLPixel(m_panRect, m_dBmPanMax, m_dBmPanMin, m_agcHangLevelOld); + + QString str = "AGC-T"; + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 32, m_agcThresholdPixel - 13, 4.0f, str); + qglColor(QColor(225, 125, 125, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 34, m_agcThresholdPixel - 15, 5.0f, str); + + // AGC threshold line + glBegin(GL_LINES); + qglColor(QColor(0, 0, 0, 255)); + glVertex3f(m_dBmScalePanRect.right() - 1, m_agcThresholdPixel + 2, 4.0f); + glVertex3f(m_panRect.right() - 1, m_agcThresholdPixel, 4.0f); + qglColor(QColor(225, 125, 125, 255)); + glVertex3f(m_dBmScalePanRect.right() - 3, m_agcThresholdPixel, 5.0f); + glVertex3f(m_panRect.right() - 1, m_agcThresholdPixel, 4.0f); + glEnd(); + + // AGC hang threshold line + if (m_agcHangEnabled) { + + str = "AGC-H"; + qglColor(QColor(0, 0, 0, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 32, m_agcHangLevelPixel - 13, 4.0f, str); + qglColor(QColor(125, 225, 125, 255)); + m_oglTextSmall->renderText(m_panRect.right() - 34, m_agcHangLevelPixel - 15, 5.0f, str); + + glBegin(GL_LINES); + qglColor(QColor(0, 0, 0, 255)); + glVertex3f(m_dBmScalePanRect.right() - 1, m_agcHangLevelPixel + 2, 4.0f); + glVertex3f(m_panRect.right() - 1, m_agcHangLevelPixel, 4.0f); + qglColor(QColor(125, 225, 125, 255)); + glVertex3f(m_dBmScalePanRect.right() - 3, m_agcHangLevelPixel, 5.0f); + glVertex3f(m_panRect.right() - 1, m_agcHangLevelPixel, 4.0f); + glEnd(); + } + } + + glDisable(GL_SCISSOR_TEST); + glDisable(GL_LINE_STIPPLE); + glEnable(GL_MULTISAMPLE); +} + +//********************************************************************************************** +// The algorithms of the scale functions renderPanVerticalScale() and renderPanHorizontalScale() +// are taken from SDRMAXIII (c) Catherine Moss, with permission. + +void QGLReceiverPanel::renderPanVerticalScale() { + + QString str; + + int spacing = 7; + int fontHeight; + int fontMaxWidth; + if (m_smallSize) { + + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing; + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width(); + } + else { + + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect(".0dBm").height() + spacing; + fontMaxWidth = m_fonts.bigFont1Metrics->boundingRect("-000.0").width(); + } + + + GLint width = m_dBmScalePanRect.width(); + GLint height = m_dBmScalePanRect.height(); + + qreal unit = (qreal)(height / qAbs(m_dBmPanMax - m_dBmPanMin)); + + m_dBmScale = getYRuler2(m_dBmScalePanRect, fontHeight, unit, m_dBmPanMin, m_dBmPanMax); + + glClear(GL_COLOR_BUFFER_BIT); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + if (m_smallSize) + textRect.moveLeft(3); + else + textRect.moveLeft(-1); + + int yOld = -textRect.height(); + + int len = m_dBmScale.mainPointPositions.length(); + int sublen = m_dBmScale.subPointPositions.length(); + + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, width, height), QColor(30, 30, 30, 180)); + + if (len > 0) { + + glColor3f(0.65f, 0.76f, 0.81f); + glLineWidth(1); + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(width, m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + glColor3f(0.45f, 0.56f, 0.61f); + if (sublen > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < sublen; i++) { + + glVertex3f(width, m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 2, m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + glColor3f(0.75f, 0.86f, 0.91f); + for (int i = 0; i < len; i++) { + + textRect.moveBottom(m_dBmScale.mainPointPositions.at(i) + textRect.height()/2); + + if (textRect.y() >= yOld && textRect.bottom() <= (m_dBmScalePanRect.height() - textRect.height())) { + + str = QString::number(m_dBmScale.mainPoints.at(i), 'f', 1); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x() + fontMaxWidth - m_fonts.smallFontMetrics->tightBoundingRect(str).width(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + fontMaxWidth - m_fonts.bigFont1Metrics->tightBoundingRect(str).width(), textRect.y(), str); + yOld = textRect.bottom(); + } + } + } + + textRect.moveTop(m_dBmScalePanRect.height() - textRect.height()); + glColor3f(0.94f, 0.22f, 0.43f); + + str = QString("dBm"); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + 10, textRect.y(), str); + + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); +} + +void QGLReceiverPanel::renderPanHorizontalScale() { + + //GRAPHICS_DEBUG << "render frequency scale"; + int fontHeight; + int fontMaxWidth; + if (m_smallSize) { + + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kMGHz").height(); + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.000.0").width(); + } + else { + + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect(".0kMGHz").height(); + fontMaxWidth = m_fonts.bigFont1Metrics->boundingRect("000.000.0").width(); + } + + qreal freqSpan = (qreal)(m_sampleRate * m_freqScaleZoomFactor); + qreal lowerFreq = (qreal)m_centerFrequency - freqSpan / 2; + qreal upperFreq = (qreal)m_centerFrequency + freqSpan / 2; + qreal unit = (qreal)(m_freqScalePanRect.width() / freqSpan); + + m_frequencyScale = getXRuler(m_freqScalePanRect, fontMaxWidth, unit, lowerFreq, upperFreq); + + // draw the frequency scale + int offset_X = -1; + int textOffset_y = 5; + double freqScale = 1; + + QString fstr = QString(" Hz "); + if (upperFreq >= 1e6) { freqScale = 1e6; fstr = QString(" MHz "); } + else + if (upperFreq >= 1e3) { freqScale = 1e3; fstr = QString(" kHz "); } + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, m_freqScalePanRect.width(), m_freqScalePanRect.height()), QColor(0, 0, 0, 255)); + + QRect scaledTextRect(0, textOffset_y, 1, m_freqScalePanRect.height()); + + if (m_smallSize) + scaledTextRect.setWidth(m_fonts.smallFontMetrics->width(fstr)); + else + scaledTextRect.setWidth(m_fonts.bigFont1Metrics->width(fstr)); + + scaledTextRect.moveLeft(m_freqScalePanRect.width() - scaledTextRect.width()); + + glColor3f(0.65f, 0.76f, 0.81f); + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + glLineWidth(3); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 4.0f, 0.0f); + } + glEnd(); + + for (int i = 0; i < len; i++) { + + QString str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 3); + + if (i > 0) { + + double delta = m_frequencyScale.mainPoints.at(i) - m_frequencyScale.mainPoints.at(i-1); + if (delta < 1000.0) + str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 4); + else + if (freqScale == 1e3) + while (str.endsWith('0')) str.remove(str.size() - 1, 1); + } + if (str.endsWith('.')) str.remove(str.size() - 1, 1); + + int textWidth; + if (m_smallSize) + textWidth = m_fonts.smallFontMetrics->width(str); + else + textWidth = m_fonts.bigFont1Metrics->width(str); + QRect textRect(m_frequencyScale.mainPointPositions.at(i) + offset_X - (textWidth / 2), textOffset_y, textWidth, fontHeight); + + if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue; + + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x(), textRect.y(), str); + } + } + + if (m_frequencyScale.subPointPositions.length() > 0) { + + glLineWidth(1); + glBegin(GL_LINES); + for (int i = 0; i < m_frequencyScale.subPointPositions.length(); i++) { + + glVertex3f(m_frequencyScale.subPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.subPointPositions.at(i), 3.0f, 0.0f); + } + glEnd(); + } + + glColor3f(0.94f, 0.22f, 0.43f); + + if (m_smallSize) + m_oglTextSmall->renderText(m_freqScalePanRect.width() - 30, textOffset_y, fstr); + else + m_oglTextBig1->renderText(m_freqScalePanRect.width() - 33, textOffset_y, fstr); +} + +void QGLReceiverPanel::renderPanadapterGrid() { + + //GRAPHICS_DEBUG << "render panadapter grid"; + glClear(GL_COLOR_BUFFER_BIT); + glLineStipple(1, 0x9999); + //glLineStipple(1, 0xCCCC); + glEnable(GL_LINE_STIPPLE); + glLineWidth(1.0f); + + // vertical lines + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + GLint x1 = m_panRect.left(); + GLint x2 = 1; + if (m_dBmScalePanRect.isValid()) x2 += m_dBmScalePanRect.width(); + + //GLint y1 = rect.top() + 1; + GLint y1 = 1; + GLint y2 = m_panRect.bottom() - 1; + + TGL2int *vertexArray = new TGL2int[len * 2]; + int vertexArrayLen = 0; + + TGL2int point1, point2; + point1.y = y1; + point2.y = y2; + for (int i = 0; i < len; i++) { + + GLint x = m_frequencyScale.mainPointPositions.at(i); + if (x < x2) continue; + x += x1; + point1.x = x; + point2.x = x; + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_INT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + } + + // horizontal lines + len = m_dBmScale.mainPointPositions.length(); + if (len > 0) { + + TGL2float *vertexArray = new TGL2float[len * 2]; + int vertexArrayLen = 0; + + TGL2float point1, point2; + point1.x = m_panRect.left() + m_dBmScalePanRect.width(); + point2.x = m_panRect.right(); + + for (int i = 0; i < len; i++) { + + GLfloat y = m_dBmScale.mainPointPositions.at(i); + + point1.y = y; + point2.y = y; + + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + + } + glDisable(GL_LINE_STIPPLE); +} + +void QGLReceiverPanel::renderWaterfallVerticalScale() { + + QString str; + + int spacing = 7; + int fontHeight; + int fontMaxWidth; + if (m_smallSize) { + + fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0s").height() + spacing; + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.0").width(); + } + else { + + fontHeight = m_fonts.bigFont1Metrics->tightBoundingRect(".0s").height() + spacing; + fontMaxWidth = m_fonts.bigFont1Metrics->boundingRect("000.0").width(); + } + + GLint width = m_secScaleWaterfallRect.width(); + GLint height = m_secScaleWaterfallRect.height(); + + qreal unit = (qreal)(height / qAbs(m_secWaterfallMax - m_secWaterfallMin)); + + m_secScale = getYRuler2(m_secScaleWaterfallRect, fontHeight, unit, m_secWaterfallMin, m_secWaterfallMax); + //m_secScale = getYRuler3(m_secScaleWaterfallRect, fontHeight, unit, m_secWaterfallMin, m_secWaterfallMax, 10.0f); + + glClear(GL_COLOR_BUFFER_BIT); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + if (m_smallSize) + textRect.moveLeft(3); + else + textRect.moveLeft(-1); + + int yOld = -textRect.height(); + + int len = m_secScale.mainPointPositions.length(); + int sublen = m_secScale.subPointPositions.length(); + + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, width, height), QColor(40, 40, 40, 180)); + + if (len > 0) { + + glColor3f(0.65f, 0.76f, 0.81f); + glLineWidth(1); + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(width, m_secScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 4, m_secScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + glColor3f(0.45f, 0.56f, 0.61f); + if (sublen > 0) { + + glBegin(GL_LINES); + for (int i = 0; i < sublen; i++) { + + glVertex3f(width, m_secScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(width - 2, m_secScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + glColor3f(0.95f, 0.96f, 0.91f); + for (int i = 0; i < len; i++) { + + textRect.moveBottom(m_secScale.mainPointPositions.at(i) + textRect.height()/2); + + if (textRect.y() >= yOld && textRect.bottom() <= (height - textRect.height())) { + + str = QString::number(m_secScale.mainPoints.at(i), 'f', 1); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x() + fontMaxWidth - m_fonts.smallFontMetrics->tightBoundingRect(str).width(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + fontMaxWidth - m_fonts.bigFont1Metrics->tightBoundingRect(str).width(), textRect.y(), str); + yOld = textRect.bottom(); + } + } + } + + textRect.moveTop(height - textRect.height()); + glColor3f(0.94f, 0.22f, 0.43f); + + str = QString("sec"); + if (m_smallSize) + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + else + m_oglTextBig1->renderText(textRect.x() + 10, textRect.y(), str); + + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); +} + +//******************************************************************** + +void QGLReceiverPanel::getRegion(QPoint p) { + + //QRect mouse_rect(0, 0, 100, 100); + //mouse_rect.moveCenter(p); + /*if (m_lockedPanButtonRect.contains(p)) { + + m_mouseRegion = lockedPanButtonRegion; + } + else if (m_vfoToMidButtonRect.contains(p)) { + + m_mouseRegion = vfoToMidButtonRegion; + } + else if (m_midToVfoButtonRect.contains(p)) { + + m_mouseRegion = midToVfoButtonRegion; + }*/ + if (m_agcButtonRect.contains(p)) { + + m_mouseRegion = agcButtonRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (m_freqScalePanRect.contains(p)) { + + m_mouseRegion = freqScalePanadapterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (m_dBmScalePanRect.contains(p)) { + + m_mouseRegion = dBmScalePanadapterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (qAbs(p.x() - m_filterRect.left()) < m_snapMouse && + m_panRect.contains(p) + ) { + m_mouseRegion = filterRegionLow; + m_mouseDownFilterFrequencyLo = m_filterLowerFrequency; + } + else if (qAbs(p.x() - m_filterRect.right()) < m_snapMouse && + m_panRect.contains(p) + ) { + m_mouseRegion = filterRegionHigh; + m_mouseDownFilterFrequencyHi = m_filterUpperFrequency; + } + else if (m_filterRect.contains(p)) { + + m_mouseRegion = filterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + //else if (qAbs(p.y() - m_agcThresholdPixel) < m_snapMouse && !m_crossHairCursor) { + else if (qAbs(p.y() - m_agcThresholdPixel) < m_snapMouse) { + + m_mouseRegion = agcThresholdLine; + m_mouseDownAGCThreshold = m_agcThresholdOld; + } + //else if (qAbs(p.y() - m_agcHangLevelPixel) < m_snapMouse && !m_crossHairCursor) { + else if (qAbs(p.y() - m_agcHangLevelPixel) < m_snapMouse) { + + m_mouseRegion = agcHangLine; + m_mouseDownAGCHangLevel = m_agcHangLevelOld; + } + //else if (qAbs(p.y() - m_agcFixedGainLevelPixel) < m_snapMouse && !m_crossHairCursor) { + else if (qAbs(p.y() - m_agcFixedGainLevelPixel) < m_snapMouse) { + + m_mouseRegion = agcFixedGainLine; + m_mouseDownFixedGainLevel = -m_agcFixedGain; + } + else if (m_panRect.contains(p)) { + + m_mouseRegion = panadapterRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else if (m_waterfallRect.contains(p)) { + + m_mouseRegion = waterfallRegion; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + }*/ + } + else + m_mouseRegion = elsewhere; + + //GRAPHICS_DEBUG << "region" << m_mouseRegion; +} + +void QGLReceiverPanel::resizeGL(int iWidth, int iHeight) { + + int width = (int)(iWidth/2) * 2; + int height = iHeight; + + if (width != m_oldWidth) { + + m_freqScalePanadapterRenew = true; + m_panGridRenew = true; + + m_oldWidth = width; + } + + m_spectrumVertexColorUpdate = true; + m_waterfallUpdate = true; + m_peakHoldBufferResize = true; + + glFinish(); + + m_resizeTime.restart(); + setupDisplayRegions(QSize(width, height)); + glViewport(0, 0, (GLsizei)width, (GLsizei)height); + + setProjectionOrthographic(width, height); +} + +void QGLReceiverPanel::setupDisplayRegions(QSize size) { + + m_displayTop = 0; + //m_displayTop = m_fonts.fontHeightSmallFont + 2; + int freqScaleRectHeight = 20; + //int dBmScaleWidth = 45; + + m_freqScalePanRect = QRect( + 0, + m_displayTop + qRound((size.height() - m_displayTop - freqScaleRectHeight) * m_freqRulerPosition), + size.width(), + freqScaleRectHeight); + + m_panRect = QRect( + 0, + m_displayTop, + size.width(), + m_freqScalePanRect.top() - m_displayTop); + + + if (m_panRect.height() != m_oldPanRectHeight) { + + m_dBmScalePanadapterRenew = true; + m_panGridRenew = true; + m_secScaleWaterfallRenew = true; + } + + m_oldPanRectHeight = m_panRect.height(); + m_panRectWidth = (GLint)m_panRect.width(); + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_waterfallRect = QRect( + m_freqScalePanRect.left(), + m_freqScalePanRect.top() + m_freqScalePanRect.height(), + //m_freqScalePanRect.top(), + m_freqScalePanRect.width(), + //size.height() - m_displayTop - m_freqScalePanRect.top() - m_freqScalePanRect.height()); + size.height() - m_freqScalePanRect.top() - m_freqScalePanRect.height()); + //size.height() - m_freqScalePanRect.top()); + + m_waterfallUpdate = true; + + if ((m_panRect.height() + m_waterfallRect.height()) > m_bigHeight && m_panRect.width() > m_bigWidth) + m_smallSize = false; + else + m_smallSize = true; + + m_dBmScalePanRect = QRect( + m_panRect.left(), + m_displayTop, + 45, + m_panRect.height()); + + m_secScaleWaterfallRect = QRect( + m_waterfallRect.left(), + m_freqScalePanRect.top() + m_freqScalePanRect.height(), + 45, + m_waterfallRect.height()); + + m_secWaterfallMin = -(1.0/m_fps) * m_secScaleWaterfallRect.height(); + + m_freqScalePanadapterUpdate = true; + m_dBmScalePanadapterUpdate = true; + m_secScaleWaterfallUpdate = true; + m_panGridUpdate = true; + +// GRAPHICS_DEBUG << "***************************************************************************"; +// GRAPHICS_DEBUG << "receiver:" << m_receiver; +// GRAPHICS_DEBUG << "total size" << size.height(); +// GRAPHICS_DEBUG << "sizes (top, bottom, height):"; +// GRAPHICS_DEBUG << "panRect" << m_panRect.top() << m_panRect.bottom() << m_panRect.height(); +// //GRAPHICS_DEBUG << "panRect (H/W): " << m_panRect.height() << ": " << m_panRect.width(); +// GRAPHICS_DEBUG << "waterfallRect" << m_waterfallRect.top() << m_waterfallRect.bottom() << m_waterfallRect.height(); +// GRAPHICS_DEBUG << "freqScalePanRect" << m_freqScalePanRect.top() << m_freqScalePanRect.bottom() << m_freqScalePanRect.height(); +// GRAPHICS_DEBUG << "dBmScalePanRect" << m_dBmScalePanRect.top() << m_dBmScalePanRect.bottom() << m_dBmScalePanRect.height(); +// GRAPHICS_DEBUG << ""; + +} + +void QGLReceiverPanel::saveGLState() { + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); +} + +void QGLReceiverPanel::restoreGLState() { + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glPopAttrib(); +} + +void QGLReceiverPanel::showText(float x, float y, float z = 0.0f, const QString &text = "", bool smallText = true) { + + if (smallText) + m_oglTextSmall->renderText(x, y, z, text); + else + m_oglTextBig1->renderText(x, y, z, text); +} + +//******************************************************************** +// HMI control + +void QGLReceiverPanel::enterEvent(QEvent *event) { + + setFocus(Qt::MouseFocusReason); + + m_mousePos = QPoint(-1, -1); + m_mouseRegion = elsewhere; + + setCursor(Qt::BlankCursor); + update(); + + QGLWidget::enterEvent(event); +} + +void QGLReceiverPanel::leaveEvent(QEvent *event) { + + m_mousePos = QPoint(-100, -100); + m_mouseRegion = elsewhere; + + update(); + + QGLWidget::leaveEvent(event); +} + +void QGLReceiverPanel::wheelEvent(QWheelEvent* event) { + + //GRAPHICS_DEBUG << "wheelEvent"; + QPoint pos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + double freqStep = set->getMouseWheelFreqStep(m_currentReceiver); + + switch (m_mouseRegion) { + + case panadapterRegion: + case waterfallRegion: + case filterRegion: + case filterRegionLow: + case filterRegionHigh: + + double delta = 0; + if (event->delta() < 0) + delta = -freqStep; + else if (event->delta() > 0) + delta = freqStep; + + if (!m_panLocked) { + + if (m_centerFrequency + delta > MAXFREQUENCY) + m_centerFrequency = MAXFREQUENCY; + else if (m_centerFrequency + delta < 0) + m_centerFrequency = 0; + else + // snap to the frequency step + m_centerFrequency = (long)(qRound((m_centerFrequency + delta) / qAbs(freqStep)) * qAbs(freqStep)); + + m_vfoFrequency = m_centerFrequency - m_deltaFrequency; + } + else { + + if (m_vfoFrequency + delta > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency + delta < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + else + // snap to the frequency step + m_vfoFrequency = (long)(qRound((m_vfoFrequency + delta) / qAbs(freqStep)) * qAbs(freqStep)); + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + //GRAPHICS_DEBUG << "m_deltaFrequency: " << m_deltaFrequency; + } + + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + + break; + } + + //updateGL(); + update(); +} + +void QGLReceiverPanel::mousePressEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mousePressEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == agcButtonRegion) { + + if (event->buttons() == Qt::LeftButton) { + + if (m_showAGCLines) { + + m_showAGCLines = false; + set->setAGCShowLines(this, m_receiver, false); + } + else { + + m_showAGCLines = true; + set->setAGCShowLines(this, m_receiver, true); + } + } + } + else if (m_mouseRegion == panadapterRegion || m_mouseRegion == waterfallRegion) { + + if (event->buttons() == Qt::LeftButton && m_receiver != set->getCurrentReceiver()) { + + set->setCurrentReceiver(this, m_receiver); + } + else if (event->buttons() == Qt::LeftButton && m_clickVFO) { + + m_crossHairCursor = false; + setCursor(Qt::OpenHandCursor); + m_dragMouse = true; + + double freqStep = set->getMouseWheelFreqStep(m_currentReceiver); + int dx = m_panRect.width()/2 - m_mousePos.x(); + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width()); + + m_vfoFrequency = (long)(qRound((m_centerFrequency - unit * dx) / qAbs(freqStep)) * qAbs(freqStep)); + + /*if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2;*/ + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + update(); + } + else if (event->buttons() == Qt::LeftButton) { + + m_crossHairCursor = false; + setCursor(Qt::OpenHandCursor); + m_dragMouse = true; + } + else if (event->buttons() == Qt::RightButton) { + + showRadioPopup(true); + } + } + else if (m_mouseRegion == filterRegion) { + + //setCursor(Qt::ArrowCursor); + if (event->buttons() == Qt::LeftButton) + m_highlightFilter = true; + } + else if (m_mouseRegion == freqScalePanadapterRegion) { + + m_rulerMouseDownPos = m_freqScalePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor); + update(); + + return; + } + else if (m_mouseRegion == dBmScalePanadapterRegion) { + + m_rulerMouseDownPos = m_dBmScalePanRect.topLeft(); + + if (event->buttons() == Qt::RightButton) + setCursor(Qt::SplitVCursor); + update(); + + return; + } + + update(); +} + +void QGLReceiverPanel::mouseReleaseEvent(QMouseEvent *event) { + + //GRAPHICS_DEBUG << "mouseReleaseEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == freqScalePanadapterRegion) { + + return; + } + //else if (m_mouseRegion == panadapterRegion || m_mouseRegion == waterfallRegion) { + //} + m_dragMouse = false; + m_crossHairCursor = true; + if (m_crossHair) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); + + update(); +} + +void QGLReceiverPanel::mouseDoubleClickEvent(QMouseEvent *event) { + + //GRAPHICS_DEBUG << "mouseDoubleClickEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == panadapterRegion) { + + if (event->buttons() == Qt::LeftButton) { + + //set->showRadioPopupWidget(); +// if (!band160mBtn->isVisible()) +// band160mBtn->show(); +// else +// band160mBtn->hide(); + } + } +} + +void QGLReceiverPanel::mouseMoveEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mouseMoveEvent"; + QPoint pos = event->pos(); + m_mousePos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + switch (m_mouseRegion) { + + //case lockedPanButtonRegion: + //case vfoToMidButtonRegion: + //case midToVfoButtonRegion: + + //if (m_crossHairCursor) setCursor(Qt::ArrowCursor); + + // break; + + case agcThresholdLine: + + //GRAPHICS_DEBUG << "agcThresholdLine Rx:" << m_receiver; + if (!m_showAGCLines || (m_agcMode == (AGCMode) agcOFF)) + break; + + m_crossHairCursor = false; + setCursor(Qt::SizeVerCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height(); + qreal dAGCThreshold = dPos.y() * unit; + + m_agcThresholdNew = m_mouseDownAGCThreshold + dAGCThreshold; + if (m_agcThresholdNew > m_dBmPanMax-2) + m_agcThresholdNew = m_dBmPanMax-2; + + if (m_agcThresholdNew < m_dBmPanMin+2) + m_agcThresholdNew = m_dBmPanMin+2; + + set->setAGCThreshold_dB(this, m_receiver, m_agcThresholdNew); + } + break; + + case agcHangLine: + + //GRAPHICS_DEBUG << "agcHangLine Rx:" << m_receiver; + if (!m_showAGCLines || (m_agcMode == (AGCMode) agcOFF) || !m_agcHangEnabled) + break; + + m_crossHairCursor = false; + setCursor(Qt::SizeVerCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height(); + qreal dAGCThreshold = dPos.y() * unit; + + m_agcHangLevelNew = m_mouseDownAGCHangLevel + dAGCThreshold; + + if (m_agcHangLevelNew > m_dBmPanMax-2) + m_agcHangLevelNew = m_dBmPanMax-2; + + if (m_agcHangLevelNew < m_dBmPanMin+2) + m_agcHangLevelNew = m_dBmPanMin+2; + + set->setAGCHangLevel_dB(this, m_receiver, m_agcHangLevelNew); + //GRAPHICS_DEBUG << "set m_agcHangLevelNew = " << m_agcHangLevelNew; + } + break; + + case agcFixedGainLine: + + //GRAPHICS_DEBUG << "agcFixedGainLine Rx:" << m_receiver; + if (!m_showAGCLines || (m_agcMode != (AGCMode) agcOFF)) + break; + + m_crossHairCursor = false; + setCursor(Qt::SizeVerCursor); + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height(); + qreal dAGCFixedGain = dPos.y() * unit; + + qreal agcFixedGain = m_mouseDownFixedGainLevel + dAGCFixedGain; + + if (agcFixedGain > m_dBmPanMax-2) + agcFixedGain = m_dBmPanMax-2; + + if (agcFixedGain < m_dBmPanMin+2) + agcFixedGain = m_dBmPanMin+2; + + set->setAGCFixedGain_dB(this, m_receiver, -agcFixedGain); + } + break; + + case panadapterRegion: + case waterfallRegion: + + //GRAPHICS_DEBUG << "panadapterRegion Rx:" << m_receiver; + if (!m_dragMouse) { + + m_crossHairCursor = true; + if (m_crossHair) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); + } + + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_freqScalePanRect.width()); + qreal deltaFreq = unit * dPos.x(); + + long newFrequency = m_centerFrequency + deltaFreq; + if (newFrequency > MAXFREQUENCY) + newFrequency = MAXFREQUENCY; + else + if (newFrequency + deltaFreq < 0) + newFrequency = 0; + else { + + if (m_panLocked) { + + if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + + m_vfoFrequency -= deltaFreq; + } + else + m_centerFrequency += deltaFreq; + } + + if (m_panLocked) { + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + } + else { + + m_vfoFrequency = m_centerFrequency - m_deltaFrequency; + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + } + + m_mouseDownPos = pos; + + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + break; + + //case waterfallRegion: + + //GRAPHICS_DEBUG << "waterfallRegion Rx:" << m_receiver; + //m_crossHairCursor = true; + //setCursor(Qt::BlankCursor); + + /*if (event->buttons() == Qt::LeftButton) { + + m_cameraAngle += (pos - m_mouseDownPos); + m_mouseDownPos = pos; + } + else + if (event->buttons() == Qt::RightButton) { + + m_cameraDistance += (pos.y() - m_mouseDownPos.y()) * 0.2f; + m_mouseDownPos = pos; + } + setCursor(Qt::ArrowCursor);*/ + //update(); + //break; + + case dBmScalePanadapterRegion: + //GRAPHICS_DEBUG << "dBmScalePanadapterRegion"; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal unit = (qreal)(qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height()); + + qreal newMin = m_dBmPanMin - unit * dPos.y(); + qreal newMax = m_dBmPanMax - unit * dPos.y(); + + if (newMin > MINDBM && newMax < MAXDBM) { + + m_dBmPanMin = newMin; + m_dBmPanMax = newMax; + + set->setdBmPanScaleMin(m_receiver, m_dBmPanMin); + set->setdBmPanScaleMax(m_receiver, m_dBmPanMax); + } + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else + if (event->buttons() == Qt::RightButton && + event->modifiers() == Qt::ControlModifier) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmPanDelta = 0.5f; + else if (dPos.y() < 0) + m_dBmPanDelta = -0.5f; + + m_dBmPanMin += m_dBmPanDelta; + m_dBmPanMax -= m_dBmPanDelta; + + if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) { + + m_dBmPanMin -= m_dBmPanDelta; + m_dBmPanMax += m_dBmPanDelta; + } + if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM; + if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM; + + set->setdBmPanScaleMin(m_receiver, m_dBmPanMin); + set->setdBmPanScaleMax(m_receiver, m_dBmPanMax); + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmPanDelta = 0.5f; + else if (dPos.y() < 0) + m_dBmPanDelta = -0.5f; + + m_dBmPanMax -= m_dBmPanDelta; + + if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) { + + m_dBmPanMin -= m_dBmPanDelta; + m_dBmPanMax += m_dBmPanDelta; + } + if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM; + if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM; + + set->setdBmPanScaleMin(m_receiver, m_dBmPanMin); + set->setdBmPanScaleMax(m_receiver, m_dBmPanMax); + + m_mouseDownPos = pos; + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else { + + setCursor(Qt::ArrowCursor); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + break; + + case freqScalePanadapterRegion: + //GRAPHICS_DEBUG << "freqScalePanadapterRegion Rx" << m_receiver; + if (event->buttons() == Qt::LeftButton && + event->modifiers() == Qt::ShiftModifier) { + + QPoint dPos = m_mouseDownPos - pos; + int bottom_y = height() - m_freqScalePanRect.height(); + int new_y = m_rulerMouseDownPos.y() - dPos.y(); + + if (new_y < m_panRect.top() + m_panSpectrumMinimumHeight) + new_y = m_panRect.top() + m_panSpectrumMinimumHeight; + if (new_y > bottom_y) + new_y = bottom_y; + + m_freqRulerPosition = (float)(new_y - m_panRect.top()) / (bottom_y - m_panRect.top()); + set->setFreqRulerPosition(this, m_receiver, m_freqRulerPosition); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + + qreal unit = (qreal)((m_sampleRate * m_freqScaleZoomFactor) / m_freqScalePanRect.width()); + qreal deltaFreq = unit * dPos.x(); + + /*if (m_freqScaleZoomFactor < 1.0) { + + } + else {*/ + + long newFrequency = m_centerFrequency + deltaFreq; + if (newFrequency > MAXFREQUENCY) + newFrequency = MAXFREQUENCY; + else + if (newFrequency + deltaFreq < 0) + newFrequency = 0; + else { + + m_centerFrequency += deltaFreq; + } + + if (!m_panLocked) { + + m_vfoFrequency = m_centerFrequency - m_deltaFrequency; + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + } + + //set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + //set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + + else { + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + qreal vol = set->getMainVolume(m_receiver); + set->setMainVolume(this, m_receiver, 0.0f); + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + set->setNCOFrequency(this, true, m_receiver, -m_deltaFrequency); + set->setMainVolume(this, m_receiver, vol); + } + + //set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + //} + m_mouseDownPos = pos; + + m_displayCenterlineHeight = m_panRect.top() + (m_panRect.height() - 3); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + } + else + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.x() > 0) + m_freqScaleZoomFactor += 0.01; + else if (dPos.x() < 0) + m_freqScaleZoomFactor -= 0.01; + + if (m_freqScaleZoomFactor > 1.0) m_freqScaleZoomFactor = 1.0; + if (m_freqScaleZoomFactor < 0.05) m_freqScaleZoomFactor = 0.05; + //if (m_freqScaleZoomFactor < 0.15) m_freqScaleZoomFactor = 0.15; + + m_mouseDownPos = pos; + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + else + setCursor(Qt::ArrowCursor); + + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + m_highlightFilter = false; + break; + + case filterRegionLow: + + setCursor(Qt::SizeHorCursor); + m_showFilterLeftBoundary = true; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterLowerFrequency = qRound(m_mouseDownFilterFrequencyLo - dFreq); + set->setRXFilter(this, m_receiver, m_filterLowerFrequency, m_filterUpperFrequency); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + + m_highlightFilter = false; + break; + + case filterRegionHigh: + + setCursor(Qt::SizeHorCursor); + m_showFilterRightBoundary = true; + if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterUpperFrequency = qRound(m_mouseDownFilterFrequencyHi - dFreq); + set->setRXFilter(this, m_receiver, m_filterLowerFrequency, m_filterUpperFrequency); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + + m_highlightFilter = false; + break; + + case filterRegion: + + setCursor(Qt::ArrowCursor); + m_displayCenterlineHeight = m_panRect.top() + (size().height() - 3); + + if (event->buttons() == Qt::LeftButton) { + + m_highlightFilter = true; + QPoint dPos = m_mouseDownPos - pos; + qreal dFreq = (qreal)(dPos.x() * m_sampleRate * m_freqScaleZoomFactor) / m_panRect.width(); + + m_filterUpperFrequency = qRound(m_mouseDownFilterFrequencyHi - dFreq); + m_filterLowerFrequency = qRound(m_mouseDownFilterFrequencyLo - dFreq); + set->setRXFilter(this, m_receiver, m_filterLowerFrequency, m_filterUpperFrequency); + +// if (m_displayTime.elapsed() >= 50) { +// +// m_displayTime.restart(); +// update(); +// } + } + m_showFilterLeftBoundary = false; + m_showFilterRightBoundary = false; + break; + + case elsewhere: + //GRAPHICS_DEBUG << "elsewhere"; + break; + } + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } +} + +void QGLReceiverPanel::keyPressEvent(QKeyEvent* event) { + + //GRAPHICS_DEBUG << "keyPressEvent"; + if (event->key() == Qt::Key_Control) { + + //m_keyCTRLpressed = true; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //printf("Ry %f\n",ry); + //ry+=10.0f; + } + else if (event->key() == Qt::Key_T) { + + //printf("Ry %f\n",ry); + //ry-=10.0f; + } + else if (event->key() == Qt::Key_P) { + + //drawTeapot = !drawTeapot; + } + else if (event->key() == Qt::Key_W) { + + //approach -= 0.1f; + } + else if (event->key() == Qt::Key_S) { + + //approach += 0.1f; + } + else { + + //m_keyCTRLpressed = false; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //event->ignore(); + } + + QWidget::keyPressEvent(event); + //updateGL(); + update(); +} + +//void QGLReceiverPanel::timerEvent(QTimerEvent *) { +// +// update(); +//} + +//******************************************************************** + +void QGLReceiverPanel::setSpectrumSize(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (m_dataEngineState == QSDR::DataEngineDown) { + + GRAPHICS_DEBUG << "set spectrum size to: " << value; + m_spectrumSize = value; + update(); + } +} + +void QGLReceiverPanel::setCtrFrequency(QObject *sender, int mode, int rx, long freq) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + //if (sender == this) return; + if (m_receiver != rx) return; + + if (m_peakHold) { + + //spectrumBufferMutex.lock(); + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-500.0); + //spectrumBufferMutex.unlock(); + } + + for (int i = 0; i < set->getNumberOfReceivers(); i++) { + + m_rxDataList[i].ctrFrequency = freq; + } + + //GRAPHICS_DEBUG << "set center F = " << freq; + m_centerFrequency = freq; + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + update(); +} + +void QGLReceiverPanel::setVFOFrequency(QObject *sender, int mode, int rx, long freq) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + //if (sender == this) return; + if (m_receiver != rx) return; + + if (m_peakHold) { + + //spectrumBufferMutex.lock(); + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-500.0); + //spectrumBufferMutex.unlock(); + } + + for (int i = 0; i < set->getNumberOfReceivers(); i++) { + + m_rxDataList[i].vfoFrequency = freq; + } + + //GRAPHICS_DEBUG << "set vfo F = " << freq; + m_vfoFrequency = freq; + if (m_vfoFrequency > m_centerFrequency + m_sampleRate/2) + m_vfoFrequency = m_centerFrequency + m_sampleRate/2; + else if (m_vfoFrequency < m_centerFrequency - m_sampleRate/2) + m_vfoFrequency = m_centerFrequency - m_sampleRate/2; + + m_deltaFrequency = m_centerFrequency - m_vfoFrequency; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + update(); +} + +void QGLReceiverPanel::setVfoToMidFrequency() { + + m_vfoFrequency = m_centerFrequency; + m_deltaFrequency = 0; + m_deltaF = 0; + + set->setVFOFrequency(this, 0, m_receiver, m_vfoFrequency); + set->setNCOFrequency(this, false, m_receiver, 0); +} + +void QGLReceiverPanel::setMidToVfoFrequency() { + + m_centerFrequency = m_vfoFrequency; + m_deltaFrequency = 0; + m_deltaF = 0; + + set->setCtrFrequency(this, 0, m_receiver, m_centerFrequency); + set->setNCOFrequency(this, false, m_receiver, 0); +} + +void QGLReceiverPanel::setFilterFrequencies(QObject *sender, int rx, qreal lo, qreal hi) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_filterLowerFrequency = lo; + m_filterUpperFrequency = hi; + m_filterChanged = true; + update(); +} + +void QGLReceiverPanel::setCurrentReceiver(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_currentReceiver = value; + m_panGridUpdate = true; + update(); +} + +void QGLReceiverPanel::freqRulerPositionChanged(QObject *sender, int rx, float pos) { + + Q_UNUSED (sender) + + if (rx == m_receiver) { + + m_freqRulerPosition = pos; + + setupDisplayRegions(size()); + update(); + } +} + +void QGLReceiverPanel::setSpectrumBuffer(int rx, const qVectorFloat& buffer) { + + if (m_receiver != rx) return; + + QVector specBuf(m_spectrumSize); + QVector waterBuf(m_spectrumSize); + waterBuf = buffer; + + + if (m_dataEngineState == QSDR::DataEngineUp) { + + if (m_spectrumAveraging) { + + spectrumBufferMutex.lock(); + specBuf = buffer; + averager->ProcessDBAverager(specBuf, specBuf); + computeDisplayBins(specBuf, waterBuf); + spectrumBufferMutex.unlock(); + } + else { + + specBuf = buffer; + if (m_dataEngineState == QSDR::DataEngineUp) + computeDisplayBins(specBuf, waterBuf); + } + } +} + +void QGLReceiverPanel::computeDisplayBins(QVector& buffer, QVector& waterfallBuffer) { + + //int m_sampleSize = 0; + int deltaSampleSize = 0; + int idx = 0; + int lIdx = 0; + int rIdx = 0; + qreal localMax; + + if (m_serverMode == QSDR::ChirpWSPRFile) { + + m_sampleSize = (int)floor(2 * BUFFER_SIZE * m_freqScaleZoomFactor); + deltaSampleSize = 2 * BUFFER_SIZE - m_sampleSize; + } + else { + + m_sampleSize = (int)floor(m_fftMult * m_spectrumSize * m_freqScaleZoomFactor); + deltaSampleSize = m_spectrumSize - m_sampleSize; + } + + if (m_receiver == 0) { + + if (m_sampleSize < 2048) { + + if (m_fftMult == 1) { + + GRAPHICS_DEBUG << "set sample size to 8192"; + set->setSampleSize(this, 0, 8192); + m_dBmPanLogGain += 6.0; + m_fftMult = 2; + + return; + } + else if (m_fftMult == 2) { + + GRAPHICS_DEBUG << "set sample size to 16384"; + set->setSampleSize(this, 0, 16384); + m_dBmPanLogGain += 6.0; + m_fftMult = 4; + + return; + } + else if (m_fftMult == 4) { + + GRAPHICS_DEBUG << "set sample size to 32768"; + set->setSampleSize(this, 0, 32768); + m_dBmPanLogGain += 6.0; + m_fftMult = 8; + + return; + } + } + else if (m_sampleSize > 4096) { + + if (m_fftMult == 2) { + + GRAPHICS_DEBUG << "set sample size to 4096"; + set->setSampleSize(this, 0, 4096); + m_dBmPanLogGain -= 6.0; + m_fftMult = 1; + + return; + } + else if (m_fftMult == 4) { + + GRAPHICS_DEBUG << "set sample size to 8192"; + set->setSampleSize(this, 0, 8192); + m_dBmPanLogGain -= 6.0; + m_fftMult = 2; + + return; + } + else if (m_fftMult == 8) { + + GRAPHICS_DEBUG << "set sample size to 16384"; + set->setSampleSize(this, 0, 16384); + m_dBmPanLogGain -= 6.0; + m_fftMult = 4; + + return; + } + } + } + + m_panScale = (qreal)(1.0 * m_sampleSize / m_panRectWidth); + m_scaleMultOld = m_scaleMult; + + if (m_panScale < 0.125) { + m_scaleMult = 0.0625; + } + else if (m_panScale < 0.25) { + m_scaleMult = 0.125; + } + else if (m_panScale < 0.5) { + m_scaleMult = 0.25; + } + else if (m_panScale < 1.0) { + m_scaleMult = 0.5; + } + else { + m_scaleMult = 1.0; + } + + m_panSpectrumBinsLength = (GLint)(m_scaleMult * m_panRectWidth); + + /*if (m_sampleSize != m_oldSampleSize) { + + GRAPHICS_DEBUG << "m_panSpectrumBinsLength = " << m_panSpectrumBinsLength; + GRAPHICS_DEBUG << "m_sampleSize = " << m_sampleSize; + GRAPHICS_DEBUG << "deltaSampleSize = " << deltaSampleSize; + GRAPHICS_DEBUG << ""; + + m_oldSampleSize = m_sampleSize; + }*/ + + if (m_scaleMultOld != m_scaleMult) { + + m_waterfallUpdate = true; + } + + m_waterfallPixel.clear(); + m_waterfallPixel.resize(4 * m_panRectWidth); + + m_panadapterBins.clear(); + + if (m_peakHoldBufferResize) { + + //spectrumBufferMutex.lock(); + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-300.0); + //spectrumBufferMutex.unlock(); + + m_peakHoldBufferResize = false; + } + + for (int i = 0; i < m_panSpectrumBinsLength; i++) { + + //qreal max; + idx = 0; + lIdx = (int)qFloor((qreal)(i * m_panScale / m_scaleMult)); + rIdx = (int)qFloor((qreal)(i * m_panScale / m_scaleMult) + m_panScale / m_scaleMult); + + // max value; later we try mean value also! + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + + if (buffer.at(j) > localMax) { + + localMax = buffer.at(j); + idx = j; + } + } + // shift the beginning of the bins by half of the difference between + // full spectrum size and reduced spectrum size due to zooming + idx += deltaSampleSize/2; + + QColor pColor; + if (m_mercuryAttenuator) { + + m_panadapterBins << buffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain - 20.0f; + pColor = getWaterfallColorAtPixel(waterfallBuffer.at(idx) - m_dBmPanLogGain - 20.0f); + } + else { + + m_panadapterBins << buffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain; + pColor = getWaterfallColorAtPixel(waterfallBuffer.at(idx) - m_dBmPanLogGain); + } + + if (m_peakHold && (m_panadapterBins.at(i) > m_panPeakHoldBins.at(i))) { + + m_panPeakHoldBins[i] = m_panadapterBins.at(i); + } + + + TGL_ubyteRGBA color; + color.red = (uchar)(pColor.red()); + color.green = (uchar)(pColor.green()); + color.blue = (uchar)(pColor.blue()); + color.alpha = 255; + + for (int j = 0; j < (int)(1/m_scaleMult); j++) { + + m_waterfallPixel[(int)(i/m_scaleMult) + j] = color; + } + } + m_waterfallDisplayUpdate = true; + update(); +} + +// get waterfall colors - taken from PowerSDR/KISS Konsole +QColor QGLReceiverPanel::getWaterfallColorAtPixel(qreal value) { + + QColor color; + //int r = 0; int g = 0; int b = 0; + int r, g, b; + int lowerThreshold = (int)m_dBmPanMin - m_waterfallOffsetLo; + int upperThreshold = (int)m_dBmPanMax + m_waterfallOffsetHi; + + float offset; + float globalRange; + float localRange; + float percent; + + switch (m_waterfallMode) { + + case (WaterfallColorMode) Simple: + + if (value <= lowerThreshold) + color = m_waterfallLoColor; + else + if (value >= upperThreshold) + color = QColor(255, 255, 255);//m_waterfallHiColor; + else { + + percent = (value - lowerThreshold) / (upperThreshold - lowerThreshold); + if (percent <= 0.5) { // use a gradient between low and mid colors + + percent *= 2; + + r = (int)((1 - percent) * m_waterfallLoColor.red() + percent * m_waterfallMidColor.red()); + g = (int)((1 - percent) * m_waterfallLoColor.green() + percent * m_waterfallMidColor.green()); + b = (int)((1 - percent) * m_waterfallLoColor.blue() + percent * m_waterfallMidColor.blue()); + } + else { // use a gradient between mid and high colors + + percent = (float)(percent - 0.5) * 2; + + r = (int)((1 - percent) * m_waterfallMidColor.red() + percent * 255);//m_waterfallHiColor.red()); + g = (int)((1 - percent) * m_waterfallMidColor.green() + percent * 255);//m_waterfallHiColor.green()); + b = (int)((1 - percent) * m_waterfallMidColor.blue() + percent * 255);//m_waterfallHiColor.blue()); + } + + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + color = QColor(r, g, b, m_waterfallAlpha); + } + + break; + + case (WaterfallColorMode) Enhanced: + + if (value <= lowerThreshold) + color = m_waterfallLoColor; + else + if (value >= upperThreshold) + color = m_waterfallHiColor; + else { + + offset = value - lowerThreshold; + globalRange = offset / m_waterfallColorRange; // value from 0.0 to 1.0 where 1.0 is high and 0.0 is low. + + if (globalRange < (float)2/9) { // background to blue + + localRange = globalRange / ((float)2/9); + r = (int)((1.0 - localRange) * m_waterfallLoColor.red()); + g = (int)((1.0 - localRange) * m_waterfallLoColor.green()); + b = (int)(m_waterfallLoColor.blue() + localRange * (255 - m_waterfallLoColor.blue())); + } + else + if (globalRange < (float)3/9) { // blue to blue-green + + localRange = (globalRange - (float)2/9) / ((float)1/9); + r = 0; + g = (int)(localRange * 255); + b = 255; + } + else + if (globalRange < (float)4/9) { // blue-green to green + + localRange = (globalRange - (float)3/9) / ((float)1/9); + r = 0; + g = 255; + b = (int)((1.0 - localRange) * 255); + } + else + if (globalRange < (float)5/9) { // green to red-green + + localRange = (globalRange - (float)4/9) / ((float)1/9); + r = (int)(localRange * 255); + g = 255; + b = 0; + } + else + if (globalRange < (float)7/9) { // red-green to red + + localRange = (globalRange - (float)5/9) / ((float)2/9); + r = 255; + g = (int)((1.0 - localRange) * 255); + b = 0; + } + else + if (globalRange < (float)8/9) { // red to red-blue + + localRange = (globalRange - (float)7/9) / ((float)1/9); + r = 255; + g = 0; + b = (int)(localRange * 255); + } + else { // red-blue to purple end + + localRange = (globalRange - (float)8/9) / ((float)1/9); + r = (int)((0.75 + 0.25 * (1.0 - localRange)) * 255); + g = (int)(localRange * 255 * 0.5); + b = 255; + } + if (r > 255) r = 255; + if (g > 255) g = 255; + if (b > 255) b = 255; + if (r < 0) r = 0; + if (g < 0) g = 0; + if (b < 0) b = 0; + color = QColor(r, g, b, m_waterfallAlpha); + } + + break; + } + + return color; +} + +void QGLReceiverPanel::setFramesPerSecond(QObject* sender, int rx, int value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_fps = value; + + m_secWaterfallMin = -(1.0/m_fps) * m_secScaleWaterfallRect.height(); + m_secScaleWaterfallRenew = true; + m_secScaleWaterfallUpdate = true; + update(); +} + +void QGLReceiverPanel::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + Q_UNUSED (hwmode) + Q_UNUSED (state) + + if (m_dataEngineState != state) + m_dataEngineState = state; + + if (state == QSDR::DataEngineDown) + m_fftMult = 1; + // m_panadapterBins.clear(); + + if (state == QSDR::DataEngineDown) + averager->clearBuffer(); + + if (m_serverMode != mode) + m_serverMode = mode; + +// if (m_serverMode == mode) +// return; +// else +// m_serverMode = mode; + + //resizeGL(width(), height()); + m_displayTime.restart(); + + update(); +} + +void QGLReceiverPanel::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode) +{ + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + + if (m_panMode != panMode) + m_panMode = panMode; + + if (m_waterfallMode != waterfallColorMode) + m_waterfallMode = waterfallColorMode; + + update(); +} + + void QGLReceiverPanel::setSpectrumAveraging(QObject* sender, int rx, bool value) { + + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + spectrumBufferMutex.lock(); + + if (m_spectrumAveraging == value) + return; + else + m_spectrumAveraging = value; + + spectrumBufferMutex.unlock(); + } + +void QGLReceiverPanel::setSpectrumAveragingCnt(int value) { + + spectrumBufferMutex.lock(); + + //m_tmp.clear(); + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); + + m_specAveragingCnt = value; + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + + spectrumBufferMutex.unlock(); +} + +void QGLReceiverPanel::setPanGridStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + spectrumBufferMutex.lock(); + + if (m_panGrid == value) + return; + else + m_panGrid = value; + + spectrumBufferMutex.unlock(); + update(); +} + +void QGLReceiverPanel::setPeakHoldStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + spectrumBufferMutex.lock(); + + if (m_peakHold == value) + return; + else + m_peakHold = value; + + m_panPeakHoldBins.clear(); + m_panPeakHoldBins.resize(m_panSpectrumBinsLength); + m_panPeakHoldBins.fill(-500.0); + spectrumBufferMutex.unlock(); +} + +void QGLReceiverPanel::setPanLockedStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + if (m_panLocked == value) + return; + else + m_panLocked = value; + + update(); +} + +void QGLReceiverPanel::setClickVFOStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + if (m_clickVFO == value) + return; + else + m_clickVFO = value; + + update(); +} + +void QGLReceiverPanel::setHairCrossStatus(bool value, int rx) { + + if (m_receiver != rx) return; + + if (m_crossHair == value) + return; + else + m_crossHair = value; + + update(); +} + +void QGLReceiverPanel::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; + m_deltaF = (qreal)(1.0*m_deltaFrequency/m_sampleRate); + + m_freqScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + m_filterChanged = true; + + update(); +} + +void QGLReceiverPanel::setMercuryAttenuator(QObject* sender, HamBand band, int value) { + + Q_UNUSED(sender) + Q_UNUSED(band) + + m_mercuryAttenuator = value; + update(); +} + +void QGLReceiverPanel::setPanadapterColors() { + + m_spectrumColorsChanged = true; + + mutex.lock(); + m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0); + + m_red = (GLfloat)(set->getPanadapterColors().panLineColor.red() / 256.0); + m_green = (GLfloat)(set->getPanadapterColors().panLineColor.green() / 256.0); + m_blue = (GLfloat)(set->getPanadapterColors().panLineColor.blue() / 256.0); + + m_redF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.red() / 256.0); + m_greenF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.green() / 256.0); + m_blueF = (GLfloat)(set->getPanadapterColors().panLineFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + m_waterfallMidColor = set->getPanadapterColors().waterfallColor.toRgb() ; + + QColor gridColor = m_gridColor; + m_gridColor = set->getPanadapterColors().gridLineColor; + + if (gridColor != m_gridColor) { + + m_redGrid = (GLfloat)(m_gridColor.red()/256.0); + m_greenGrid = (GLfloat)(m_gridColor.green()/256.0); + m_blueGrid = (GLfloat)(m_gridColor.blue()/256.0); + + m_panGridUpdate = true; + } + mutex.unlock(); + + update(); +} + +void QGLReceiverPanel::setWaterfallOffesetLo(int rx, int value) { + + if (m_receiver != rx) return; + + m_waterfallOffsetLo = value; + update(); +} + +void QGLReceiverPanel::setWaterfallOffesetHi(int rx, int value) { + + if (m_receiver != rx) return; + + m_waterfallOffsetHi = value; + update(); +} + +void QGLReceiverPanel::setdBmScaleMin(int rx, qreal value) { + + if (m_receiver != rx) return; + + m_dBmPanMin = value; + + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + + update(); +} + +void QGLReceiverPanel::setdBmScaleMax(int rx, qreal value) { + + if (m_receiver != rx) return; + + m_dBmPanMax = value; + + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + + update(); +} + +void QGLReceiverPanel::setMouseWheelFreqStep(QObject *sender, int rx, qreal step) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_mouseWheelFreqStep = step; + update(); +} + +void QGLReceiverPanel::setHamBand(QObject *sender, int rx, bool byButton, HamBand band) { + + Q_UNUSED(sender) + + if (m_receiver != rx || !byButton) return; + // we change the dBm-scale only, if the frequency is changed by changing the band by button. + // That is, if we change band by changing the frequency, the dBm scale stays constant. + + //m_panLocked = false; + //m_deltaFrequency = 0; + //m_deltaF = 0; + + m_rxDataList[m_receiver].hamBand = band; + //m_dspModeString = set->getDSPModeString(m_rxDataList[m_receiver].dspMode); + + m_dBmPanMin = m_rxDataList.at(m_receiver).dBmPanScaleMinList.at(band); + m_dBmPanMax = m_rxDataList.at(m_receiver).dBmPanScaleMaxList.at(band); + + m_dBmScalePanadapterUpdate = true; + m_panGridUpdate = true; + m_peakHoldBufferResize = true; + + update(); +} + +void QGLReceiverPanel::setADCStatus(int value) { + + m_adcStatus = value; + update(); + + QTimer::singleShot(50, this, SLOT(updateADCStatus())); +} + +void QGLReceiverPanel::updateADCStatus() { + + if (m_dataEngineState == QSDR::DataEngineUp) + m_adcStatus = 1; + else + m_adcStatus = 0; + + //qDebug() << "m_adcStatus: " << m_adcStatus; + update(); +} + +void QGLReceiverPanel::setAGCLineLevels(QObject *sender, int rx, qreal thresh, qreal hang) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcThresholdOld == thresh && m_agcHangLevelOld == hang) return; + + m_agcThresholdOld = thresh; + m_agcHangLevelOld = hang; + //GRAPHICS_DEBUG << "m_agcThresholdOld = " << m_agcThresholdOld; + //GRAPHICS_DEBUG << "m_agcHangLevelOld = " << m_agcHangLevelOld; +} + +void QGLReceiverPanel::setAGCLineFixedLevel(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + if (m_agcFixedGain == value) return; + + m_agcFixedGain = value; + //GRAPHICS_DEBUG << "m_agcFixedGain = " << m_agcFixedGain; +} + +void QGLReceiverPanel::setAGCMode(QObject *sender, int rx, AGCMode mode, bool hangEnabled) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + if (m_agcHangEnabled == hangEnabled && m_agcMode == mode) return; + + m_agcMode = mode; + m_agcModeString = set->getAGCModeString(m_receiver); + m_agcHangEnabled = hangEnabled; + GRAPHICS_DEBUG << "m_agcHangEnabled = " << m_agcHangEnabled; + + update(); +} + +void QGLReceiverPanel::setAGCLinesStatus(QObject* sender, bool value, int rx) { + + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + m_showAGCLines = value; + + update(); +} + +void QGLReceiverPanel::setDSPMode(QObject* sender, int rx, DSPMode mode) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + + m_dspMode = mode; + m_dspModeString = set->getDSPModeString(m_dspMode); + + update(); +} + +void QGLReceiverPanel::showRadioPopup(bool value) { + + Q_UNUSED (value) + + radioPopup->showPopupWidget(this, QCursor::pos()); +} + +//void QGLReceiverPanel::setAGCHangEnabled(QObject *sender, int rx, bool hangEnabled) { +// +// Q_UNUSED(sender) +// +// if (m_receiver != rx) return; +// +// if (m_agcHangEnabled == hangEnabled) return; +// m_agcHangEnabled = hangEnabled; +// GRAPHICS_DEBUG << "m_agcHangEnabled = " << m_agcHangEnabled; +// +// update(); +//} diff --git a/Source/src/GL/cusdr_oglReceiverPanel.h b/Source/src/GL/cusdr_oglReceiverPanel.h new file mode 100644 index 0000000..f234ffa --- /dev/null +++ b/Source/src/GL/cusdr_oglReceiverPanel.h @@ -0,0 +1,432 @@ +/** +* @file cusdr_oglReceiverPanel.h +* @brief receiver panel header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-03-14 +*/ + +/* + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_QGL_RECEIVERPANEL_H +#define _CUSDR_QGL_RECEIVERPANEL_H + +#include "cusdr_oglUtils.h" +#include "cusdr_oglInfo.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" +#include "Util/cusdr_buttons.h" +#include "cusdr_oglText.h" +#include "QtDSP/qtdsp_dualModeAverager.h" +#include "cusdr_radioPopupWidget.h" + +#include +#include + + +#ifdef LOG_GRAPHICS +# define GRAPHICS_DEBUG qDebug().nospace() << "ReceiverPanel::\t" +#else +# define GRAPHICS_DEBUG nullDebug() +#endif + + +class QGLReceiverPanel : public QGLWidget { + + Q_OBJECT + +public: + QGLReceiverPanel(QWidget *parent = 0, int rx = 0); + ~QGLReceiverPanel(); + +public slots: + QSize minimumSizeHint() const; + QSize sizeHint() const; + + //void setSpectrumBuffer(const float* buffer, int size); + //void setSpectrumBuffer(const qVectorFloat& buffer); + void setSpectrumBuffer(int rx, const qVectorFloat& buffer); + void setCtrFrequency(QObject* sender, int mode, int rx, long freq); + void setVFOFrequency(QObject* sender, int mode, int rx, long freq); + +protected: + void initializeGL(); + void resizeGL(int iWidth, int iHeight); + void paintGL(); + + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseDoubleClickEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event ); + void keyPressEvent(QKeyEvent* event); + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + CFonts* fonts; + TFonts m_fonts; + + DualModeAverager* averager; + RadioPopupWidget* radioPopup; + AGCMode m_agcMode; + DSPMode m_dspMode; + PanGraphicsMode m_panMode; + WaterfallColorMode m_waterfallMode; + + QTime m_displayTime; + QTime m_resizeTime; + QTime freqChangeTimer; + QTime peakHoldTimer; + + QString m_bandText; + QString m_agcModeString; + QString m_dspModeString; + QString m_filterWidthString; + + TScale m_frequencyScale; + TScale m_dBmScale; + TScale m_secScale; + + QList m_rxDataList; + + QVector m_panadapterBins; + QVector m_panPeakHoldBins; + QVarLengthArray m_waterfallPixel; + + QQueue > specAv_queue; + + QGLFramebufferObject* m_frequencyScaleFBO; + QGLFramebufferObject* m_dBmScaleFBO; + QGLFramebufferObject* m_panadapterGridFBO; + QGLFramebufferObject* m_textureFBO; + QGLFramebufferObject* m_waterfallLineFBO; + QGLFramebufferObject* m_waterfallFBO; + QGLFramebufferObject* m_secScaleWaterfallFBO; + + QRect m_panRect; + QRect m_dBmScalePanRect; + QRect m_freqScalePanRect; + QRect m_waterfallRect; + QRect m_secScaleWaterfallRect; + QRect m_filterRect; + QRect m_agcButtonRect; + QRect m_lockedPanButtonRect; + QRect m_vfoToMidButtonRect; + QRect m_midToVfoButtonRect; + QRect m_clickVFOButtonRect; + + OGLText* m_oglTextTiny; + OGLText* m_oglTextSmall; + OGLText* m_oglTextNormal; + OGLText* m_oglTextFreq1; + OGLText* m_oglTextFreq2; + OGLText* m_oglTextBig1; + OGLText* m_oglTextBig2; + OGLText* m_oglTextHuge; + + QPoint m_mousePos; + QPoint m_oldMousePos; + QPoint m_mouseLastPos; + QPoint m_mouseDownPos; + QPoint m_rulerMouseDownPos; + QPoint m_cameraAngle; + + QColor m_waterfallLoColor; + QColor m_waterfallHiColor; + QColor m_waterfallMidColor; + QColor m_gridColor; + QColor m_darkColor; + + QMutex mutex; + QMutex spectrumBufferMutex; + + enum Region { + + freqScalePanadapterRegion, + panadapterRegion, + dBmScalePanadapterRegion, + waterfallRegion, + filterRegion, + filterRegionLow, + filterRegionHigh, + agcButtonRegion, + agcThresholdLine, + agcHangLine, + agcFixedGainLine, + //lockedPanButtonRegion, + //vfoToMidButtonRegion, + //midToVfoButtonRegion, + //clickVfoButtonRegion, + elsewhere, + out + }; + + GLint m_panRectWidth; + GLint m_panSpectrumBinsLength; + + GLint m_filterLeft; + GLint m_filterRight; + GLint m_filterTop; + GLint m_filterBottom; + + GLfloat m_agcThresholdPixel; + GLfloat m_agcHangLevelPixel; + GLfloat m_agcFixedGainLevelPixel; + + GLfloat m_bkgRed; + GLfloat m_bkgGreen; + GLfloat m_bkgBlue; + + GLfloat m_red; + GLfloat m_green; + GLfloat m_blue; + + GLfloat m_redF; + GLfloat m_greenF; + GLfloat m_blueF; + + + GLfloat m_redST; + GLfloat m_greenST; + GLfloat m_blueST; + + GLfloat m_redSB; + GLfloat m_greenSB; + GLfloat m_blueSB; + + GLfloat m_redGrid; + GLfloat m_greenGrid; + GLfloat m_blueGrid; + + unsigned int timer; + + int m_bigHeight; + int m_bigWidth; + int m_receiver; + //int m_frequencyRxOnRx; + int m_spectrumSize; + int m_sampleSize; + int m_oldSampleSize; + int m_oldWidth; + int m_oldPanRectHeight; + int m_cnt; + int m_specAveragingCnt; + int m_currentReceiver; + int m_waterfallAlpha; + int m_waterfallOffsetLo; + int m_waterfallOffsetHi; + int m_waterfallColorRange; + int m_freqRulerDisplayWidth; + int m_oldWaterfallWidth; + int m_displayTop; + int m_dBmPanLogGain; + int m_panSpectrumMinimumHeight; + int m_mouseRegion; + int m_oldMouseRegion; + int m_oldMousePosX; + int m_snapMouse; + int m_panDisplayMode; + int m_sampleRate; + int m_downRate; + int m_mercuryAttenuator; + int m_haircrossOffsetRight; + int m_haircrossOffsetLeft; + int m_haircrossMaxRight; + int m_haircrossMinTop; + int m_displayCenterlineHeight; + int m_waterfallLineCnt; + int m_adcStatus; + int m_fps; + int m_filterWidth; + int m_fftMult; + + long m_centerFrequency; + long m_vfoFrequency; + long m_deltaFrequency; + long m_otherFrequency; + //long m_oldFreq; + + bool m_smallSize; + bool m_spectrumVertexColorUpdate; + bool m_dBmScalePanadapterRenew; + bool m_dBmScalePanadapterUpdate; + bool m_freqScalePanadapterRenew; + bool m_freqScalePanadapterUpdate; + bool m_secScaleWaterfallUpdate; + bool m_secScaleWaterfallRenew; + bool m_panGridRenew; + bool m_panGridUpdate; + bool m_waterfallUpdate; + bool m_waterfallDisplayUpdate; + bool m_distRulerUpdate; + bool m_newWidebandPanFreqRuler; + bool m_spectrumColorsChanged; + bool m_spectrumAveraging; + //bool m_spectrumAveragingOld; + bool m_crossHair; + bool m_crossHairCursor; + bool m_panGrid; + bool m_peakHold; + bool m_filterChanged; + bool m_showFilterLeftBoundary; + bool m_showFilterRightBoundary; + bool m_highlightFilter; + bool m_peakHoldBufferResize; + bool m_showAGCLines; + bool m_agcHangEnabled; + bool m_dragMouse; + bool m_panLocked; + bool m_clickVFO; + + qreal m_yScaleFactor; + qreal m_panFrequencyScale; + qreal m_freqScaleZoomFactor; + qreal m_dBmPanMin; + qreal m_dBmPanMax; + qreal m_dBmPanDelta; + qreal m_mouseWheelFreqStep; + qreal m_secWaterfallMin; + qreal m_secWaterfallMax; + qreal m_panScale; + qreal m_scaleMult; + qreal m_scaleMultOld; + qreal m_filterLowerFrequency; + qreal m_filterUpperFrequency; + qreal m_mouseDownFilterFrequencyLo; + qreal m_mouseDownFilterFrequencyHi; + qreal m_filterLo; + qreal m_filterHi; + qreal m_deltaF; + qreal m_agcThresholdNew; + qreal m_agcThresholdOld; + qreal m_mouseDownAGCThreshold; + qreal m_agcHangLevelNew; + qreal m_agcHangLevelOld; + qreal m_mouseDownAGCHangLevel; + qreal m_agcFixedGain; + qreal m_mouseDownFixedGainLevel; + + float m_scale; + float m_cameraDistance; + float m_freqRulerPosition; + + QVector m_tmp; + + + //****************************************************************** + void setupConnections(); + + QColor getWaterfallColorAtPixel(qreal value); + + void saveGLState(); + void restoreGLState(); + + // drawing + void paintReceiverDisplay(); + void paint3DPanadapterMode(); + + void drawPanadapter(); + void drawPanVerticalScale(); + void drawPanHorizontalScale(); + void drawPanadapterGrid(); + void drawPanFilter(); + void drawCenterLine(); + void drawWaterfall(); + void drawWaterfallVerticalScale(); + void drawCrossHair(); + void drawReceiverInfo(); + void drawAGCControl(); + void drawVFOControl(); + + void renderPanVerticalScale(); + void renderPanHorizontalScale(); + void renderPanadapterGrid(); + void renderWaterfallVerticalScale(); + + //void computeDisplayBins(const QVector& panBuffer, const float* waterfallBuffer); + //void computeDisplayBins(QVector &buffer); + void computeDisplayBins(QVector& panBuffer, QVector& waterfallBuffer); + void showText(float x, float y, float z, const QString &text, bool smallText); + void showRadioPopup(bool value); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setSpectrumSize(QObject *sender, int value); + void setCurrentReceiver(QObject *sender, int value); + void setHamBand(QObject *sender, int rx, bool byButton, HamBand band); + void setFilterFrequencies(QObject *sender, int rx, qreal lo, qreal hi); + void setMercuryAttenuator(QObject* sender, HamBand band, int value); + void setupDisplayRegions(QSize size); + + void setSpectrumAveraging(QObject* sender, int rx, bool value); + void setSpectrumAveragingCnt(int value); + void setVfoToMidFrequency(); + void setMidToVfoFrequency(); + void setPanGridStatus(bool value, int rx); + void setPeakHoldStatus(bool value, int rx); + void setPanLockedStatus(bool value, int rx); + void setClickVFOStatus(bool value, int rx); + void setHairCrossStatus(bool value, int rx); + void setPanadapterColors(); + void getRegion(QPoint p); + void freqRulerPositionChanged(QObject *sender, int rx, float pos); + void sampleRateChanged(QObject *sender, int value); + void setWaterfallOffesetLo(int rx, int value); + void setWaterfallOffesetHi(int rx, int value); + void setdBmScaleMin(int rx, qreal value); + void setdBmScaleMax(int rx, qreal value); + void setMouseWheelFreqStep(QObject *, int, qreal); + + void setADCStatus(int value); + void updateADCStatus(); + void setFramesPerSecond(QObject* sender, int rx, int value); + void setDSPMode(QObject* sender, int rx, DSPMode mode); + void setAGCMode(QObject* sender, int rx, AGCMode mode, bool hangEnabled); + void setAGCLineLevels(QObject* sender, int rx, qreal thresh, qreal hang); + void setAGCLineFixedLevel(QObject* sender, int rx, qreal value); + void setAGCLinesStatus(QObject* sender, bool value, int rx); + //void setAGCHangEnabled(QObject *sender, int rx, bool hangEnabled); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString msg); + void coordChanged(int x,int y); +}; + +#endif // _CUSDR_QGL_RECEIVERPANEL_H diff --git a/Source/src/GL/cusdr_oglText.cpp b/Source/src/GL/cusdr_oglText.cpp new file mode 100644 index 0000000..2466b38 --- /dev/null +++ b/Source/src/GL/cusdr_oglText.cpp @@ -0,0 +1,282 @@ +/** +* @file cusdr_oglText.cpp +* @brief OpenGL Text generation class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-18 +*/ + +/* + * adapted from the MIFit project: http://code.google.com/p/mifit + * + * Copyright 2012 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cusdr_oglText.h" + +const int TEXTURE_SIZE = 256; + +struct CharData { + + GLuint textureId; + uint width; + uint height; + GLfloat s[2]; + GLfloat t[2]; +}; + +struct OGLTextPrivate { + + OGLTextPrivate(const QFont &f); + ~OGLTextPrivate(); + + void allocateTexture(); + CharData &createCharacter(QChar c); + + QFont font; + QFontMetrics fontMetrics; + + QHash characters; + QList textures; + + GLint xOffset; + GLint yOffset; +}; + +OGLTextPrivate::OGLTextPrivate(const QFont &f) + : font(f), fontMetrics(f), xOffset(0), yOffset(0) {} + +OGLTextPrivate::~OGLTextPrivate() { + + foreach (GLuint texture, textures) + glDeleteTextures(1, &texture); +} + +void OGLTextPrivate::allocateTexture() { + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + + // the texture ends at the edges (clamp) + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + + // select modulate to mix texture with color for shading + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + QImage image(TEXTURE_SIZE, TEXTURE_SIZE, QImage::Format_ARGB32); + image.fill(Qt::transparent); + image = QGLWidget::convertToGLFormat(image); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + //glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_SIZE, TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits()); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, TEXTURE_SIZE, TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, image.bits()); + + textures += texture; +} + +CharData &OGLTextPrivate::createCharacter(QChar c) { + + ushort unicodeC = c.unicode(); + if (characters.contains(unicodeC)) + return characters[unicodeC]; + + if (textures.empty()) + allocateTexture(); + + GLuint texture = textures.last(); + + GLsizei width = fontMetrics.width(c); + GLsizei height = fontMetrics.height(); + + QPixmap pixmap(width, height); + pixmap.fill(Qt::transparent); + + /*QImage image(width, height, QImage::Format_ARGB32_Premultiplied); + if (!image.isNull()) { + + image.fill(Qt::transparent); + + QPainter p(&image); + if (&font) p.setFont(this->font); + }*/ + + QPainter painter; + //const QPainter::CompositionMode comp_mode = painter.compositionMode(); + //painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.begin(&pixmap); + //painter.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing); + painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing, false); + painter.setFont(font); + painter.setPen(Qt::white); + + //painter.drawText(0, fontMetrics.ascent(), c); + painter.drawText(pixmap.rect(), Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignCenter, c); + painter.end(); + + + QImage image = QGLWidget::convertToGLFormat(pixmap.toImage()); + glBindTexture(GL_TEXTURE_2D, texture); + glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height, GL_RGBA, GL_UNSIGNED_BYTE, image.bits()); + + CharData& character = characters[unicodeC]; + character.textureId = texture; + character.width = width; + character.height = height; + character.s[0] = static_cast(xOffset) / TEXTURE_SIZE; + character.t[0] = static_cast(yOffset) / TEXTURE_SIZE; + character.s[1] = static_cast(xOffset + width) / TEXTURE_SIZE; + character.t[1] = static_cast(yOffset + height) / TEXTURE_SIZE; + + xOffset += width; + if (xOffset + fontMetrics.maxWidth() >= TEXTURE_SIZE) { + + xOffset = 1; + yOffset += height; + } + if (yOffset + fontMetrics.height() >= TEXTURE_SIZE) { + + allocateTexture(); + yOffset = 1; + } + return character; +} + + + +OGLText::OGLText(const QFont &f) : d(new OGLTextPrivate(f)) {} + + +OGLText::~OGLText() { + + delete d; +} + +QFont OGLText::font() const +{ + return d->font; +} + +QFontMetrics OGLText::fontMetrics() const { + + return d->fontMetrics; +} + +//! Renders text at given x, y. +void OGLText::renderText(float x, float y, const QString &text) { + + const bool GL_TEXTURE_2D_wasEnabled = glIsEnabled(GL_TEXTURE_2D); + GLint prev_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev_texture); + GLint prev_shade_model; glGetIntegerv(GL_SHADE_MODEL, &prev_shade_model); + + glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT); + glPushMatrix(); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (prev_shade_model != GL_FLAT) glShadeModel(GL_FLAT); + if (!GL_TEXTURE_2D_wasEnabled) glEnable(GL_TEXTURE_2D); + + GLuint texture = 0; + glTranslatef(x, y, 0); + + for (int i = 0; i < text.length(); ++i) { + + //if (text.length() > 80) + // qDebug() << "********************* OK"; + + CharData &c = d->createCharacter(text.at(i)); + if (texture != c.textureId) { + + texture = c.textureId; + glBindTexture(GL_TEXTURE_2D, texture); + } + + glBegin(GL_QUADS); + glTexCoord2f(c.s[0], c.t[0]); glVertex2f(0, c.height); + glTexCoord2f(c.s[1], c.t[0]); glVertex2f(c.width, c.height); + glTexCoord2f(c.s[1], c.t[1]); glVertex2f(c.width, 0); + glTexCoord2f(c.s[0], c.t[1]); glVertex2f(0, 0); + glEnd(); + + glTranslatef(c.width, 0, 0); + } + + glShadeModel(prev_shade_model); + glBindTexture(GL_TEXTURE_2D, prev_texture); + if (!GL_TEXTURE_2D_wasEnabled) glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + glPopAttrib(); +} + +void OGLText::renderText(float x, float y, float z, const QString &text) { + + const bool GL_TEXTURE_2D_wasEnabled = glIsEnabled(GL_TEXTURE_2D); + GLint prev_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &prev_texture); + GLint prev_shade_model; glGetIntegerv(GL_SHADE_MODEL, &prev_shade_model); + + glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TEXTURE_BIT); + glPushMatrix(); + glEnable(GL_TEXTURE_2D); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + if (prev_shade_model != GL_FLAT) glShadeModel(GL_FLAT); + if (!GL_TEXTURE_2D_wasEnabled) glEnable(GL_TEXTURE_2D); + + GLuint texture = 0; + glTranslatef(x, y, 0); + for (int i = 0; i < text.length(); ++i) { + + CharData &c = d->createCharacter(text.at(i)); + if (texture != c.textureId) { + + texture = c.textureId; + glBindTexture(GL_TEXTURE_2D, texture); + } + + /*glBegin(GL_QUADS); + glTexCoord2f(c.s[0], c.t[0]); glVertex2f(0, c.height); + glTexCoord2f(c.s[1], c.t[0]); glVertex2f(c.width, c.height); + glTexCoord2f(c.s[1], c.t[1]); glVertex2f(c.width, 0); + glTexCoord2f(c.s[0], c.t[1]); glVertex2f(0, 0); + glEnd();*/ + glBegin(GL_QUADS); + glTexCoord2f(c.s[0], c.t[0]); glVertex3f(0, c.height, z); + glTexCoord2f(c.s[1], c.t[0]); glVertex3f(c.width, c.height, z); + glTexCoord2f(c.s[1], c.t[1]); glVertex3f(c.width, 0, z); + glTexCoord2f(c.s[0], c.t[1]); glVertex3f(0, 0, z); + glEnd(); + + glTranslatef(c.width, 0, 0); + } + + glShadeModel(prev_shade_model); + glBindTexture(GL_TEXTURE_2D, prev_texture); + if (!GL_TEXTURE_2D_wasEnabled) glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + glPopAttrib(); +} diff --git a/Source/src/GL/cusdr_oglText.h b/Source/src/GL/cusdr_oglText.h new file mode 100644 index 0000000..3101c70 --- /dev/null +++ b/Source/src/GL/cusdr_oglText.h @@ -0,0 +1,63 @@ +/** +* @file cusdr_oglText.h +* @brief OpenGL Text generation header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-18 +*/ + +/* + * adapted from the MIFit project: http://code.google.com/p/mifit + * + * Copyright 2012 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_OGL_TEXT_H +#define _CUSDR_OGL_TEXT_H + +#include "cusdr_oglUtils.h" +#include "cusdr_oglInfo.h" +#include "cusdr_settings.h" + +#include + +class QChar; +class QFont; +class QFontMetrics; +class QString; + +class OGLTextPrivate; + +class OGLText { + +public: + OGLText(const QFont &f); + virtual ~OGLText(); + + QFont font() const; + QFontMetrics fontMetrics() const; + + void renderText(float x, float y, const QString &text); + void renderText(float x, float y, float z, const QString &text); + +private: + Q_DISABLE_COPY(OGLText) + + OGLTextPrivate *const d; +}; + +#endif // _CUSDR_OGL_TEXT_H diff --git a/Source/src/GL/cusdr_oglUtils.h b/Source/src/GL/cusdr_oglUtils.h new file mode 100644 index 0000000..7fb7044 --- /dev/null +++ b/Source/src/GL/cusdr_oglUtils.h @@ -0,0 +1,899 @@ +/** +* @file cusdr_oglUtils.h +* @brief Utils header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-11-17 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_OPENGLTYPES_H +#define _CUSDR_OPENGLTYPES_H + +#include +//#include +//#include +//#include +//#include +#include +#include + +#define GL_CLAMP_TO_EDGE 0x812F + + +typedef struct _gl2i { + + GLint x; + GLint y; + +} TGL2int; + +typedef struct _gl3i { + + GLint x; + GLint y; + GLint z; + +} TGL3int; + +typedef struct _gl2f { + + GLfloat x; + GLfloat y; + +} TGL2float; + +typedef struct _gl3f { + + GLfloat x; + GLfloat y; + GLfloat z; + +} TGL3float; + +typedef struct _ucharRGBA { + + uchar red; + uchar green; + uchar blue; + uchar alpha; + +} ucharRGBA; + +typedef struct _glubyteRGBA { + + GLubyte red; + GLubyte green; + GLubyte blue; + GLubyte alpha; + +} TGL_ubyteRGBA; + +typedef struct _scaleSteps { + + double smallStep; + double bigStep; + +} TScaleSteps; + +typedef struct _scale { + + QList mainPointPositions; + QList subPointPositions; + + QList mainPoints; + QList subPoints; + +} TScale; + + +struct s_glRGBA_float { + + GLfloat r, g, b, a; + + s_glRGBA_float() : r(0), g(0), b(0), a(0) {} + + s_glRGBA_float(GLfloat red, GLfloat grn, GLfloat blu, GLfloat alpha) : r(red), g(grn), b(blu), a(alpha) {} +}; + +struct s_glRGBA_uByte { + + GLubyte r, g, b, a; + + s_glRGBA_uByte() : r(0), g(0), b(0), a(0) {} + + s_glRGBA_uByte(GLubyte red, GLubyte grn, GLubyte blu, GLubyte alpha) : r(red), g(grn), b(blu), a(alpha) {} +}; + +typedef struct _widebandDisplayData { + + QSize size; + + QRect widebandPanRect; + QRect freqScaleWidebandPanRect; + QRect dBmScaleWidebandPanRect; + + QVector widebandPanBins; + + qreal dBmPanMin; + qreal dBmPanMax; + qreal scaleMult; + qreal freqScaleZoomFactor; + + long frequency; + + bool freqScaleWidebandUpdate; + bool freqScaleWidebandRenew; + bool dBmScaleWidebandUpdate; + bool dBmScaleWidebandRenew; + bool widebandPanGridUpdate; + bool widebandPanGridRenew; + +} TWideBandDisplayData; + +//************************************************************** +inline QString frequencyString(double frequency, bool addPlusSign = false) { + + QString str(""); + + double f = qAbs(frequency); + + if (f >= 1e9) { + + str = QString::number(f / 1e9, 'f', 6); + str.insert(str.size() - 3, '.'); + str += " GHz"; + } + else + if (f >= 1e6) { + + str = QString::number(f / 1e6, 'f', 6 + 1); + str.insert(str.size() - 4, '.'); + str.insert(str.size() - 1, '.'); + str += " MHz"; + } + else + if (f >= 1e3) { + + str = QString::number(f / 1e3, 'f', 3 + 1); + str.insert(str.size() - 1, '.'); + str += " kHz"; + } + else { + + str = QString::number(f, 'f', 1) + "Hz"; + } + + if (frequency < 0) str = '-' + str; + else + if (frequency > 0 && addPlusSign) str = '+' + str; + + return str; +} + +inline int nextPowerOfTwo(int value) { + + value--; + value |= value >> 1; + value |= value >> 2; + value |= value >> 4; + value |= value >> 8; + value |= value >> 16; + ++value; + return value; +} + +inline TScaleSteps getXScale(double size) { + + TScaleSteps s; + + qint64 base = 1; + int mult = 1; + while (size > 10.0f) { + size /= 10; + base *= 10; + } + + if (size < 2) mult = 2; + else if (size < 5) mult = 5; + else mult = 10; + + s.bigStep = base * mult; + switch (mult) { + + case 1: s.smallStep = s.bigStep / 5; break; + case 2: s.smallStep = s.bigStep / 2; break; + case 5: s.smallStep = s.bigStep / 5; break; + case 10: s.smallStep = s.bigStep / 5; break; + } + return s; +} + +inline TScaleSteps getXScale(double size, float scale) { + + TScaleSteps s; + + qint64 base = 1; + int mult = 1; + while (size > scale) { + size /= scale; + base *= scale; + } + + if (size < 2) mult = 2; + else if (size < 5) mult = 5; + else mult = 10; + + s.bigStep = base * mult; + switch (mult) { + + case 1: s.smallStep = s.bigStep / 5; break; + case 2: s.smallStep = s.bigStep / 2; break; + case 5: s.smallStep = s.bigStep / 5; break; + case 10: s.smallStep = s.bigStep / 5; break; + } + return s; +} + +inline TScaleSteps getYScale(double size, float scale) { + + TScaleSteps s; + + qint64 base = 1; + int mult = 1; + while (size > scale) { + size /= scale; + base *= scale; + } + + if (size < 2) mult = 2; + else if (size < 5) mult = 5; + else mult = 10; + + s.bigStep = base * mult; + switch (mult) { + + case 1: s.smallStep = s.bigStep / 5; break; + case 2: s.smallStep = s.bigStep / 2; break; + case 5: s.smallStep = s.bigStep / 5; break; + case 10: s.smallStep = s.bigStep / 2; break; + } + return s; +} + +inline TScale getXRuler(const QRect &rect, int fontMaxWidth, qreal unit, qreal lo, qreal hi) { + + TScale ruler; + + TScaleSteps scale = getXScale(fontMaxWidth / unit); + //qreal value = floor(lo / scale.bigStep) * scale.bigStep; + qreal value = qFloor(lo / scale.bigStep) * scale.bigStep; + + while (value < hi) { + + int x = qRound(unit * (value - lo)); + + if (x >= rect.width()) break; + if (x > 0) { + + ruler.mainPoints << value; + ruler.mainPointPositions << x; + } + + if (scale.smallStep > 0) { + + qreal smallValue = value + scale.smallStep; + qreal smallUpperValue = value + scale.bigStep; + + while (smallValue < smallUpperValue && smallValue < hi) { + + int x = qRound(unit * (smallValue - lo)); + if (x >= rect.width()) break; + if (x > 0) ruler.subPointPositions << x; + + smallValue += scale.smallStep; + } + } + value += scale.bigStep; + } + + return ruler; +} + +inline TScale getXRuler(const QRect &rect, int fontMaxWidth, qreal unit, qreal lo, qreal hi, float s) { + + TScale ruler; + + TScaleSteps scale = getXScale(fontMaxWidth / unit, s); + //qreal value = floor(lo / scale.bigStep) * scale.bigStep; + qreal value = qFloor(lo / scale.bigStep) * scale.bigStep; + + while (value < hi) { + + int x = qRound(unit * (value - lo)); + + if (x >= rect.width()) break; + if (x > 0) { + + ruler.mainPoints << value; + ruler.mainPointPositions << x; + } + + if (scale.smallStep > 0) { + + qreal smallValue = value + scale.smallStep; + qreal smallUpperValue = value + scale.bigStep; + + while (smallValue < smallUpperValue && smallValue < hi) { + + int x = qRound(unit * (smallValue - lo)); + if (x >= rect.width()) break; + if (x > 0) ruler.subPointPositions << x; + + smallValue += scale.smallStep; + } + } + value += scale.bigStep; + } + + return ruler; +} + +inline TScale getYRuler(const QRect &rect, int fontHeight, qreal unit, qreal lo, qreal hi) { + + TScale ruler; + + TScaleSteps scale = getYScale(fontHeight / unit, 10.0f); + //qreal value = ceil(hi / scale.bigStep) * scale.bigStep; + qreal value = qCeil(hi / scale.bigStep) * scale.bigStep; + + while (value >= lo) { + + int y = qRound(unit * -(value - hi)); + if (y > 0 && y < rect.height()) { + + if (ruler.mainPointPositions.length() < 100) { + + ruler.mainPoints << value; + ruler.mainPointPositions << rect.top() + y; + } + } + + if (scale.smallStep > 0) { + + qreal smallValue = value - scale.smallStep; + qreal smallEndValue = value - scale.bigStep; + while (smallValue > smallEndValue && smallValue > lo) { + + int y = qRound(unit * -(smallValue - hi)); + if (y > 0 && y < rect.height()) { + + if (ruler.subPointPositions.length() < 200) + ruler.subPointPositions << rect.top() + y; + } + smallValue -= scale.smallStep; + } + } + value -= scale.bigStep; + } + + return ruler; +} + +inline TScale getYRuler2(const QRect &rect, int fontHeight, qreal unit, qreal lo, qreal hi) { + + TScale ruler; + + TScaleSteps scale = getYScale(fontHeight / unit, 10.0f); + qreal value = qCeil(hi / scale.bigStep) * scale.bigStep; + + while (value >= lo) { + + int y = qRound(unit * -(value - hi)); + if (y > 0 && y < rect.height()) { + + if (ruler.mainPointPositions.length() < 100) { + + ruler.mainPoints << value; + //ruler.mainPointPositions << rect.top() + y; + ruler.mainPointPositions << y; + } + } + + if (scale.smallStep > 0) { + + qreal smallValue = value - scale.smallStep; + qreal smallEndValue = value - scale.bigStep; + while (smallValue > smallEndValue && smallValue > lo) { + + int y = qRound(unit * -(smallValue - hi)); + if (y > 0 && y < rect.height()) { + + if (ruler.subPointPositions.length() < 200) + ruler.subPointPositions << y; + //ruler.subPointPositions << rect.top() + y; + } + smallValue -= scale.smallStep; + } + } + value -= scale.bigStep; + } + + return ruler; +} + +inline TScale getYRuler3(const QRect &rect, int fontHeight, qreal unit, qreal lo, qreal hi, float v) { + + TScale ruler; + + TScaleSteps scale = getYScale(fontHeight / unit, v); + qreal value = qCeil(hi / scale.bigStep) * scale.bigStep; + + while (value >= lo) { + + int y = qRound(unit * -(value - hi)); + if (y > 0 && y < rect.height()) { + + if (ruler.mainPointPositions.length() < 100) { + + ruler.mainPoints << value; + //ruler.mainPointPositions << rect.top() + y; + ruler.mainPointPositions << y; + } + } + + if (scale.smallStep > 0) { + + qreal smallValue = value - scale.smallStep; + qreal smallEndValue = value - scale.bigStep; + while (smallValue > smallEndValue && smallValue > lo) { + + int y = qRound(unit * -(smallValue - hi)); + if (y > 0 && y < rect.height()) { + + if (ruler.subPointPositions.length() < 200) + ruler.subPointPositions << y; + //ruler.subPointPositions << rect.top() + y; + } + smallValue -= scale.smallStep; + } + } + value -= scale.bigStep; + } + + return ruler; +} + +inline GLfloat dBmToGLPixel(const QRect &rect, qreal dBmMax, qreal dBmMin, qreal value) { + + GLfloat y; + + qreal yScale = rect.height() / qAbs(dBmMax - dBmMin); + y = (GLfloat)(yScale * (dBmMax - value) + (qreal)rect.top()); + + return y; +} + +inline qreal glPixelTodBm(const QRect &rect, qreal dBmMax, qreal dBmMin, int position) { + + qreal dBm; + + float yScale = rect.height() / qAbs(dBmMax - dBmMin); + dBm = dBmMax - (qreal)(position - rect.top())/yScale; + //qreal dBm = m_dBmPanMax - ((m_dBmPanMax - m_dBmPanMin) * ((qreal)(position - rect.top()) / rect.height())); + + return dBm; +} + +//************************************************************** + +inline void setProjectionOrthographic(int width, int height) { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + //glOrtho(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0); + glOrtho(0.0, width, height, 0, -5.0, 5.0); + //glOrtho(0.0, width, height, 0, -1.0, 1.0); + //glOrtho(0.0, width, 0, height, -1.0, 1.0); + + glMatrixMode(GL_MODELVIEW); +} + +inline void setProjectionPerspective(int width, int height) { + + Q_UNUSED(width) + Q_UNUSED(height) + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + //glFrustum(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0); + //gluPerspective(60.0f, (float)(width)/height, 1.0f, 10.0f); + + glMatrixMode(GL_MODELVIEW); +} + +inline GLuint emptyTexture1D(int width) { + + GLuint txtnumber; + unsigned int* data; + + data = (unsigned int*)new GLuint[(width * 4 * sizeof(unsigned int))]; + +#if defined(Q_OS_WIN32) + ZeroMemory(data,(width * 4 * sizeof(unsigned int))); +#elif defined(Q_OS_LINUX) + memset(data, 0, width * 4 * sizeof(unsigned int)); +#endif + + glGenTextures(1, &txtnumber); + glBindTexture(GL_TEXTURE_1D, txtnumber); + glTexImage1D(GL_TEXTURE_1D, 0, 4, width, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + delete[] data; + return txtnumber; +} + +inline GLuint emptyTexture2D(int width, int height) { + + GLuint txtnumber; + unsigned int* data; + + data = (unsigned int*)new GLuint[((width * height)* 4 * sizeof(unsigned int))]; + +#if defined(Q_OS_WIN32) + ZeroMemory(data,((width * height)* 4 * sizeof(unsigned int))); +#elif defined(Q_OS_LINUX) + memset(data, 0, (width * height)* 4 * sizeof(unsigned int)); +#endif + + glGenTextures(1, &txtnumber); + glBindTexture(GL_TEXTURE_2D, txtnumber); + glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + delete [] data; + return txtnumber; +} + +inline void drawQuad2Di(int x, int y, int width, int height) { + + glEnable(GL_TEXTURE_2D); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex2i(x - width/2, y - height/2); + glTexCoord2f(1, 1); glVertex2i(x + width/2, y - height/2); + glTexCoord2f(1, 0); glVertex2i(x + width/2, y + height/2); + glTexCoord2f(0, 0); glVertex2i(x - width/2, y + height/2); + glEnd(); + + glDisable(GL_TEXTURE_2D); +} + +inline void drawQuad3Df(float x, float y, float z, float width, float height) { + + glEnable(GL_TEXTURE_2D); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex3f(x - width/2, y - height/2, -z); + glTexCoord2f(1, 1); glVertex3f(x + width/2, y - height/2, -z); + glTexCoord2f(1, 0); glVertex3f(x + width/2, y + height/2, -z); + glTexCoord2f(0, 0); glVertex3f(x - width/2, y + height/2, -z); + glEnd(); + + glDisable(GL_TEXTURE_2D); +} + +inline void drawGLRect(const QRect &rect, const QColor &color) { + + if (rect.isEmpty()) return; + + // draw a rectangle using 2 triangles + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = x1 + rect.width();//rect.right() + 1; + GLint y2 = y1 + rect.height();//rect.bottom() + 1; + + TGL2int vertexArray[4] = {{x1, y1}, {x2, y1}, {x1, y2}, {x2, y2}}; + + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_INT, 0, vertexArray); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisableClientState(GL_VERTEX_ARRAY); +} + +inline void drawGLRect(const QRect &rect, const QColor &color, float z) { + + if (rect.isEmpty()) return; + + // draw a rectangle using 2 triangles + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = x1 + rect.width(); + GLint y2 = y1 + rect.height(); + + TGL3float vertexArray[4] = + { + {(GLfloat)x1, (GLfloat)y1, z}, + {(GLfloat)x2, (GLfloat)y1, z}, + {(GLfloat)x1, (GLfloat)y2, z}, + {(GLfloat)x2, (GLfloat)y2, z} + }; + + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisableClientState(GL_VERTEX_ARRAY); +} + +inline void drawGLRect(const QRect &rect, const QColor &color1, const QColor &color2, bool colorLeftToRight) { + + // draw a rectangle using 2 triangles + + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = rect.right() + 1; + GLint y2 = rect.bottom() + 1; + + TGL2int vertexArray[4] = {{x1, y1}, {x2, y1}, {x1, y2}, {x2, y2}}; + + s_glRGBA_uByte gl_color1; + gl_color1.r = color1.red(); + gl_color1.g = color1.green(); + gl_color1.b = color1.blue(); + gl_color1.a = color1.alpha(); + + s_glRGBA_uByte gl_color2; + gl_color2.r = color2.red(); + gl_color2.g = color2.green(); + gl_color2.b = color2.blue(); + gl_color2.a = color2.alpha(); + + s_glRGBA_uByte vertexColors[4]; + if (!colorLeftToRight) { + + // top to bottom + vertexColors[0] = gl_color1; // top left + vertexColors[1] = gl_color1; // top right + vertexColors[2] = gl_color2; // bottom left + vertexColors[3] = gl_color2; // bottom right + } + else { + + // left to right + vertexColors[0] = gl_color1; // top left + vertexColors[1] = gl_color2; // top right + vertexColors[2] = gl_color1; // bottom left + vertexColors[3] = gl_color2; // bottom right + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_INT, 0, vertexArray); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, vertexColors); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); +} + +inline void drawGLRect(const QRect &rect, const QColor &color1, const QColor &color2, float z, bool colorLeftToRight) { + + // draw a rectangle using 2 triangles + + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = rect.right() + 1; + GLint y2 = rect.bottom() + 1; + + TGL3float vertexArray[4] = + { + {(GLfloat)x1, (GLfloat)y1, z}, + {(GLfloat)x2, (GLfloat)y1, z}, + {(GLfloat)x1, (GLfloat)y2, z}, + {(GLfloat)x2, (GLfloat)y2, z} + }; + + s_glRGBA_uByte gl_color1; + gl_color1.r = color1.red(); + gl_color1.g = color1.green(); + gl_color1.b = color1.blue(); + gl_color1.a = color1.alpha(); + + s_glRGBA_uByte gl_color2; + gl_color2.r = color2.red(); + gl_color2.g = color2.green(); + gl_color2.b = color2.blue(); + gl_color2.a = color2.alpha(); + + s_glRGBA_uByte vertexColors[4]; + + if (!colorLeftToRight) { + + // top to bottom + vertexColors[0] = gl_color1; // top left + vertexColors[1] = gl_color1; // top right + vertexColors[2] = gl_color2; // bottom left + vertexColors[3] = gl_color2; // bottom right + } + else { + + // left to right + vertexColors[0] = gl_color1; // top left + vertexColors[1] = gl_color2; // top right + vertexColors[2] = gl_color1; // bottom left + vertexColors[3] = gl_color2; // bottom right + } + + glEnableClientState(GL_VERTEX_ARRAY); + //glVertexPointer(2, GL_INT, 0, vertexArray); + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(4, GL_UNSIGNED_BYTE, 0, vertexColors); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glDisableClientState(GL_COLOR_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); +} + +inline void drawGLTriangleLeft(const QRect &rect, const QColor &color, float z) { + + if (rect.isEmpty()) return; + + GLint x1 = rect.left(); + GLint x2 = rect.left() + rect.width(); + GLint y1 = rect.top() + rect.height()/2; + GLint y2 = rect.top(); + GLint y3 = rect.top() + rect.height(); + + TGL3float vertexArray[3] = + { + {(GLfloat)x1, (GLfloat)y1, z}, + {(GLfloat)x2, (GLfloat)y2, z}, + {(GLfloat)x2, (GLfloat)y3, z} + }; + + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableClientState(GL_VERTEX_ARRAY); +} + +inline void drawGLTriangleRight(const QRect &rect, const QColor &color, float z) { + + if (rect.isEmpty()) return; + + GLint x1 = rect.left(); + GLint x2 = rect.left() + rect.width(); + GLint y1 = rect.top(); + GLint y2 = y1 + rect.height(); + GLint y3 = y1 + rect.height()/2; + + TGL3float vertexArray[3] = + { + {(GLfloat)x1, (GLfloat)y1, z}, + {(GLfloat)x2, (GLfloat)y3, z}, + {(GLfloat)x1, (GLfloat)y2, z} + }; + + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_TRIANGLES, 0, 3); + glDisableClientState(GL_VERTEX_ARRAY); +} + +inline void drawGLBackground(const QRect &rect) { + + if (rect.isEmpty()) return; + + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = x1 + rect.width(); + GLint y2 = y1 + rect.height(); + + //glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glBegin(GL_TRIANGLE_STRIP); + glColor3f((GLfloat)0.13, (GLfloat)0.13, (GLfloat)0.13); glVertex3f(x1, y1, 0.0); // top left corner + glColor3f((GLfloat)0.13, (GLfloat)0.13, (GLfloat)0.13); glVertex3f(x2, y1, 0.0); // top right corner + glColor3f((GLfloat)0.18, (GLfloat)0.18, (GLfloat)0.18); glVertex3f(x1, y2, 0.0); // bottom left corner + glColor3f((GLfloat)0.31, (GLfloat)0.31, (GLfloat)0.31); glVertex3f(x2, y2, 0.0); // bottom right corner + glEnd(); + //glFlush(); +} + +inline void drawGLScaleBackground(const QRect &rect, const QColor &color) { + + if (rect.isEmpty()) return; + + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = x1 + rect.width(); + GLint y2 = y1 + rect.height(); + + //const bool GL_TEXTURE_2D_wasEnabled = glIsEnabled(GL_TEXTURE_2D); + glColor4ub(color.red(), color.green(), color.blue(), color.alpha()); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + + glBegin(GL_POLYGON); + glVertex3f(x1, y1, 0.0); // top left corner + glVertex3f(x2, y1, 0.0); // top middle corner + glVertex3f(x2, y2, 0.0); // bottom middle corner + glVertex3f(x1, y2, 0.0); // bottom left corner + glEnd(); + glFlush(); +} + +inline void renderTexture( + const QRect &rect, + const GLuint texId, + float z) +{ + if (rect.isEmpty()) return; + if (!texId) return; + + const bool GL_TEXTURE_2D_enabled = glIsEnabled(GL_TEXTURE_2D); + GLint oldTex; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &oldTex); + + GLint x1 = rect.left(); + GLint y1 = rect.top(); + GLint x2 = x1 + rect.width(); + GLint y2 = y1 + rect.height(); + + if (!GL_TEXTURE_2D_enabled) glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, texId); + + glBegin(GL_QUADS); + glTexCoord2f(0, 1); glVertex3f(x1, y1, z); // top left corner + glTexCoord2f(1, 1); glVertex3f(x2, y1, z); // top right corner + glTexCoord2f(1, 0); glVertex3f(x2, y2, z); // bottom right corner + glTexCoord2f(0, 0); glVertex3f(x1, y2, z); // bottom left corner + glEnd(); + + glBindTexture(GL_TEXTURE_2D, oldTex); + if (!GL_TEXTURE_2D_enabled) glDisable(GL_TEXTURE_2D); +} + +//inline void writeBitmapString(void *font, char *string) { +// +// char *c; +// for (c = string; *c != '\0'; c++) glutBitmapCharacter(font, *c); +//} +// +//inline void writeStrokeString(void *font, char *string) { +// +// char *c; +// for (c = string; *c != '\0'; c++) glutStrokeCharacter(font, *c); +//} + +#endif // _CUSDR_OPENGLTYPES_H diff --git a/Source/src/GL/cusdr_oglWidebandPanel.cpp b/Source/src/GL/cusdr_oglWidebandPanel.cpp new file mode 100644 index 0000000..7a4d15c --- /dev/null +++ b/Source/src/GL/cusdr_oglWidebandPanel.cpp @@ -0,0 +1,2074 @@ +/** +* @file cusdr_oglWidebandPanel.h +* @brief wide band spectrum panel class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-11 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_WBGRAPHICS + +// use: WBGRAPHICS_DEBUG + +#include "cusdr_oglWidebandPanel.h" + +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#ifndef GL_MULTISAMPLE +#define GL_MULTISAMPLE 0x809D +#endif + +QGLWidebandPanel::QGLWidebandPanel(QWidget *parent) + : QGLWidget(QGLFormat(QGL::SampleBuffers|QGL::AlphaChannel), parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(set->getDataEngineState()) + , m_panMode(set->getPanadapterMode(0)) + //, m_specAveragingCnt(set->getSpectrumAveragingCnt()) + , m_mousePos(QPoint(-1, -1)) + , m_mouseDownPos(QPoint(-1, -1)) + , m_spectrumUpdate(false) + , m_freqScaleUpdate(true) + , m_freqScaleRenew(true) + , m_dBmScaleUpdate(true) + , m_dBmScaleRenew(true) + , m_panGridRenew(true) + , m_spectrumColorsChanged(true) + , m_crossHairCursor(false) + //, m_panGrid(set->getPanGridStatus(0)) + , m_panGrid(true) + , m_calibrate(false) + , m_panSpectrumBinsLength(0) + , m_snapMouse(3) + , m_currentReceiver(set->getCurrentReceiver()) + , m_sampleRate(set->getSampleRate()) + , m_freqScaleZoomFactor(1.0) + , m_dBmScaleOffset(0.0) +{ +// QGL::setPreferredPaintEngine(QPaintEngine::OpenGL); + + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + setAutoBufferSwap(true); + setAutoFillBackground(false); + + setMouseTracking(true); + //setFocusPolicy(Qt::StrongFocus); + + setupDisplayRegions(size()); + m_oldWidth = size().width(); + m_oldHeight = size().height(); + + m_rxDataList = set->getReceiverDataList(); + m_widebandOptions = set->getWidebandOptions(); + m_panMode = m_widebandOptions.panMode; + + m_frequency = m_rxDataList.at(0).vfoFrequency; + + m_lowerFrequency = 0.0; + m_upperFrequency = (qreal) MAXHPFREQUENCY; + + m_dBmPanMin = set->getWidebanddBmScaleMin(); + m_dBmPanMax = set->getWidebanddBmScaleMax(); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_fonts.smallFont.setBold(true); + + m_oglTextTiny = new OGLText(m_fonts.tinyFont); + m_oglTextSmall = new OGLText(m_fonts.smallFont); + m_oglTextNormal = new OGLText(m_fonts.normalFont); + + + timer = 0; + + setupConnections(); + + m_panTimer.start(); + m_displayTime.start(); + m_resizeTime.start(); + + m_wbSpectrumBuffer.resize(BIGWIDEBANDSIZE / 2); + m_wbSpectrumBuffer.fill(-1000.0f); + m_wbSpectrumBufferLength = m_wbSpectrumBuffer.size(); + + m_dBmPanLogGain = 75;//69; // allow user to calibrate this value + + if (m_specAveragingCnt > 0) + m_scale = 1.0f / m_specAveragingCnt; + else + m_scale = 1.0f; + + m_frequencyScaleFBO = 0; + m_dBmScaleFBO = 0; + m_gridFBO = 0; + + + m_gridColor = set->getPanadapterColors().gridLineColor; + + m_redGrid = (GLfloat)(m_gridColor.red()/256.0); + m_greenGrid = (GLfloat)(m_gridColor.green()/256.0); + m_blueGrid = (GLfloat)(m_gridColor.blue()/256.0); + + m_r = (GLfloat)(set->getPanadapterColors().wideBandLineColor.red() / 256.0); + m_g = (GLfloat)(set->getPanadapterColors().wideBandLineColor.green() / 256.0); + m_b = (GLfloat)(set->getPanadapterColors().wideBandLineColor.blue() / 256.0); + + m_rf = (GLfloat)(set->getPanadapterColors().wideBandFilledColor.red() / 256.0); + m_gf = (GLfloat)(set->getPanadapterColors().wideBandFilledColor.green() / 256.0); + m_bf = (GLfloat)(set->getPanadapterColors().wideBandFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0); +} + +QGLWidebandPanel::~QGLWidebandPanel() { + + disconnect(set, 0, this, 0); + + makeCurrent(); + glFinish(); + + while (!specAv_queue.isEmpty()) + specAv_queue.dequeue(); + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + + if (m_gridFBO) { + + delete m_gridFBO; + m_gridFBO = 0; + } +} + +QSize QGLWidebandPanel::minimumSizeHint() const { + + return QSize(width(), 50); + //return QSize(width(), height()); +} + +QSize QGLWidebandPanel::sizeHint() const { + + //return QSize(width(), height()); + return QSize(width(), 120); +} + +void QGLWidebandPanel::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)) + ); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + + CHECKED_CONNECT( + set, + SIGNAL(widebandSpectrumBufferChanged(const qVectorFloat &)), + this, + SLOT(setWidebandSpectrumBuffer(const qVectorFloat &))); + + CHECKED_CONNECT( + set, + SIGNAL(widebandSpectrumBufferReset()), + this, + SLOT(resetWidebandSpectrumBuffer())); + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setFrequency(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(panadapterColorChanged()), + this, + SLOT(setPanadapterColors())); + + /*CHECKED_CONNECT( + set, + SIGNAL(panGridStatusChanged(bool, int)), + this, + SLOT(setPanGridStatus(bool, int)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(setMercuryAttenuator(QObject *, HamBand, int))); + + //CHECKED_CONNECT( + // set, + // SIGNAL(spectrumAveragingCntChanged(int)), + // this, + // SLOT(setSpectrumAveragingCnt(int))); +} + +void QGLWidebandPanel::initializeGL() { + + if (!isValid()) return; + + glShadeModel(GL_SMOOTH); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // 4-byte pixel alignment + //glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + //glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST); + + glDepthFunc(GL_LESS); + glEnable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + + m_cnt = 0; + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); +} + +void QGLWidebandPanel::paintGL() { + + switch (m_serverMode) { + + case QSDR::NoServerMode: + case QSDR::ChirpWSPR: + case QSDR::ChirpWSPRFile: + case QSDR::DemoMode: + + drawGLRect(QRect(0, 0, width(), height()), QColor(0, 0, 0)); + break; + + case QSDR::SDRMode: + + if (m_resizeTime.elapsed() > 200 || m_dataEngineState == QSDR::DataEngineDown) { + + drawSpectrum(); + drawHorizontalScale(); + drawVerticalScale(); + + if (m_panGrid) + drawGrid(); + + // Ham band information + drawHamBand(1810000, 2000000, "160m"); + drawHamBand(3500000, 3800000, "80m"); + drawHamBand(5258500, 5403500, "60m"); + drawHamBand(7000000, 7300000, "40m"); + drawHamBand(10100000, 10150000, "30m"); + drawHamBand(14000000, 14350000, "20m"); + drawHamBand(18068000, 18168000, "17m"); + drawHamBand(21000000, 21450000, "15m"); + drawHamBand(24890000, 24990000, "12m"); + drawHamBand(28000000, 29700000, "10m"); + drawHamBand(50000000, 51990000, "6m"); + + //qglColor(QColor(255, 255, 255, 130)); + //m_oglTextSmall->renderText(m_panRect.right() - 100, m_panRect.top(), 5.0f, "Region 1"); + + if (m_mouseRegion == panRegion && m_crossHairCursor) + drawCrossHair(); + } + + break; + } +} + +//************************************************************************ +void QGLWidebandPanel::drawSpectrum() { + + GLint width = m_panRect.width(); + GLint height = m_panRect.height(); + + GLint x1 = m_panRect.left(); + GLint y1 = m_panRect.top(); + GLint x2 = x1 + width; + GLint y2 = y1 + height; + + GLint vertexArrayLength = 0; + + // x scale + int idx = 0; + int lIdx = 0; + int rIdx = 0; + int deltaIdx = 0; + + qreal scaleMult = 1.0; + + m_scaledBufferSize = qFloor(m_wbSpectrumBufferLength * m_freqScaleZoomFactor); + deltaIdx = qFloor((qreal)(m_wbSpectrumBufferLength * (m_lowerFrequency / MAXHPFREQUENCY))); + + qreal frequencyScale = (qreal)(1.0f * m_scaledBufferSize / width); + + if (frequencyScale < 0.125) + scaleMult = 0.0625; + else if (frequencyScale < 0.25) + scaleMult = 0.125; + else if (frequencyScale < 0.5) + scaleMult = 0.25; + else if (frequencyScale < 1.0) + scaleMult = 0.5; + + qreal scale = frequencyScale / scaleMult; + + // y scale + float yScale; + float yScaleColor; + float yTop; + float localMax; + + //qreal dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin); + qreal dBmRange; + + if (m_calibrate) + dBmRange = qAbs(m_dBmPanMaxOld - m_dBmPanMinOld); + else + dBmRange = qAbs(m_dBmPanMax - m_dBmPanMin); + + yScale = height / dBmRange; + yScaleColor = 1.0f / dBmRange; + yTop = (float) y2; + + if (m_dataEngineState == QSDR::DataEngineUp) + glClear(GL_DEPTH_BUFFER_BIT); + else + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glEnable(GL_MULTISAMPLE); + glEnable(GL_LINE_SMOOTH); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + glLineWidth(1); + + // draw background + if (m_dataEngineState == QSDR::DataEngineUp) { + +// glBegin(GL_TRIANGLE_STRIP); +// glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner +// glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner +// glColor3f(0.8f * m_bkgRed, 0.8f * m_bkgGreen, 0.8f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner +// glColor3f( m_bkgRed, m_bkgGreen, m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner +// glEnd(); + glBegin(GL_TRIANGLE_STRIP); + glColor3f(0.8f * m_bkgRed, 0.8f * m_bkgGreen, 0.8f * m_bkgBlue); glVertex3f(x1, y1, -4.0); // top left corner + glColor3f(0.6f * m_bkgRed, 0.6f * m_bkgGreen, 0.6f * m_bkgBlue); glVertex3f(x2, y1, -4.0); // top right corner + glColor3f(0.4f * m_bkgRed, 0.4f * m_bkgGreen, 0.4f * m_bkgBlue); glVertex3f(x1, y2, -4.0); // bottom left corner + glColor3f(0.2f * m_bkgRed, 0.2f * m_bkgGreen, 0.2f * m_bkgBlue); glVertex3f(x2, y2, -4.0); // bottom right corner + glEnd(); + } + else { + + drawGLRect(m_panRect, QColor(30, 30, 50, 155), -4.0f); + } + + // set a scissor box + glScissor(x1, size().height() - y2, x2, height); + glEnable(GL_SCISSOR_TEST); + + // set up the vertex arrays + vertexArrayLength = (GLint)(scaleMult * width); + //WBGRAPHICS_DEBUG << "vertexArrayLength: " << vertexArrayLength; + + TGL3float *vertexArray = new TGL3float[vertexArrayLength]; + TGL3float *vertexColorArray = new TGL3float[vertexArrayLength]; + + TGL3float *vertexArrayBg = new TGL3float[2*vertexArrayLength]; + TGL3float *vertexColorArrayBg = new TGL3float[2*vertexArrayLength]; + + switch (m_panMode) { + + case (PanGraphicsMode) FilledLine: + + for (int i = 0; i < vertexArrayLength; i++) { + + idx = 0; + lIdx = (int)floor((qreal)(i * scale)); + rIdx = (int)floor((qreal)(i * scale) + scale); + + // max value; later we try mean value also! + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + if (m_wbSpectrumBuffer.at(j) > localMax) { + + localMax = m_wbSpectrumBuffer.at(j); + idx = j; + } + } + idx += deltaIdx; + + mutex.lock(); + + vertexColorArrayBg[2*i].x = m_rf; + vertexColorArrayBg[2*i].y = m_gf; + vertexColorArrayBg[2*i].z = m_bf; + + vertexColorArrayBg[2*i+1].x = 0.3 * m_rf; + vertexColorArrayBg[2*i+1].y = 0.3 * m_gf; + vertexColorArrayBg[2*i+1].z = 0.3 * m_bf; + + qreal yvalue = 0; + if (idx < m_wbSpectrumBufferLength) + yvalue = m_wbSpectrumBuffer.at(idx) - m_dBmPanMin; + + vertexColorArray[i].x = m_r * (yScaleColor * yvalue); + vertexColorArray[i].y = m_g * (yScaleColor * yvalue); + vertexColorArray[i].z = m_b * (yScaleColor * yvalue); + + if (idx < m_wbSpectrumBufferLength) + yvalue = m_wbSpectrumBuffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain; + + if (m_mercuryAttenuator) + yvalue -= 20.0f; + + vertexArrayBg[2*i].x = (GLfloat)(i/scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * yvalue); + vertexArrayBg[2*i].z = -2.5; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + vertexArrayBg[2*i+1].z = -2.5; + + vertexArray[i].x = (GLfloat)(i/scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * yvalue); + vertexArray[i].z = -1.0; + + mutex.unlock(); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + glDrawArrays(GL_QUAD_STRIP, 0, 2*vertexArrayLength); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + + break; + + case (PanGraphicsMode) Line: + + for (int i = 0; i < vertexArrayLength; i++) { + + lIdx = (int)floor((qreal)(i * scale)); + rIdx = (int)floor((qreal)(i * scale) + scale); + + // max value; later we try mean value also! + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + if (m_wbSpectrumBuffer.at(j) > localMax) { + + localMax = m_wbSpectrumBuffer.at(j); + idx = j; + } + } + idx += deltaIdx; + + mutex.lock(); + + qreal yvalue = 0; + if (idx < m_wbSpectrumBufferLength) + yvalue = m_wbSpectrumBuffer.at(idx) - m_dBmPanMin; + + vertexColorArray[i].x = m_r * (yScaleColor * yvalue); + vertexColorArray[i].y = m_g * (yScaleColor * yvalue); + vertexColorArray[i].z = m_b * (yScaleColor * yvalue); + + if (idx < m_wbSpectrumBufferLength) { + + if (m_calibrate) + yvalue = m_wbSpectrumBuffer.at(idx) - m_dBmPanMinOld - m_dBmPanLogGain; + else + yvalue = m_wbSpectrumBuffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain - m_dBmScaleOffset; + } + + if (m_mercuryAttenuator) yvalue -= 20.0f; + + vertexArray[i].x = (GLfloat)(i/scaleMult); + vertexArray[i].y = (GLfloat)(yTop - yScale * yvalue); + vertexArray[i].z = -1.0; + + mutex.unlock(); + } + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArray); + glColorPointer(3, GL_FLOAT, 0, vertexColorArray); + glDrawArrays(GL_LINE_STRIP, 0, vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + + break; + + + case (PanGraphicsMode) Solid: + + glDisable(GL_MULTISAMPLE); + glDisable(GL_LINE_SMOOTH); + + mutex.lock(); + for (int i = 0; i < vertexArrayLength; i++) { + + lIdx = qFloor((qreal)(i * scale)); + rIdx = qFloor((qreal)(i * scale) + scale); + + // max value + localMax = -10000.0F; + for (int j = lIdx; j < rIdx; j++) { + + if (m_wbSpectrumBuffer.at(j) > localMax) { + + localMax = m_wbSpectrumBuffer.at(j); + idx = j; + } + } + //qreal mean = m_wbSpectrumBuffer.at(lIdx + deltaIdx); + //int len = rIdx - lIdx; + //WBGRAPHICS_DEBUG << "leftIdx = " << lIdx << " rightIdx = " << rIdx << " length = " << len; + //for (int j = lIdx+1; j < len; j++) { + + // mean += m_wbSpectrumBuffer.at(j); + //} + //if (len > 0) mean /= len; + + idx += deltaIdx; + + //mutex.lock(); + vertexColorArrayBg[2*i].x = m_redST; + vertexColorArrayBg[2*i].y = m_greenST; + vertexColorArrayBg[2*i].z = m_blueST; + + vertexColorArrayBg[2*i+1].x = m_redSB; + vertexColorArrayBg[2*i+1].y = m_greenSB; + vertexColorArrayBg[2*i+1].z = m_blueSB; + + qreal yvalue = 0; + if (idx < m_wbSpectrumBufferLength) + yvalue = m_wbSpectrumBuffer.at(idx) - m_dBmPanMin - m_dBmPanLogGain; + //yvalue = mean - m_dBmPanMin - m_dBmPanLogGain; + + if (m_mercuryAttenuator) + yvalue -= 20.0; + + vertexArrayBg[2*i].x = (GLfloat)(i/scaleMult); + vertexArrayBg[2*i].y = (GLfloat)(yTop - yScale * yvalue); + vertexArrayBg[2*i].z = -2.0f; + + vertexArrayBg[2*i+1].x = (GLfloat)(i/scaleMult); + vertexArrayBg[2*i+1].y = (GLfloat)yTop; + vertexArrayBg[2*i+1].z = -2.0f; + + //mutex.unlock(); + } + mutex.unlock(); + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + glVertexPointer(3, GL_FLOAT, 0, vertexArrayBg); + glColorPointer(3, GL_FLOAT, 0, vertexColorArrayBg); + glDrawArrays(GL_LINES, 0, 2*vertexArrayLength); + + glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + + delete[] vertexArray; + delete[] vertexColorArray; + delete[] vertexArrayBg; + delete[] vertexColorArrayBg; + + break; + } + glDisable(GL_SCISSOR_TEST); + + // draw a rectangle for the panadapter frequency region + if (m_dataEngineState == QSDR::DataEngineUp && !m_calibrate) { + + y1 = m_panRect.top() + 15; + y2 = m_panRect.height() - 15; + + //m_frequencySpan = (m_upperFrequency - m_lowerFrequency) * m_freqScaleZoomFactor; + //m_frequencyUnit = (qreal)(m_freqScaleRect.width() / m_frequencySpan); + + //int centerFreq = (int)(m_frequencyUnit * (m_frequency - m_lowerFrequency)); + //int deltaF = (int)(m_frequencyUnit * (float)m_sampleRate/2); + //int linePos = centerFreq; + + int centerFreq = (int)(m_frequencyUnit * (m_frequency - m_lowerFrequency)); + int deltaF = (int)(m_frequencyUnit * (float)m_sampleRate/2); + //int linePos = centerFreq; + + + x1 = (GLint)(centerFreq - deltaF); + x2 = (GLint)(centerFreq + deltaF); + +// int dist = qAbs(x2-x1); +// if (dist < 2) { +// +// x2 = x1 + 1; +// linePos = x1; +// glLineWidth(2); +// } +// else if (dist%2 == 0) { +// +// glLineWidth(1); +// } +// else if (dist%2 == 1) { +// +// linePos -= 1; +// glLineWidth(2); +// } + + QRect rect = QRect(x1, y1, x2-x1, y2); + drawGLRect(rect, QColor(160, 235, 255, 80), 0.0f); + + // small vertical line +// qglColor(QColor(255, 0, 0, 255)); +// glBegin(GL_LINES); +// glVertex3f(centerFreq, y2 + 15, 4.0f); +// glVertex3f(centerFreq, y2 + 30, 4.0f); +// glEnd(); + + glLineWidth(1); + } + + //glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glDisable(GL_LINE_SMOOTH); +} + +void QGLWidebandPanel::drawVerticalScale() { + + if (!m_dBmScaleRect.isValid()) return; + + int width = m_dBmScaleRect.width(); + int height = m_dBmScaleRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_dBmScaleFBO || m_dBmScaleUpdate || m_dBmScaleRenew) { + + if (!m_dBmScaleFBO || m_dBmScaleRenew) { + + if (m_dBmScaleFBO) { + + delete m_dBmScaleFBO; + m_dBmScaleFBO = 0; + } + + m_dBmScaleFBO = new QGLFramebufferObject(width, height);//, format); + //WBGRAPHICS_DEBUG << "dBmScaleFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_dBmScaleFBO->bind(); + renderVerticalScale(); + m_dBmScaleFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + //WBGRAPHICS_DEBUG << "dBm scale updated."; + m_dBmScaleUpdate = false; + m_dBmScaleRenew = false; + } + + renderTexture(m_dBmScaleRect, m_dBmScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLWidebandPanel::drawHorizontalScale() { + + if (!m_freqScaleRect.isValid()) return; + + int width = m_freqScaleRect.width(); + int height = m_freqScaleRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor3f(0.65f, 0.76f, 0.81f); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_frequencyScaleFBO || m_freqScaleUpdate || m_freqScaleRenew) { + + if (!m_frequencyScaleFBO || m_freqScaleRenew) { + + if (m_frequencyScaleFBO) { + + delete m_frequencyScaleFBO; + m_frequencyScaleFBO = 0; + } + + m_frequencyScaleFBO = new QGLFramebufferObject(width, height);//, format); + //WBGRAPHICS_DEBUG << "wb-frequencyScaleFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_frequencyScaleFBO->bind(); + renderHorizontalScale(); + m_frequencyScaleFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + //WBGRAPHICS_DEBUG << "frequency scale updated."; + m_freqScaleUpdate = false; + m_freqScaleRenew = false; + } + + renderTexture(m_freqScaleRect, m_frequencyScaleFBO->texture(), 0.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); +} + +void QGLWidebandPanel::drawGrid() { + + if (!m_panRect.isValid()) return; + + int width = m_panRect.width(); + int height = m_panRect.height(); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); + glColor4f(m_redGrid, m_greenGrid, m_blueGrid, 1.0); + + glDisable(GL_MULTISAMPLE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); + + if (!m_gridFBO || m_panGridUpdate || m_panGridRenew) { + + if (!m_gridFBO || m_panGridRenew) { + + if (m_gridFBO) { + + delete m_gridFBO; + m_gridFBO = 0; + } + + m_gridFBO = new QGLFramebufferObject(width, height);//, format); + //WBGRAPHICS_DEBUG << "gridFBO generated."; + } + + glPushAttrib(GL_VIEWPORT_BIT); + glViewport(0, 0, width, height); + setProjectionOrthographic(width, height); + + m_gridFBO->bind(); + renderGrid(); + m_gridFBO->release(); + + glPopAttrib(); + glViewport(0, 0, size().width(), size().height()); + setProjectionOrthographic(size().width(), size().height()); + + //WBGRAPHICS_DEBUG << "grid updated."; + m_panGridUpdate = false; + m_panGridRenew = false; + } + + renderTexture(m_panRect, m_gridFBO->texture(), -3.0f); + + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glColor3f(0.65f, 0.76f, 0.81f); + glEnable(GL_MULTISAMPLE); +} + +void QGLWidebandPanel::drawCrossHair() { + + QRect rect(0, m_panRect.top(), width(), height() - m_panRect.top()); + + int x = m_mousePos.x(); + int y = m_mousePos.y(); + + glDisable(GL_MULTISAMPLE); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glDisable(GL_LINE_SMOOTH); + glLineWidth(1.0f); + + qglColor(QColor(255, 255, 255, 80)); + + // set a scissor box + glScissor(rect.left(), rect.top(), rect.width() - 1, rect.height()); + glEnable(GL_SCISSOR_TEST); + + // horizontal line + glBegin(GL_LINES); + glVertex3f(rect.left() - 1, y, 4.0f); + glVertex3f(m_dBmScaleRect.left() - 2, y, 4.0f); + glEnd(); + + // vertical line + glBegin(GL_LINES); + glVertex3f(x, rect.top() + 1, 4.0f); + glVertex3f(x, rect.bottom() - 1, 4.0f); + glEnd(); + + // cross hair + qglColor(QColor(255, 255, 255, 180)); + glBegin(GL_LINES); + glVertex3f(x , y - 20, 5.0f); + glVertex3f(x , y + 20, 5.0f); + glVertex3f(x - 20, y, 5.0f); + glVertex3f(x + 20, y, 5.0f); + glEnd(); + + // text only on panadapter + if (m_mouseRegion == panRegion) { + + QString str; + qglColor(QColor(255, 255, 255, 255)); + + qreal unit = (qreal)((MAXHPFREQUENCY * m_freqScaleZoomFactor) / m_panRect.width()); + qreal frequency = (unit * x) + m_lowerFrequency; + + str = frequencyString(frequency); + if (x > m_panRect.width() - 85) + m_oglTextSmall->renderText(x - 90, y - 18, 5.0f, str); + else + m_oglTextSmall->renderText(x + 4, y - 18, 5.0f, str); + + qreal dBm = m_dBmPanMax - ((m_dBmPanMax - m_dBmPanMin) * ((qreal)(y - m_panRect.top()) / m_panRect.height())); + str = QString::number(dBm, 'f', 1) + " dBm"; + if (x > m_panRect.width() - 85) + m_oglTextSmall->renderText(x - 90, y + 6, 5.0f, str); + else + m_oglTextSmall->renderText(x + 4, y + 6, 5.0f, str); + } + + glDisable(GL_SCISSOR_TEST); + glEnable(GL_MULTISAMPLE); +} + +void QGLWidebandPanel::drawHamBand( + int lo, + int hi, + const QString &band +) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + GLint x1 = (GLint)(m_frequencyUnit * (lo - m_lowerFrequency)); + GLint x2 = (GLint)(m_frequencyUnit * (hi - m_lowerFrequency)); + + GLint y1 = m_panRect.top();// + 15; + GLint y2 = m_panRect.bottom(); + + QRect rect = QRect(x1, y1, x2-x1, y2); + + if (x2 < m_dBmScaleRect.left()) { + + drawGLRect( + rect, + QColor((int)(255 * m_bkgRed), (int)(255 * m_bkgGreen), (int)(255 * m_bkgBlue), 180), + QColor((int)(255 * m_bkgRed), (int)(255 * m_bkgGreen), (int)(255 * m_bkgBlue), 80), + -2.0f, + false); + } + + //QFontMetrics d_fm(m_smallFont); + int fontWidth = m_fonts.smallFontMetrics->boundingRect(band).width(); + + qglColor(QColor(255, 255, 255, 180)); + m_oglTextSmall->renderText((x2 + x1 - fontWidth)/2.0f, y1, 5.0f, band); +} + +//************************************************************************ +// The algorithms of the scale functions are taken from SDRMAXIII +// (c) Catherine Moss, with permission. + +void QGLWidebandPanel::renderVerticalScale() { + + QString str; + //QFontMetrics d_fm(m_smallFont); + int spacing = 6; + int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0dBm").height() + spacing; + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("-000.0").width(); + + GLint width = m_dBmScaleRect.width(); + GLint height = m_dBmScaleRect.height(); + + qreal unit = (qreal)(m_dBmScaleRect.height() / qAbs(m_dBmPanMax - m_dBmPanMin)); + + m_dBmScale = getYRuler2(m_dBmScaleRect, fontHeight, unit, m_dBmPanMin, m_dBmPanMax); + + glClear(GL_COLOR_BUFFER_BIT); + + QRect textRect(0, 0, fontMaxWidth, fontHeight); + textRect.moveLeft(3); + m_dBmScaleTextPos = -textRect.height(); + + int len = m_dBmScale.mainPointPositions.length(); + int sublen = m_dBmScale.subPointPositions.length(); + + // draw the scale background + drawGLScaleBackground(QRect(0, 0, width, height), QColor(30, 30, 30, 180)); + + if (len > 0) { + + glColor3f(0.65f, 0.76f, 0.81f); + glLineWidth(1); + + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(0, m_dBmScale.mainPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(4, m_dBmScale.mainPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + + glColor3f(0.45f, 0.56f, 0.61f); + if (sublen > 0) { + + glBegin(GL_LINES); + for (int i = 1; i < sublen; i++) { + + glVertex3f(0.0f, (float)m_dBmScale.subPointPositions.at(i), 0.0f); // origin of the line + glVertex3f(2.0f, (float)m_dBmScale.subPointPositions.at(i), 0.0f); // ending point of the line + } + glEnd(); + } + + glColor3f(0.75f, 0.86f, 0.91f); + for (int i = 0; i < len; i++) { + + textRect.moveBottom((int)m_dBmScale.mainPointPositions.at(i) + textRect.height()/2); + + //if (textRect.y() >= yOld && textRect.bottom() <= (m_dBmScaleRect.height() - textRect.height())) { + if (textRect.y() > m_dBmScaleRect.top() + textRect.height() && textRect.bottom() <= (m_dBmScaleRect.height() - textRect.height()/2)) { + + str = QString::number((qreal)m_dBmScale.mainPoints.at(i), 'f', 1); + m_oglTextSmall->renderText(textRect.x() + 10, textRect.y(), str); + m_dBmScaleTextPos = textRect.bottom(); + } + } + } + + textRect.moveTop(m_dBmScaleRect.top()); + glColor3f(0.94f, 0.22f, 0.43f); + + str = QString("dBm"); + m_oglTextSmall->renderText(textRect.x() + 18, textRect.y(), str); +} + +void QGLWidebandPanel::renderHorizontalScale() { + + if (m_freqScaleRect.isEmpty()) return; + + //QFontMetrics d_fm(m_smallFont); + int fontHeight = m_fonts.smallFontMetrics->tightBoundingRect(".0kMGHz").height(); + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000.000").width(); + + m_frequencySpan = MAXHPFREQUENCY * m_freqScaleZoomFactor; + m_frequencyUnit = (qreal)(m_freqScaleRect.width() / m_frequencySpan); + m_frequencyScale = getXRuler(m_freqScaleRect, fontMaxWidth, m_frequencyUnit, m_lowerFrequency, m_upperFrequency); + + // draw the frequency scale + int offset_X = -1; + int textOffset_y = 5; + double freqScale = 1; + + QString fstr = QString(" Hz "); + if (m_upperFrequency >= 1e6) { freqScale = 1e6; fstr = QString(" MHz "); } + else + if (m_upperFrequency >= 1e3) { freqScale = 1e3; fstr = QString(" kHz "); } + + // draw the wide band scale background + drawGLScaleBackground(QRect(0, 0, m_freqScaleRect.width(), m_freqScaleRect.height()), QColor(0, 0, 0, 255)); + + QRect scaledTextRect(0, textOffset_y, 1, fontHeight); + scaledTextRect.setWidth(m_fonts.smallFontMetrics->width(fstr)); + scaledTextRect.moveLeft(m_freqScaleRect.width() - scaledTextRect.width());// - menu_pull_right_rect.width()); + + glColor3f((GLfloat)0.65f, (GLfloat)0.76f, (GLfloat)0.81f); + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + glLineWidth(3); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.mainPointPositions.at(i), 4.0f, 0.0f); + } + glEnd(); + + for (int i = 0; i < len; i++) { + + QString str = QString::number(m_frequencyScale.mainPoints.at(i) / freqScale, 'f', 3); + + if (freqScale == 1e3) + while (str.endsWith('0')) str.remove(str.size() - 1, 1); + + if (str.endsWith('.')) str.remove(str.size() - 1, 1); + + int text_width = m_fonts.smallFontMetrics->width(str); + QRect textRect(m_frequencyScale.mainPointPositions.at(i) + offset_X - (text_width / 2), textOffset_y, text_width, fontHeight); + + if (textRect.left() < 0 || textRect.right() >= scaledTextRect.left()) continue; + + m_oglTextSmall->renderText(textRect.x(), textRect.y(), str); + } + } + + len = m_frequencyScale.subPointPositions.length(); + if (len > 0) { + + glLineWidth(1); + glBegin(GL_LINES); + for (int i = 0; i < len; i++) { + + glVertex3f(m_frequencyScale.subPointPositions.at(i), 1.0f, 0.0f); + glVertex3f(m_frequencyScale.subPointPositions.at(i), 3.0f, 0.0f); + } + glEnd(); + } + + glColor3f(0.94f, 0.22f, 0.43f); + m_oglTextSmall->renderText(m_freqScaleRect.width() - 30, textOffset_y, fstr); +} + +void QGLWidebandPanel::renderGrid() { + + glClear(GL_COLOR_BUFFER_BIT); + glLineStipple(1, 0x9999); + glEnable(GL_LINE_STIPPLE); + glLineWidth(1.0f); + + // vertical lines + int len = m_frequencyScale.mainPointPositions.length(); + if (len > 0) { + + GLint x1 = m_panRect.left(); + GLint x2 = 1; + if (m_dBmScaleRect.isValid()) x2 += m_dBmScaleRect.width(); + + //GLint y1 = rect.top() + 1; + GLint y1 = 1; + GLint y2 = m_panRect.bottom() - 1; + + TGL2int *vertexArray = new TGL2int[len * 2]; + int vertexArrayLen = 0; + + TGL2int point1, point2; + point1.y = y1; + point2.y = y2; + for (int i = 0; i < len; i++) { + + GLint x = m_frequencyScale.mainPointPositions.at(i); + if (x < x2) continue; + x += x1; + point1.x = x; + point2.x = x; + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_INT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + } + + // horizontal lines + len = m_dBmScale.mainPointPositions.length(); + if (len > 0) { + + TGL2float *vertexArray = new TGL2float[len * 2]; + int vertexArrayLen = 0; + + TGL2float point1, point2; + point1.x = m_panRect.left();// + m_dBmScaleRect.width(); + point2.x = m_panRect.right(); + + for (int i = 0; i < len; i++) { + + GLfloat y = m_dBmScale.mainPointPositions.at(i); + + point1.y = y; + point2.y = y; + + vertexArray[vertexArrayLen++] = point1; + vertexArray[vertexArrayLen++] = point2; + } + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vertexArray); + glDrawArrays(GL_LINES, 0, vertexArrayLen); + glDisableClientState(GL_VERTEX_ARRAY); + + delete[] vertexArray; + } + glDisable(GL_LINE_STIPPLE); +} + +//******************************************************************** + +void QGLWidebandPanel::getRegion(QPoint p) { + + if (m_freqScaleRect.contains(p)) { + + m_mouseRegion = freqScaleRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else if (m_dBmScaleRect.contains(p)) { + + m_mouseRegion = dBmScaleRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else if (m_panRect.contains(p)) { + + m_mouseRegion = panRegion; + + if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + update(); + } + } + else + m_mouseRegion = elsewhere; + + /*if (m_displayTime.elapsed() >= 50) { + + m_displayTime.restart(); + updateGL(); + update(); + }*/ + //GRAPHICS_DEBUG << "region" << m_mouseRegion; +} + +void QGLWidebandPanel::resizeGL(int iWidth, int iHeight) { + + int width = (int)(iWidth/2) * 2; + int height = iHeight; + + if (width != m_oldWidth) { + + m_freqScaleRenew = true; + m_panGridRenew = true; + + m_oldWidth = width; + } + + if (height != m_oldHeight) { + + m_dBmScaleRenew = true; + m_panGridRenew = true; + + m_oldHeight = height; + } + + m_spectrumVertexColorUpdate = true; + + glFinish(); + + m_resizeTime.restart(); + setupDisplayRegions(QSize(width, height)); + glViewport(0, 0, (GLsizei)width, (GLsizei)height); + + setProjectionOrthographic(width, height); +} + +void QGLWidebandPanel::setupDisplayRegions(QSize size) { + + m_displayTop = 0; + int freqScaleRectHeight = 20; + int dBmScaleWidth = 45; + + //WBGRAPHICS_DEBUG << "WB display width:" << size.width(); + //WBGRAPHICS_DEBUG << "WB display height:" << size.height()/6.0; + + m_freqScaleRect = QRect( + 0, + size.height() - m_displayTop - freqScaleRectHeight, + size.width(), + freqScaleRectHeight); + + m_panRect = QRect( + 0, + m_displayTop, + size.width(), + m_freqScaleRect.top() - m_displayTop); + + m_dBmScaleRect = QRect( + m_panRect.right() - dBmScaleWidth, + m_displayTop, + dBmScaleWidth, + m_panRect.height()); + + m_panRectWidth = (GLint)m_panRect.width(); + m_freqScaleUpdate = true; + m_dBmScaleUpdate = true; + m_panGridUpdate = true; + + //*************************************************************************** + /*WBGRAPHICS_DEBUG << "***************************************************************************"; + WBGRAPHICS_DEBUG << "total size" << size.height(); + WBGRAPHICS_DEBUG << "sizes (top, bottom, height):"; + WBGRAPHICS_DEBUG << "m_wideBandPanRect" << m_panRect.top() << m_panRect.bottom() << m_panRect.height(); + WBGRAPHICS_DEBUG << "m_freqScaleWideBandRect" << m_freqScaleRect.top() << m_freqScaleRect.bottom() << m_freqScaleRect.height(); + WBGRAPHICS_DEBUG << "m_dBmScaleWideBandRect" << m_dBmScaleRect.top() << m_dBmScaleRect.bottom() << m_dBmScaleRect.height(); + WBGRAPHICS_DEBUG << "";*/ +} + +void QGLWidebandPanel::saveGLState() { + + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); +} + +void QGLWidebandPanel::restoreGLState() { + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glPopAttrib(); +} + +//******************************************************************** +// HMI control + +void QGLWidebandPanel::enterEvent(QEvent *event) { + + setFocus(Qt::MouseFocusReason); + + m_mousePos = QPoint(-1, -1); + m_mouseRegion = elsewhere; + update(); + + QGLWidget::enterEvent(event); +} + +void QGLWidebandPanel::leaveEvent(QEvent *event) { + + m_mousePos = QPoint(-1, -1); + m_mouseRegion = elsewhere; + update(); + + QGLWidget::leaveEvent(event); +} + +void QGLWidebandPanel::wheelEvent(QWheelEvent* event) { + + //GRAPHICS_DEBUG << "wheelEvent"; + QPoint pos = event->pos(); + + //if (event->buttons() == Qt::NoButton) getRegion(pos); + + //double freqStep = set->getMouseWheelFreqStep(m_currentReceiver); + + //switch (m_mouseRegion) { + + // case panRegion: + + // double delta = 0; + // if (event->delta() < 0) delta = -freqStep; + // else + // if (event->delta() > 0) delta = freqStep; + + // if (m_frequency + delta > MAXHPFREQUENCY) + // m_frequency = MAXHPFREQUENCY; + // else + // if (m_frequency + delta < 0) + // m_frequency = 0; + // else + // // snap to the frequency step + // m_frequency = (long)(qRound((m_frequency + delta) / qAbs(freqStep)) * qAbs(freqStep)); + + // set->setFrequency(this, true, m_currentReceiver, m_frequency); + // break; + //} + + // //updateGL(); + //update(); +} + +void QGLWidebandPanel::mousePressEvent(QMouseEvent* event) { + + //GRAPHICS_DEBUG << "mousePressEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == freqScaleRegion) { + + m_yScaleMouseDownPos = m_freqScaleRect.topLeft(); + + if (event->buttons() == Qt::RightButton) setCursor(Qt::SplitHCursor); + update(); + + return; + } + else if (m_mouseRegion == dBmScaleRegion) { + + //m_yScaleMouseDownPos = m_dBmScaleRect.topLeft(); + + if (event->buttons() == Qt::RightButton) { + + setCursor(Qt::SplitVCursor); + m_yScaleMouseDownPos = m_dBmScaleRect.topLeft(); + } + + if (event->buttons() == Qt::LeftButton && + event->modifiers() == Qt::ControlModifier) { + + setCursor(Qt::SplitVCursor); + + m_dBmPanMinOld = m_dBmPanMin; + m_dBmPanMaxOld = m_dBmPanMax; + + m_dBmScaleOffset = 0.0; + m_calibrate = true; + } + + update(); + + return; + } + else if (m_mouseRegion == panRegion) { + + if (event->buttons() == Qt::RightButton) { + + if (m_crossHairCursor) { + + m_crossHairCursor = false; + setCursor(Qt::ArrowCursor); + } + else { + + m_crossHairCursor = true; + setCursor(Qt::BlankCursor); + } + } + else if (event->buttons() == Qt::LeftButton) { + + float unit = (float)(m_panRect.width() / (MAXHPFREQUENCY * m_freqScaleZoomFactor)); + + m_frequency = (long)(1000 * (int)(qRound(m_mousePos.x()/unit + m_lowerFrequency)/1000)); + set->setVFOFrequency(this, 1, m_currentReceiver, m_frequency); + } + update(); + + return; + } + + update(); +} + +void QGLWidebandPanel::mouseReleaseEvent(QMouseEvent *event) { + + //GRAPHICS_DEBUG << "mouseReleaseEvent"; + m_mousePos = event->pos(); + m_mouseDownPos = m_mousePos; + + getRegion(m_mousePos); + + if (m_mouseRegion == freqScaleRegion) { + + return; + } + else if (m_mouseRegion == panRegion) { + + return; + } + + if (m_calibrate) m_calibrate = false; + + update(); +} + +void QGLWidebandPanel::mouseMoveEvent(QMouseEvent* event) { + + QPoint pos = event->pos(); + m_mousePos = event->pos(); + + if (event->buttons() == Qt::NoButton) getRegion(pos); + + switch (m_mouseRegion) { + + case panRegion: + + if (m_crossHairCursor) + setCursor(Qt::BlankCursor); + else + setCursor(Qt::ArrowCursor); + + update(); + break; + + case dBmScaleRegion: + + if (event->buttons() == Qt::LeftButton && + event->modifiers() == Qt::ControlModifier) { + + QPoint dPos = m_mouseDownPos - pos; + qreal unit = (qreal)(qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height()); + qreal delta = - unit * dPos.y(); + + qreal newMin = m_dBmPanMin + delta; + qreal newMax = m_dBmPanMax + delta; + + m_dBmScaleOffset -= delta / unit; + WBGRAPHICS_DEBUG << "m_dBmScaleOffset: " << m_dBmScaleOffset; + + if (newMin > MINDBM && newMax < MAXDBM) { + + m_dBmPanMin = newMin; + m_dBmPanMax = newMax; + + //set->setWidebanddBmScaleMin(this, m_dBmPanMin); + //set->setWidebanddBmScaleMax(this, m_dBmPanMax); + } + + m_mouseDownPos = pos; + m_dBmScaleUpdate = true; + m_panGridUpdate = true; + } + else if (event->buttons() == Qt::LeftButton) { + + QPoint dPos = m_mouseDownPos - pos; + qreal unit = (qreal)(qAbs(m_dBmPanMax - m_dBmPanMin) / m_panRect.height()); + + qreal newMin = m_dBmPanMin - unit * dPos.y(); + qreal newMax = m_dBmPanMax - unit * dPos.y(); + + if (newMin > MINDBM && newMax < MAXDBM) { + + m_dBmPanMin = newMin; + m_dBmPanMax = newMax; + + set->setWidebanddBmScaleMin(this, m_dBmPanMin); + set->setWidebanddBmScaleMax(this, m_dBmPanMax); + } + + m_mouseDownPos = pos; + m_dBmScaleUpdate = true; + m_panGridUpdate = true; + } + else + if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + if (dPos.y() > 0) + m_dBmPanDelta = 1.0; + else if (dPos.y() < 0) + m_dBmPanDelta = -1.0f; + + //m_dBmPanMin += m_dBmPanDelta; + m_dBmPanMax -= m_dBmPanDelta; + + if (qAbs(m_dBmPanMax - m_dBmPanMin) < 10) { + + m_dBmPanMin -= m_dBmPanDelta; + m_dBmPanMax += m_dBmPanDelta; + } + if (m_dBmPanMin < MINDBM) m_dBmPanMin = MINDBM; + if (m_dBmPanMax > MAXDBM) m_dBmPanMax = MAXDBM; + + set->setWidebanddBmScaleMin(this, m_dBmPanMin); + set->setWidebanddBmScaleMax(this, m_dBmPanMax); + + m_mouseDownPos = pos; + m_dBmScaleUpdate = true; + m_panGridUpdate = true; + } + else + setCursor(Qt::ArrowCursor); + + update(); + break; + + case freqScaleRegion: + + if (event->buttons() == Qt::LeftButton) { + + if (m_freqScaleZoomFactor < 1.0) { + + QPoint dPos = m_mouseDownPos - pos; + + m_frequencySpan = MAXHPFREQUENCY * m_freqScaleZoomFactor; + + qreal unit = (qreal)((MAXHPFREQUENCY * m_freqScaleZoomFactor) / m_freqScaleRect.width()); + + m_lowerFrequency += unit * dPos.x(); + m_upperFrequency = m_lowerFrequency + m_frequencySpan; + + if (m_lowerFrequency < 0.0) m_lowerFrequency = 0.0; + if (m_upperFrequency > (qreal) MAXHPFREQUENCY) { + + m_upperFrequency = (qreal)MAXHPFREQUENCY; + m_lowerFrequency = (qreal)(MAXHPFREQUENCY - m_frequencySpan); + } + + m_mouseDownPos = pos; + m_freqScaleUpdate = true; + m_panGridUpdate = true; + } + else { + + m_lowerFrequency = 0.0; + m_upperFrequency = (qreal) MAXHPFREQUENCY; + } + } + else if (event->buttons() == Qt::RightButton) { + + QPoint dPos = m_mouseDownPos - pos; + + if (dPos.x() > 0) { + + m_freqScaleZoomFactor += 0.005f; + } + else if (dPos.x() < 0) + m_freqScaleZoomFactor -= 0.005f; + + if (m_freqScaleZoomFactor > 1.0) m_freqScaleZoomFactor = 1.0f; + //if (m_freqScaleZoomFactor < 0.24) m_freqScaleZoomFactor = 0.24f; + if (m_freqScaleZoomFactor < 0.15) m_freqScaleZoomFactor = 0.15f; + + qreal unit = (qreal)((MAXHPFREQUENCY * m_freqScaleZoomFactor) / m_freqScaleRect.width()); + m_lowerFrequency -= unit * dPos.x(); + m_upperFrequency = m_lowerFrequency + m_frequencySpan; + + if (m_lowerFrequency < 0.0) m_lowerFrequency = 0.0; + if (m_upperFrequency > (qreal) MAXHPFREQUENCY) { + + m_upperFrequency = (qreal)MAXHPFREQUENCY; + m_lowerFrequency = (qreal)(MAXHPFREQUENCY - m_frequencySpan); + } + + m_mouseDownPos = pos; + m_freqScaleUpdate = true; + m_panGridUpdate = true; + } + else + setCursor(Qt::ArrowCursor); + + update(); + break; + + case elsewhere: + //WBGRAPHICS_DEBUG << "elsewhere"; + + update(); + break; + } + + //if (m_oldMouseRegion != m_mouseRegion) update(); + + //m_oldMouseRegion = m_mouseRegion; + + //if (m_displayTime.elapsed() >= 50) { + + // m_displayTime.restart(); + // //updateGL(); + // update(); + //} + //setupDisplayRegions(size()); + //update(); + + //locker.unlock(); +} + +void QGLWidebandPanel::keyPressEvent(QKeyEvent* event) { + + //GRAPHICS_DEBUG << "keyPressEvent"; + if (event->key() == Qt::Key_Control) { + + //m_keyCTRLpressed = true; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //printf("Ry %f\n",ry); + //ry+=10.0f; + } + else if (event->key() == Qt::Key_T) { + + //printf("Ry %f\n",ry); + //ry-=10.0f; + } + else if (event->key() == Qt::Key_P) { + + //drawTeapot = !drawTeapot; + } + else if (event->key() == Qt::Key_W) { + + //approach -= 0.1f; + } + else if (event->key() == Qt::Key_S) { + + //approach += 0.1f; + } + else { + + //m_keyCTRLpressed = false; + //GRAPHICS_DEBUG << "m_keyCTRLpressed =" << m_keyCTRLpressed; + //event->ignore(); + } + + QWidget::keyPressEvent(event); + //updateGL(); + update(); +} + +void QGLWidebandPanel::timerEvent(QTimerEvent *) { + + update(); +} + +//******************************************************************** + +void QGLWidebandPanel::setFrequency(QObject *sender, int mode, int rx, long freq) { + + Q_UNUSED (sender) + Q_UNUSED (mode) + Q_UNUSED (rx) + + m_frequency = freq; + m_freqScaleUpdate = true; + m_panGridUpdate = true; + + //updateGL(); + update(); +} + +void QGLWidebandPanel::setCurrentReceiver(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_currentReceiver = value; + update(); +} + +//void QGLWidebandPanel::computeDisplayBins(const float *panBuffer) { +// +// //int newSampleSize = 0; +// //int deltaSampleSize = 0; +// //int idx = 0; +// //int lIdx = 0; +// //int rIdx = 0; +// //qreal localMax; +// +// +// //m_panScale = (qreal)(1.0 * newSampleSize / m_panRectWidth); +// //m_scaleMultOld = m_displayData.scaleMult; +// // +// //if (m_panScale < 0.125) { +// // m_displayData.scaleMult = 0.0625; +// //} +// //else if (m_panScale < 0.25) { +// // m_displayData.scaleMult = 0.125; +// //} +// //else if (m_panScale < 0.5) { +// // m_displayData.scaleMult = 0.25; +// //} +// //else if (m_panScale < 1.0) { +// // m_displayData.scaleMult = 0.5; +// //} +// //else { +// // m_displayData.scaleMult = 1.0; +// //} +// +// //m_panSpectrumBinsLength = (GLint)(m_displayData.scaleMult * m_panRectWidth); +// +// //if (m_scaleMultOld != m_displayData.scaleMult) { +// +// // m_displayData.waterfallUpdate = true; +// //} +// +// //m_displayData.waterfallPixel.clear(); +// //m_displayData.waterfallPixel.resize(4 * m_panRectWidth); +// +// //m_displayData.panadapterBins.clear(); +// // +// //for (int i = 0; i < m_panSpectrumBinsLength; i++) { +// // +// // idx = 0; +// // lIdx = (int)floor((qreal)(i * m_panScale / m_displayData.scaleMult)); +// // rIdx = (int)floor((qreal)(i * m_panScale / m_displayData.scaleMult) + m_panScale / m_displayData.scaleMult); +// // +// // // max value; later we try mean value also! +// // localMax = -10000.0F; +// // for (int j = lIdx; j < rIdx; j++) { +// +// // if (panBuffer[j] > localMax) { +// +// // localMax = panBuffer[j]; +// // idx = j; +// // } +// // } +// // idx += deltaSampleSize/2; +// // +// // m_displayData.panadapterBins << panBuffer[idx] - m_displayData.dBmPanMin - m_dBmPanLogGain; +// +// //update(); +// ////updateGL(); +//} + +void QGLWidebandPanel::setWidebandSpectrumBuffer(const qVectorFloat &buffer) { + + //int deltaIdx; + //qreal frequencyScale; + //qreal scaleMult = 1.0; + + m_wbSpectrumBufferLength = buffer.size(); + + mutex.lock(); + m_wbSpectrumBuffer.resize(m_wbSpectrumBufferLength); + m_wbSpectrumBuffer = buffer; + + //m_scaledBufferSize = qFloor(m_wbSpectrumBufferLength * m_freqScaleZoomFactor); + mutex.unlock(); + +// deltaIdx = qFloor((qreal)(m_wbSpectrumBufferLength * (m_lowerFrequency / MAXHPFREQUENCY))); +// frequencyScale = (qreal)(1.0f * m_scaledBufferSize / width); +// +// if (frequencyScale < 0.125) +// scaleMult = 0.0625; +// else if (frequencyScale < 0.25) +// scaleMult = 0.125; +// else if (frequencyScale < 0.5) +// scaleMult = 0.25; +// else if (frequencyScale < 1.0) +// scaleMult = 0.5; + + update(); +} + +void QGLWidebandPanel::resetWidebandSpectrumBuffer() { + + m_wbSpectrumBuffer.resize(BIGWIDEBANDSIZE / 2); + m_wbSpectrumBuffer.fill(-1000.0f); +} + +void QGLWidebandPanel::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + Q_UNUSED (hwmode) + Q_UNUSED (state) + + //bool change = false; + + if (m_dataEngineState != state) { + + m_dataEngineState = state; + //change = true; + } + + //if (m_serverMode != mode) + // m_serverMode = mode; + + if (m_serverMode == mode) + return; + else { + + m_wbSpectrumBuffer.fill(-10000.0); + //memset(&m_wbSpectrumBuffer, -10000, 4 * BUFFER_SIZE * sizeof(float)); + m_serverMode = mode; + } + + //resizeGL(width(), height()); + m_displayTime.restart(); + + update(); +} + +void QGLWidebandPanel::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode colorScheme) +{ + Q_UNUSED (sender) + //Q_UNUSED (rx) + + if (rx != -1) return; + + bool change = false; + + if (m_panMode != panMode) { + + m_panMode = panMode; + change = true; + } + + if (m_waterfallMode != colorScheme) { + + m_waterfallMode = colorScheme; + change = true; + } + + if (!change) return; + + update(); +} + + +//void QGLWidebandPanel::setSpectrumAveragingCnt(int value) { +// +// mutex.lock(); +// +// memset(m_tmpBuf, 0, SAMPLE_BUFFER_SIZE * sizeof(float)); +// +// while (!specAv_queue.isEmpty()) +// specAv_queue.dequeue(); +// +// m_specAveragingCnt = value; +// +// if (m_specAveragingCnt > 0) +// m_scale = 1.0f / m_specAveragingCnt; +// else +// m_scale = 1.0f; +// +// mutex.unlock(); +//} + +void QGLWidebandPanel::setMercuryAttenuator(QObject* sender, HamBand band, int value) { + + Q_UNUSED(sender) + Q_UNUSED(band) + + m_mercuryAttenuator = value; + update(); +} + +void QGLWidebandPanel::setPanadapterColors() { + + m_spectrumColorsChanged = true; + + mutex.lock(); + m_bkgRed = (GLfloat)(set->getPanadapterColors().panBackgroundColor.red() / 256.0); + m_bkgGreen = (GLfloat)(set->getPanadapterColors().panBackgroundColor.green() / 256.0); + m_bkgBlue = (GLfloat)(set->getPanadapterColors().panBackgroundColor.blue() / 256.0); + + m_r = (GLfloat)(set->getPanadapterColors().wideBandLineColor.red() / 256.0); + m_g = (GLfloat)(set->getPanadapterColors().wideBandLineColor.green() / 256.0); + m_b = (GLfloat)(set->getPanadapterColors().wideBandLineColor.blue() / 256.0); + + m_rf = (GLfloat)(set->getPanadapterColors().wideBandFilledColor.red() / 256.0); + m_gf = (GLfloat)(set->getPanadapterColors().wideBandFilledColor.green() / 256.0); + m_bf = (GLfloat)(set->getPanadapterColors().wideBandFilledColor.blue() / 256.0); + + m_redST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.red() / 256.0); + m_greenST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.green() / 256.0); + m_blueST = (GLfloat)(set->getPanadapterColors().panSolidTopColor.blue() / 256.0); + + m_redSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.red() / 256.0); + m_greenSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.green() / 256.0); + m_blueSB = (GLfloat)(set->getPanadapterColors().panSolidBottomColor.blue() / 256.0); + + QColor gridColor = m_gridColor; + m_gridColor = set->getPanadapterColors().gridLineColor; + + if (gridColor != m_gridColor) { + + m_redGrid = (GLfloat)(m_gridColor.red()/256.0); + m_greenGrid = (GLfloat)(m_gridColor.green()/256.0); + m_blueGrid = (GLfloat)(m_gridColor.blue()/256.0); + + m_panGridUpdate = true; + } + mutex.unlock(); + + update(); +} + +void QGLWidebandPanel::setPanGridStatus(bool value, int rx) { + + Q_UNUSED (rx) + + mutex.lock(); + + if (m_panGrid == value) + return; + else + m_panGrid = value; + + mutex.unlock(); + update(); +} + +void QGLWidebandPanel::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; + update(); +} + +void QGLWidebandPanel::freqScaleUpdate(bool value) { + + m_freqScaleUpdate = value; +} + +void QGLWidebandPanel::freqScaleRenew(bool value) { + + m_freqScaleRenew = value; +} + +void QGLWidebandPanel::dBmScaleUpdate(bool value) { + + m_dBmScaleUpdate = value; +} + +void QGLWidebandPanel::dBmScaleRenew(bool value) { + + m_dBmScaleRenew = value; +} + +void QGLWidebandPanel::panGridUpdate(bool value) { + + m_panGridUpdate = value; +} + +void QGLWidebandPanel::panGridRenew(bool value) { + + m_panGridRenew = value; +} + +void QGLWidebandPanel::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void QGLWidebandPanel::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} diff --git a/Source/src/GL/cusdr_oglWidebandPanel.h b/Source/src/GL/cusdr_oglWidebandPanel.h new file mode 100644 index 0000000..8ac563a --- /dev/null +++ b/Source/src/GL/cusdr_oglWidebandPanel.h @@ -0,0 +1,290 @@ +/** +* @file cusdr_oglWidebandPanel.h +* @brief wide band spectrum panel header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-02-11 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_OGL_WIDEBANDPANEL_H +#define _CUSDR_OGL_WIDEBANDPANEL_H + +#include "cusdr_oglUtils.h" +#include "cusdr_oglInfo.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" +#include "cusdr_oglText.h" + +//#include +//#include +//#include +#include +//#include +//#include +//#include +//#include + +#ifdef LOG_WBGRAPHICS +# define WBGRAPHICS_DEBUG qDebug().nospace() << "WB-Graphics::\t" +#else +# define WBGRAPHICS_DEBUG nullDebug() +#endif + + +class QGLWidebandPanel : public QGLWidget { + + Q_OBJECT + +public: + QGLWidebandPanel(QWidget *parent = 0); + ~QGLWidebandPanel(); + +public slots: + QSize minimumSizeHint() const; + QSize sizeHint() const; + + //void setSpectrumBuffer(const float *buffer); + //void setFrequency(QObject *sender, bool value, long freq); + +protected: + void initializeGL(); + void resizeGL(int iWidth, int iHeight); + void paintGL(); + + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event ); + void keyPressEvent(QKeyEvent* event); + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void timerEvent(QTimerEvent *); + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + PanGraphicsMode m_panMode; + WaterfallColorMode m_waterfallMode; + + QVector m_widebandPanSpectrumBins; + QQueue > specAv_queue; + QList m_rxDataList; + TWideband m_widebandOptions; + + QGLFramebufferObject* m_frequencyScaleFBO; + QGLFramebufferObject* m_dBmScaleFBO; + QGLFramebufferObject* m_gridFBO; + + CFonts *fonts; + TFonts m_fonts; + + QTime m_panTimer; + QTime m_displayTime; + QTime m_resizeTime; + + QRect m_panRect; + QRect m_freqScaleRect; + QRect m_dBmScaleRect; + + QMutex mutex; + + OGLText *m_oglTextTiny; + OGLText *m_oglTextSmall; + OGLText *m_oglTextNormal; + + QPoint m_mousePos; + QPoint m_oldMousePos; + QPoint m_mouseLastPos; + QPoint m_mouseDownPos; + QPoint m_yScaleMouseDownPos; + QPoint m_cameraAngle; + + TScale m_frequencyScale; + TScale m_dBmScale; + + QColor m_gridColor; + + GLfloat m_redGrid; + GLfloat m_greenGrid; + GLfloat m_blueGrid; + + GLfloat m_r; + GLfloat m_g; + GLfloat m_b; + + GLfloat m_rf; + GLfloat m_gf; + GLfloat m_bf; + + GLfloat m_redST; + GLfloat m_greenST; + GLfloat m_blueST; + + GLfloat m_redSB; + GLfloat m_greenSB; + GLfloat m_blueSB; + + GLfloat m_bkgRed; + GLfloat m_bkgGreen; + GLfloat m_bkgBlue; + + enum Region { + + panRegion, + freqScaleRegion, + dBmScaleRegion, + elsewhere, + out + }; + + long m_frequency; + + qreal m_dBmPanMin; + qreal m_dBmPanMax; + qreal m_dBmPanMinOld; + qreal m_dBmPanMaxOld; + + + qVectorFloat m_wbSpectrumBuffer; + + float m_scale; + float m_distMax; + + bool m_spectrumUpdate; + bool m_freqScaleUpdate; + bool m_freqScaleRenew; + bool m_dBmScaleUpdate; + bool m_dBmScaleRenew; + bool m_panGridUpdate; + bool m_panGridRenew; + bool m_spectrumColorsChanged; + bool m_spectrumVertexColorUpdate; + bool m_crossHairCursor; + bool m_panGrid; + bool m_calibrate; + + int m_receiver; + int m_oldWidth; + int m_oldHeight; + int m_oldPanRectHeight; + int m_cnt; + int m_specAveragingCnt; + int m_mercuryAttenuator; + int m_dBmScaleTextPos; + int m_wbSpectrumBufferLength; + int m_scaledBufferSize; + + float m_cameraDistance; + + unsigned int timer; + + GLint m_panRectWidth; + GLint m_panSpectrumBinsLength; + + int m_mouseRegion; + int m_oldMouseRegion; + int m_snapMouse; + + int m_currentReceiver; + int m_freqScaleWidth; + int m_displayTop; + int m_dBmPanLogGain; + int m_panDisplayMode; + int m_sampleRate; + int m_downRate; + + float m_freqScalePosition; + float m_freqScaleZoomFactor; + + qreal m_dBmPanDelta; + qreal m_dBmScaleOffset; + qreal m_panScale; + qreal m_scaleMultOld; + qreal m_panFrequencyScale; + qreal m_frequencySpan; + qreal m_frequencyUnit; + qreal m_lowerFrequency; + qreal m_upperFrequency; + + //****************************************************************** + void saveGLState(); + void restoreGLState(); + //void computeDisplayBins(const float* panBuffer); + + void drawSpectrum(); + void drawVerticalScale(); + void drawHorizontalScale(); + void drawGrid(); + void drawCrossHair(); + void drawHamBand(int lo, int hi, const QString &band); + + void renderVerticalScale(); + void renderHorizontalScale(); + void renderGrid(); + +private slots: + void systemStateChanged( + QObject* sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject* sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setupConnections(); + void setCurrentReceiver(QObject *sender, int value); + void setFrequency(QObject *sender, int mode, int rx, long freq); + void setupDisplayRegions(QSize size); + void setWidebandSpectrumBuffer(const qVectorFloat &buffer); + void resetWidebandSpectrumBuffer(); + //void setSpectrumAveragingCnt(int value); + void setPanadapterColors(); + void setPanGridStatus(bool value, int rx); + void setMercuryAttenuator(QObject* sender, HamBand band, int value); + + void getRegion(QPoint p); + void sampleRateChanged(QObject* sender, int value); + void freqScaleUpdate(bool value); + void freqScaleRenew(bool value); + void dBmScaleUpdate(bool value); + void dBmScaleRenew(bool value); + void panGridUpdate(bool value); + void panGridRenew(bool value); + +signals: + void showEvent(QObject* sender); + void closeEvent(QObject* sender); + void messageEvent(QString msg); + void coordChanged(int x, int y); +}; + +#endif // _CUSDR_OGL_WIDEBANDPANEL_H diff --git a/Source/src/QtDSP/fftw3.h b/Source/src/QtDSP/fftw3.h new file mode 100644 index 0000000..6fabb7e --- /dev/null +++ b/Source/src/QtDSP/fftw3.h @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2003, 2007-11 Matteo Frigo + * Copyright (c) 2003, 2007-11 Massachusetts Institute of Technology + * + * The following statement of license applies *only* to this header file, + * and *not* to the other files distributed with FFTW or derived therefrom: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/***************************** NOTE TO USERS ********************************* + * + * THIS IS A HEADER FILE, NOT A MANUAL + * + * If you want to know how to use FFTW, please read the manual, + * online at http://www.fftw.org/doc/ and also included with FFTW. + * For a quick start, see the manual's tutorial section. + * + * (Reading header files to learn how to use a library is a habit + * stemming from code lacking a proper manual. Arguably, it's a + * *bad* habit in most cases, because header files can contain + * interfaces that are not part of the public, stable API.) + * + ****************************************************************************/ + +#ifndef FFTW3_H +#define FFTW3_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* If is included, use the C99 complex type. Otherwise + define a type bit-compatible with C99 complex */ +#if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I) +# define FFTW_DEFINE_COMPLEX(R, C) typedef R _Complex C +#else +# define FFTW_DEFINE_COMPLEX(R, C) typedef R C[2] +#endif + +#define FFTW_CONCAT(prefix, name) prefix ## name +#define FFTW_MANGLE_DOUBLE(name) FFTW_CONCAT(fftw_, name) +#define FFTW_MANGLE_FLOAT(name) FFTW_CONCAT(fftwf_, name) +#define FFTW_MANGLE_LONG_DOUBLE(name) FFTW_CONCAT(fftwl_, name) +#define FFTW_MANGLE_QUAD(name) FFTW_CONCAT(fftwq_, name) + +/* IMPORTANT: for Windows compilers, you should add a line +*/ +#define FFTW_DLL +/* + here and in kernel/ifftw.h if you are compiling/using FFTW as a + DLL, in order to do the proper importing/exporting, or + alternatively compile with -DFFTW_DLL or the equivalent + command-line flag. This is not necessary under MinGW/Cygwin, where + libtool does the imports/exports automatically. */ +#if defined(FFTW_DLL) && (defined(_WIN32) || defined(__WIN32__)) + /* annoying Windows syntax for shared-library declarations */ +# if defined(COMPILING_FFTW) /* defined in api.h when compiling FFTW */ +# define FFTW_EXTERN extern __declspec(dllexport) +# else /* user is calling FFTW; import symbol */ +# define FFTW_EXTERN extern __declspec(dllimport) +# endif +#else +# define FFTW_EXTERN extern +#endif + +enum fftw_r2r_kind_do_not_use_me { + FFTW_R2HC=0, FFTW_HC2R=1, FFTW_DHT=2, + FFTW_REDFT00=3, FFTW_REDFT01=4, FFTW_REDFT10=5, FFTW_REDFT11=6, + FFTW_RODFT00=7, FFTW_RODFT01=8, FFTW_RODFT10=9, FFTW_RODFT11=10 +}; + +struct fftw_iodim_do_not_use_me { + int n; /* dimension size */ + int is; /* input stride */ + int os; /* output stride */ +}; + +#include /* for ptrdiff_t */ +struct fftw_iodim64_do_not_use_me { + ptrdiff_t n; /* dimension size */ + ptrdiff_t is; /* input stride */ + ptrdiff_t os; /* output stride */ +}; + +typedef void (*fftw_write_char_func_do_not_use_me)(char c, void *); +typedef int (*fftw_read_char_func_do_not_use_me)(void *); + +/* + huge second-order macro that defines prototypes for all API + functions. We expand this macro for each supported precision + + X: name-mangling macro + R: real data type + C: complex data type +*/ + +#define FFTW_DEFINE_API(X, R, C) \ + \ +FFTW_DEFINE_COMPLEX(R, C); \ + \ +typedef struct X(plan_s) *X(plan); \ + \ +typedef struct fftw_iodim_do_not_use_me X(iodim); \ +typedef struct fftw_iodim64_do_not_use_me X(iodim64); \ + \ +typedef enum fftw_r2r_kind_do_not_use_me X(r2r_kind); \ + \ +typedef fftw_write_char_func_do_not_use_me X(write_char_func); \ +typedef fftw_read_char_func_do_not_use_me X(read_char_func); \ + \ +FFTW_EXTERN void X(execute)(const X(plan) p); \ + \ +FFTW_EXTERN X(plan) X(plan_dft)(int rank, const int *n, \ + C *in, C *out, int sign, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_dft_1d)(int n, C *in, C *out, int sign, \ + unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_dft_2d)(int n0, int n1, \ + C *in, C *out, int sign, unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_dft_3d)(int n0, int n1, int n2, \ + C *in, C *out, int sign, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_many_dft)(int rank, const int *n, \ + int howmany, \ + C *in, const int *inembed, \ + int istride, int idist, \ + C *out, const int *onembed, \ + int ostride, int odist, \ + int sign, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru_dft)(int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + C *in, C *out, \ + int sign, unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_guru_split_dft)(int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + R *ri, R *ii, R *ro, R *io, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru64_dft)(int rank, \ + const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + C *in, C *out, \ + int sign, unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_guru64_split_dft)(int rank, \ + const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + R *ri, R *ii, R *ro, R *io, \ + unsigned flags); \ + \ +FFTW_EXTERN void X(execute_dft)(const X(plan) p, C *in, C *out); \ +FFTW_EXTERN void X(execute_split_dft)(const X(plan) p, R *ri, R *ii, \ + R *ro, R *io); \ + \ +FFTW_EXTERN X(plan) X(plan_many_dft_r2c)(int rank, const int *n, \ + int howmany, \ + R *in, const int *inembed, \ + int istride, int idist, \ + C *out, const int *onembed, \ + int ostride, int odist, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_dft_r2c)(int rank, const int *n, \ + R *in, C *out, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_dft_r2c_1d)(int n,R *in,C *out,unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_dft_r2c_2d)(int n0, int n1, \ + R *in, C *out, unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_dft_r2c_3d)(int n0, int n1, \ + int n2, \ + R *in, C *out, unsigned flags); \ + \ + \ +FFTW_EXTERN X(plan) X(plan_many_dft_c2r)(int rank, const int *n, \ + int howmany, \ + C *in, const int *inembed, \ + int istride, int idist, \ + R *out, const int *onembed, \ + int ostride, int odist, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_dft_c2r)(int rank, const int *n, \ + C *in, R *out, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_dft_c2r_1d)(int n,C *in,R *out,unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_dft_c2r_2d)(int n0, int n1, \ + C *in, R *out, unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_dft_c2r_3d)(int n0, int n1, \ + int n2, \ + C *in, R *out, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru_dft_r2c)(int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + R *in, C *out, \ + unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_guru_dft_c2r)(int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + C *in, R *out, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru_split_dft_r2c)( \ + int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + R *in, R *ro, R *io, \ + unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_guru_split_dft_c2r)( \ + int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + R *ri, R *ii, R *out, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru64_dft_r2c)(int rank, \ + const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + R *in, C *out, \ + unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_guru64_dft_c2r)(int rank, \ + const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + C *in, R *out, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru64_split_dft_r2c)( \ + int rank, const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + R *in, R *ro, R *io, \ + unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_guru64_split_dft_c2r)( \ + int rank, const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + R *ri, R *ii, R *out, \ + unsigned flags); \ + \ +FFTW_EXTERN void X(execute_dft_r2c)(const X(plan) p, R *in, C *out); \ +FFTW_EXTERN void X(execute_dft_c2r)(const X(plan) p, C *in, R *out); \ + \ +FFTW_EXTERN void X(execute_split_dft_r2c)(const X(plan) p, \ + R *in, R *ro, R *io); \ +FFTW_EXTERN void X(execute_split_dft_c2r)(const X(plan) p, \ + R *ri, R *ii, R *out); \ + \ +FFTW_EXTERN X(plan) X(plan_many_r2r)(int rank, const int *n, \ + int howmany, \ + R *in, const int *inembed, \ + int istride, int idist, \ + R *out, const int *onembed, \ + int ostride, int odist, \ + const X(r2r_kind) *kind, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_r2r)(int rank, const int *n, R *in, R *out, \ + const X(r2r_kind) *kind, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_r2r_1d)(int n, R *in, R *out, \ + X(r2r_kind) kind, unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_r2r_2d)(int n0, int n1, R *in, R *out, \ + X(r2r_kind) kind0, X(r2r_kind) kind1, \ + unsigned flags); \ +FFTW_EXTERN X(plan) X(plan_r2r_3d)(int n0, int n1, int n2, \ + R *in, R *out, X(r2r_kind) kind0, \ + X(r2r_kind) kind1, X(r2r_kind) kind2, \ + unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru_r2r)(int rank, const X(iodim) *dims, \ + int howmany_rank, \ + const X(iodim) *howmany_dims, \ + R *in, R *out, \ + const X(r2r_kind) *kind, unsigned flags); \ + \ +FFTW_EXTERN X(plan) X(plan_guru64_r2r)(int rank, const X(iodim64) *dims, \ + int howmany_rank, \ + const X(iodim64) *howmany_dims, \ + R *in, R *out, \ + const X(r2r_kind) *kind, unsigned flags); \ + \ +FFTW_EXTERN void X(execute_r2r)(const X(plan) p, R *in, R *out); \ + \ +FFTW_EXTERN void X(destroy_plan)(X(plan) p); \ +FFTW_EXTERN void X(forget_wisdom)(void); \ +FFTW_EXTERN void X(cleanup)(void); \ + \ +FFTW_EXTERN void X(set_timelimit)(double t); \ + \ +FFTW_EXTERN void X(plan_with_nthreads)(int nthreads); \ +FFTW_EXTERN int X(init_threads)(void); \ +FFTW_EXTERN void X(cleanup_threads)(void); \ + \ +FFTW_EXTERN int X(export_wisdom_to_filename)(const char *filename); \ +FFTW_EXTERN void X(export_wisdom_to_file)(FILE *output_file); \ +FFTW_EXTERN char *X(export_wisdom_to_string)(void); \ +FFTW_EXTERN void X(export_wisdom)(X(write_char_func) write_char, \ + void *data); \ +FFTW_EXTERN int X(import_system_wisdom)(void); \ +FFTW_EXTERN int X(import_wisdom_from_filename)(const char *filename); \ +FFTW_EXTERN int X(import_wisdom_from_file)(FILE *input_file); \ +FFTW_EXTERN int X(import_wisdom_from_string)(const char *input_string); \ +FFTW_EXTERN int X(import_wisdom)(X(read_char_func) read_char, void *data); \ + \ +FFTW_EXTERN void X(fprint_plan)(const X(plan) p, FILE *output_file); \ +FFTW_EXTERN void X(print_plan)(const X(plan) p); \ + \ +FFTW_EXTERN void *X(malloc)(size_t n); \ +FFTW_EXTERN R *X(alloc_real)(size_t n); \ +FFTW_EXTERN C *X(alloc_complex)(size_t n); \ +FFTW_EXTERN void X(free)(void *p); \ + \ +FFTW_EXTERN void X(flops)(const X(plan) p, \ + double *add, double *mul, double *fmas); \ +FFTW_EXTERN double X(estimate_cost)(const X(plan) p); \ +FFTW_EXTERN double X(cost)(const X(plan) p); \ + \ +FFTW_EXTERN const char X(version)[]; \ +FFTW_EXTERN const char X(cc)[]; \ +FFTW_EXTERN const char X(codelet_optim)[]; + + +/* end of FFTW_DEFINE_API macro */ + +FFTW_DEFINE_API(FFTW_MANGLE_DOUBLE, double, fftw_complex) +FFTW_DEFINE_API(FFTW_MANGLE_FLOAT, float, fftwf_complex) +FFTW_DEFINE_API(FFTW_MANGLE_LONG_DOUBLE, long double, fftwl_complex) + +/* __float128 (quad precision) is a gcc extension on i386, x86_64, and ia64 + for gcc >= 4.6 (compiled in FFTW with --enable-quad-precision) */ +#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) \ + && !(defined(__ICC) || defined(__INTEL_COMPILER)) \ + && (defined(__i386__) || defined(__x86_64__) || defined(__ia64__)) +# if !defined(FFTW_NO_Complex) && defined(_Complex_I) && defined(complex) && defined(I) +/* note: __float128 is a typedef, which is not supported with the _Complex + keyword in gcc, so instead we use this ugly __attribute__ version. + However, we can't simply pass the __attribute__ version to + FFTW_DEFINE_API because the __attribute__ confuses gcc in pointer + types. Hence redefining FFTW_DEFINE_COMPLEX. Ugh. */ +# undef FFTW_DEFINE_COMPLEX +# define FFTW_DEFINE_COMPLEX(R, C) typedef _Complex float __attribute__((mode(TC))) C +# endif +FFTW_DEFINE_API(FFTW_MANGLE_QUAD, __float128, fftwq_complex) +#endif + +#define FFTW_FORWARD (-1) +#define FFTW_BACKWARD (+1) + +#define FFTW_NO_TIMELIMIT (-1.0) + +/* documented flags */ +#define FFTW_MEASURE (0U) +#define FFTW_DESTROY_INPUT (1U << 0) +#define FFTW_UNALIGNED (1U << 1) +#define FFTW_CONSERVE_MEMORY (1U << 2) +#define FFTW_EXHAUSTIVE (1U << 3) /* NO_EXHAUSTIVE is default */ +#define FFTW_PRESERVE_INPUT (1U << 4) /* cancels FFTW_DESTROY_INPUT */ +#define FFTW_PATIENT (1U << 5) /* IMPATIENT is default */ +#define FFTW_ESTIMATE (1U << 6) +#define FFTW_WISDOM_ONLY (1U << 21) + +/* undocumented beyond-guru flags */ +#define FFTW_ESTIMATE_PATIENT (1U << 7) +#define FFTW_BELIEVE_PCOST (1U << 8) +#define FFTW_NO_DFT_R2HC (1U << 9) +#define FFTW_NO_NONTHREADED (1U << 10) +#define FFTW_NO_BUFFERING (1U << 11) +#define FFTW_NO_INDIRECT_OP (1U << 12) +#define FFTW_ALLOW_LARGE_GENERIC (1U << 13) /* NO_LARGE_GENERIC is default */ +#define FFTW_NO_RANK_SPLITS (1U << 14) +#define FFTW_NO_VRANK_SPLITS (1U << 15) +#define FFTW_NO_VRECURSE (1U << 16) +#define FFTW_NO_SIMD (1U << 17) +#define FFTW_NO_SLOW (1U << 18) +#define FFTW_NO_FIXED_RADIX_LARGE_N (1U << 19) +#define FFTW_ALLOW_PRUNING (1U << 20) + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* FFTW3_H */ diff --git a/Source/src/QtDSP/qtdsp_agc.cpp b/Source/src/QtDSP/qtdsp_agc.cpp new file mode 100644 index 0000000..69a22c9 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_agc.cpp @@ -0,0 +1,303 @@ +/** +* @file qtdsp_agc.cpp +* @brief AGC class for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-14 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for cuSDR by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qtdsp_agc.h" + +#include + +QAGC::QAGC(QObject *parent, int size) + : QObject(parent) + , set(Settings::instance()) + , m_size(size) + , m_mask(size * 2) + , m_index(0) + , m_sndex(0) + , m_hangIndex(0) + , m_fastIndex(FASTLEAD) + , m_fastHang(0) + , m_samplerate(set->getSampleRate()) + //, m_agcMode(agcMED) + , m_gainTop(qPow(10.0f, 120.0f/20.0f)) + , m_gainNow(1.0f) + , m_gainFastNow(1.0f) + , m_gainBottom(.001f) + , m_gainLimit(1.0f) + //, m_gainFix(pow(10.0, 60.0/20.0)) + , m_gainFix(qPow(10.0f, 80.0f/20.0f)) + , m_attack(0.0f) + , m_oneMAttack(0.0f) + , m_decay(0.0f) + , m_oneMDecay(0.0f) + , m_slope(1.0f) + , m_fastAttack(0.0f) + , m_oneMFastAttack(0.0f) + , m_fastDecay(0.0f) + , m_oneMFastDecay(0.0f) + , m_hangTime(480.0f * 0.001f) + , m_hangThresh(0.001f) + , m_fastHangTime(48.0f * 0.001f) +{ + setAttack(1.0); + setDecay(1.0); + setMode(agcMED); + + m_fastAttack = 1.0 - qExp(-1000.0 / (0.2f * m_samplerate)); + m_oneMFastAttack = qExp(-1000.0 / (0.2 * m_samplerate)); + + m_fastDecay = 1.0 - qExp(-1000.0 / (3.0 * m_samplerate)); + m_oneMFastDecay = qExp(-1000.0 / (3.0 * m_samplerate)); + + InitCPX(G, m_mask, 0.0f); + + m_mask -= 1; +} + +QAGC::~QAGC() { + + G.clear(); +} + +void QAGC::ProcessAGC(const CPX &in, CPX &out, int size) { + + if (m_agcMode == agcOFF) { + + for (int i = 0; i < size; i++) + out[i] = ScaleCPX(in[i], m_gainFix); + + //memcpy(out.data(), in.data(), size * sizeof(cpx)); + return; + } + + unsigned int hangTime = (unsigned int)(m_samplerate * m_hangTime); + unsigned int fastHangTime = (unsigned int)(m_samplerate * m_fastHangTime); + + float hangThresh = 0.0; + + if (m_hangThresh > 0.0) + hangThresh = m_gainTop * m_hangThresh + m_gainBottom * (1.0 - m_hangThresh); + + for (int i = 0; i < m_size; i++) { + + G[m_index] = in.at(i); + + float tmp = 1.1 * SqrMagCPX(G.at(m_index)); + + if (tmp == 0.0) + tmp = m_gainNow; + else + tmp = m_gainLimit / tmp; + + if (tmp < hangThresh) + m_hangIndex = hangTime; + + if (tmp > m_gainNow) { + + if (m_hangIndex++ > (qint16)hangTime) + m_gainNow = m_oneMDecay * m_gainNow + m_decay * qMin(m_gainTop, tmp); + } + else { + + m_hangIndex = 0; + m_gainNow = m_oneMAttack * m_gainNow + m_attack * qMax(tmp, m_gainBottom); + } + + tmp = 1.2 * SqrMagCPX(G[m_fastIndex]); + + if (tmp != 0.0) + tmp = m_gainLimit / tmp; + else + tmp = m_gainFastNow; + + if (tmp > m_gainFastNow) { + + if (m_fastHang++ > (qint16)fastHangTime) + m_gainFastNow = qMin(m_oneMFastDecay * m_gainFastNow + m_fastDecay * qMin(m_gainTop, tmp), m_gainTop); + } + else { + + m_fastHang = 0; + m_gainFastNow = qMax(m_oneMFastAttack * m_gainFastNow + m_fastAttack * qMax(tmp, m_gainBottom), m_gainBottom); + } + + m_gainFastNow = qMax(qMin(m_gainFastNow, m_gainTop), m_gainBottom); + m_gainNow = qMax(qMin(m_gainNow, m_gainTop), m_gainBottom); + + out[i].re = Scale(G.at(m_sndex).re, qMin(m_gainFastNow, qMin(m_slope * m_gainNow, m_gainTop))); + out[i].im = Scale(G.at(m_sndex).im, qMin(m_gainFastNow, qMin(m_slope * m_gainNow, m_gainTop))); + + m_index = (m_index + m_mask) & m_mask; + m_sndex = (m_sndex + m_mask) & m_mask; + + m_fastIndex = (m_fastIndex + m_mask) & m_mask; + } +} + +void QAGC::setMode(AGCMode mode) { + + mutex.lock(); + m_agcMode = mode; + + switch (mode) { + + case agcOFF: + break; + + case agcSLOW: + + m_hangTime = 0.5; + m_fastHangTime = 0.1F; + m_decay = 1.0 - qExp(-2.0 / m_samplerate); + m_oneMDecay = 1.0 - m_decay; + break; + + case agcMED: + + m_hangTime = 0.25; + m_fastHangTime = 0.1f; + m_decay = 1.0 - qExp(-4.0 / m_samplerate); + m_oneMDecay = 1.0 - m_decay; + break; + + case agcFAST: + + m_hangTime = 0.1f; + m_fastHangTime = 0.1f; + m_decay = 1.0 - qExp(-10.0 / m_samplerate); + m_oneMDecay = 1.0 - m_decay; + break; + + case agcLONG: + m_hangTime = 0.75; + m_fastHangTime = 0.1f; + m_decay = 1.0 - qExp(-0.5 / m_samplerate); + m_oneMDecay = 1.0 - m_decay; + break; + + case agcUser: + break; + } + mutex.unlock(); +} + +float QAGC::gain() const { + + return 20.0 * log10(m_gainNow); +} + +void QAGC::setGain(float gain) { + + mutex.lock(); + m_gainNow = qPow(10.0, gain/20.0); + mutex.unlock(); +} + +float QAGC::fastGain() const { + + return 20.0 * log10(m_gainFastNow); +} + +float QAGC::hangTime() const { + + return m_hangTime / 0.001; +} + +void QAGC::setHangTime(float time) { + + mutex.lock(); + m_hangTime = time * 0.001; + mutex.unlock(); +} + +float QAGC::gainTop() const { + + return 20.0 * log10(m_gainTop); +} + +void QAGC::setGainTop(float gain) { + + mutex.lock(); + m_gainTop = qPow(10.0, gain/20.0); + mutex.unlock(); +} + +float QAGC::gainBottom() const { + + return 20.0 * log10(m_gainBottom); +} + +void QAGC::setGainBottom(float gain) { + + mutex.lock(); + m_gainBottom = qPow(10.0, gain/20.0); + mutex.unlock(); +} + +float QAGC::attack() const { return m_attack; } + +void QAGC::setAttack(float attack) { + + mutex.lock(); + m_attack = 1.0 - qExp(-1000.0 / (attack * m_samplerate)); + m_oneMAttack = qExp (-1000.0 / (attack * m_samplerate)); + + m_sndex = (m_index + (int)(0.003 * m_samplerate * attack)) & m_mask; + m_fastIndex = (m_sndex + FASTLEAD * m_mask) & m_mask; + + m_fastHangTime = 0.1f; + mutex.unlock(); +} + +float QAGC::decay() const { + + return m_decay; +} + +void QAGC::setDecay(float decay) { + + mutex.lock(); + m_decay = 1.0 - qExp(-1000.0 / (decay * m_samplerate)); + m_oneMDecay = qExp(-1000.0 / (decay * m_samplerate)); + mutex.unlock(); +} + +float QAGC::fixedGain() const { + + return 20.0 * log10(m_gainFix); +} + +void QAGC::setFixedGain(float gain) { + + mutex.lock(); + m_gainFix = qPow(10.0, gain/20.0); + mutex.unlock(); +} + +inline float QAGC::Scale(float in_val, float scalevalue) { + + return in_val * scalevalue; +} diff --git a/Source/src/QtDSP/qtdsp_agc.h b/Source/src/QtDSP/qtdsp_agc.h new file mode 100644 index 0000000..425494f --- /dev/null +++ b/Source/src/QtDSP/qtdsp_agc.h @@ -0,0 +1,116 @@ +/** +* @file qtdsp_agc.h +* @brief AGC header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-14 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_AGC_H +#define _QTDSP_AGC_H + +#include "qtdsp_qComplex.h" +#include "../cusdr_settings.h" + +//#include +//#include + +const int FASTLEAD = 72; + + +class QAGC : public QObject { + + Q_OBJECT + +public: + QAGC(QObject *parent = 0, int size = 0); + ~QAGC(); + + //void ProcessAGC(CPX* in, CPX* out, int size); + void ProcessAGC(const CPX &in, CPX &out, int size); + + //AGCMode Mode() const; + + float gain() const; + float fastGain() const; + float hangTime() const; + float gainTop() const; + float gainBottom() const; + float attack() const; + float decay() const; + float fixedGain() const; + + void setGain(float gain); + void setHangTime(float time); + void setGainTop(float gain); + void setGainBottom(float gain); + void setAttack(float attack); + void setDecay(float decay); + void setFixedGain(float gain); + +public slots: + void setMode(AGCMode mode); + +private: + Settings *set; + + QMutex mutex; + + //TReceiver m_rxData; + AGCMode m_agcMode; + + CPX G; + + int m_size; + + qint16 m_mask; + qint16 m_index; + qint16 m_sndex; + qint16 m_hangIndex; + qint16 m_fastIndex; + qint16 m_fastHang; + + float m_samplerate; + float m_gainTop; + float m_gainNow; + float m_gainFastNow; + float m_gainBottom; + float m_gainLimit; + float m_gainFix; + float m_attack; + float m_oneMAttack; + float m_decay; + float m_oneMDecay; + float m_slope; + float m_fastAttack; + float m_oneMFastAttack; + float m_fastDecay; + float m_oneMFastDecay; + float m_hangTime; + float m_hangThresh; + float m_fastHangTime; + + float Scale(float in_val, float scalevalue); +}; + +#endif // _QTDSP_AGC_H diff --git a/Source/src/QtDSP/qtdsp_demodulation.cpp b/Source/src/QtDSP/qtdsp_demodulation.cpp new file mode 100644 index 0000000..c7983ea --- /dev/null +++ b/Source/src/QtDSP/qtdsp_demodulation.cpp @@ -0,0 +1,274 @@ +/** +* @file qtdsp_demodulation.cpp +* @brief Demodulation class for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-20 +*/ + +/* + * Copyright (C) 2007, 2008 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qtdsp_demodulation.h" + + +Demodulation::Demodulation(QObject *parent, int size) + : QObject(parent) + , set(Settings::instance()) + , m_mode((DSPMode) LSB) + , m_size(size) + , m_samplerate((float)set->getSampleRate()) + , m_phase(0.0f) + , m_delay_real(0.0f) + , m_delay_imag(1.0f) + , m_alpha(0.3f * 500.0f * TWOPI / m_samplerate) + , m_beta(m_alpha * m_alpha * 0.25f) + , m_lockcurrent(0.5f) + , m_lockprevious(1.0f) + , m_dc(0.0f) + , m_afc(0.0f) + , m_cvt(0.45f * m_samplerate / (ONEPI * 500.0)) + , m_smooth(0.0f) + , m_twopi_over_sr(TWOPI/m_samplerate) + , m_cvt_sr_mult((0.45f * m_samplerate) / ONEPI) + , m_pll_lo_limit(-1000.0f) + , m_pll_hi_limit(1000.0f) + , m_pll_bandwidth(500.0f) + , m_pll_frequency(0.0f) +{ + setDemodMode((DSPMode) LSB); + + delay0.re = 0.0f; + delay0.im = 0.0f; + tmp0.re = 0.0f; + tmp0.im = 0.0f; +} + +Demodulation::~Demodulation() { + +} + +void Demodulation::ProcessBlock(CPX &in, CPX &out, int bsize) { + + Q_UNUSED(bsize) + + switch(m_mode) { + + case (DSPMode) AM: + + DoMagnitude(in, out); + break; + + case (DSPMode) SAM: + + DoSAM(in, out); + break; + + case (DSPMode)FMN: + + DoFMN(in, out); + break; + + //case (DSPMode) FMW: + + //DoFMN(in, out); + //break; + + default: + + memcpy(out.data(), in.data(), sizeof(cpx) * m_size); + break; + } +} + +inline void Demodulation::DoMagnitude(CPX &in, CPX &out) { + + for (int i = 0; i < m_size; i++) { + + float magn = SqrMagCPX(in.at(i)); + + out[i].re = magn; + out[i].im = magn; + } +} + +void Demodulation::DoSAM(CPX &in, CPX &out ) { + + float difference; + + for (int i = 0; i < m_size; i++) { + + tmp0.re = qCos(m_phase); + tmp0.im = qSin(m_phase); + + delay0.re = tmp0.re * in.at(i).re + tmp0.im * in.at(i).im; + delay0.im = -tmp0.im * in.at(i).re + tmp0.re * in.at(i).im; + + if ((delay0.im) == 0.0 && (delay0.re == 0.0)) { + + delay0.re = 0.000000000001; + } + + difference = sqrt(in.at(i).re * in.at(i).re + in.at(i).im * in.at(i).im) * (qAtan2(delay0.im, delay0.re)); + + m_pll_frequency += m_beta * difference; + + if (m_pll_frequency < m_pll_lo_limit) + m_pll_frequency = m_pll_lo_limit; + + if (m_pll_frequency > m_pll_hi_limit) + m_pll_frequency = m_pll_hi_limit; + + m_phase += m_pll_frequency + m_alpha * difference; + + while (m_phase >= TWOPI) + m_phase -= TWOPI; + + while (m_phase < 0) + m_phase += TWOPI; + + m_lockcurrent = 0.999 * m_lockcurrent + 0.001 * qAbs(delay0.re); + m_lockprevious = m_lockcurrent; + m_dc = (0.999 * m_dc) + (0.001 * delay0.re); + + out[i].re = delay0.re - m_dc; + out[i].im = out.at(i).re; + } +} + +void Demodulation::DoFMN(CPX &in, CPX &out ) { + + float difference; + + for (int i = 0; i < m_size; i++) { + + tmp0.re = qCos(m_phase); + tmp0.im = qSin(m_phase); + + delay0.re = tmp0.re * in.at(i).re + tmp0.im * in.at(i).im; + delay0.im = -tmp0.im * in.at(i).re + tmp0.re * in.at(i).im; + + if ((delay0.im) == 0.0 && (delay0.re == 0.0)) { + + delay0.re = 0.000000000001; + } + difference = qAtan2(delay0.im, delay0.re); + + m_pll_frequency += m_beta * difference; + + if (m_pll_frequency < m_pll_lo_limit) + m_pll_frequency = m_pll_lo_limit; + if (m_pll_frequency > m_pll_hi_limit) + m_pll_frequency = m_pll_hi_limit; + + m_phase += m_pll_frequency + m_alpha * difference; + + while (m_phase >= TWOPI) + m_phase -= TWOPI; + while (m_phase < 0) + m_phase += TWOPI; + + m_afc = 0.99 * m_afc + 0.01 * m_pll_frequency; + out[i].re = (m_pll_frequency - m_afc) * m_cvt; + out[i].im = out.at(i).re; + } +} + +void Demodulation::DoFMW(CPX &in, CPX &out ) { + + memcpy(out.data(), in.data(), sizeof(CPX) * m_size); +} + +void Demodulation::setDemodMode(DSPMode mode) { + + m_mode = mode; + switch(m_mode) { + + case AM: // AM + break; + + case SAM: // SAM + + m_pll_bandwidth = 500.0; + m_alpha = 0.3 * m_pll_bandwidth * m_twopi_over_sr; + m_beta = m_alpha * m_alpha * 0.25; + m_cvt = m_cvt_sr_mult / m_pll_bandwidth; + break; + + case FMN: // FMN + + m_pll_bandwidth = 10000.0; + m_alpha = 0.3 * m_pll_bandwidth * m_twopi_over_sr; + m_beta = m_alpha * m_alpha * 0.25; + m_cvt = m_cvt_sr_mult / m_pll_bandwidth; + break; + +// case dmFMW: // FMW +// m_pll_bandwidth = 90000.0; +// m_alpha = 0.3 * m_pll_bandwidth * m_twopi_over_sr; +// m_beta = m_alpha * m_alpha * 0.25; +// m_cvt = m_cvt_sr_mult / m_pll_bandwidth; +// break; + + case CWL: + break; + + case CWU: + break; + + case DIGL: + break; + + case DIGU: + break; + + case DSB: + break; + + case LSB: + break; + + case USB: + break; + + default: + //std::cout << "Unknown mode:" << m_mode << std::endl; + break; + } +} + +DSPMode Demodulation::demodMode() const { + + return m_mode; +} + +void Demodulation::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_samplerate = value; + + m_alpha = 0.3f * 500.0f * TWOPI / m_samplerate; + m_beta = m_alpha * m_alpha * 0.25f; + + m_cvt = 0.45f * m_samplerate / (ONEPI * 500.0f); + m_twopi_over_sr = TWOPI / m_samplerate; + m_cvt_sr_mult = (0.45f * m_samplerate) / ONEPI; +} diff --git a/Source/src/QtDSP/qtdsp_demodulation.h b/Source/src/QtDSP/qtdsp_demodulation.h new file mode 100644 index 0000000..10a301b --- /dev/null +++ b/Source/src/QtDSP/qtdsp_demodulation.h @@ -0,0 +1,90 @@ +/** +* @file qtdsp_demodulation.h +* @brief Demodulation header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-20 +*/ + +/* + * Copyright (C) 2007, 2008 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_DEMODULATION_H +#define _QTDSP_DEMODULATION_H + +#include +#include "qtdsp_qComplex.h" +#include "../cusdr_settings.h" + + +class Demodulation : public QObject { + + Q_OBJECT + +public: + Demodulation(QObject *parent = 0, int size = 0); + ~Demodulation(); + + void ProcessBlock(CPX &in, CPX &out, int bsize); + + DSPMode demodMode() const; + +public slots: + void setDemodMode(DSPMode mode); + void setSampleRate(QObject *sender, int value); + +private: + Settings *set; + + cpx tmp0; + cpx delay0; + + DSPMode m_mode; + + int m_size; + + float m_samplerate; + float m_phase; + float m_delay_real; + float m_delay_imag; + float m_alpha; + float m_beta; + float m_lockcurrent; + float m_lockprevious; + float m_dc; + float m_afc; + float m_cvt; + float m_smooth; + float m_twopi_over_sr; + float m_cvt_sr_mult; + float m_pll_lo_limit; + float m_pll_hi_limit; + float m_pll_bandwidth; + float m_pll_frequency; + + + void DoMagnitude(CPX &in, CPX &out); + void DoSAM(CPX &in, CPX &out); + void DoFMN(CPX &in, CPX &out); + void DoFMW(CPX &in, CPX &out); +}; + +#endif // _QTDSP_DEMODULATION_H + diff --git a/Source/src/QtDSP/qtdsp_dspEngine.cpp b/Source/src/QtDSP/qtdsp_dspEngine.cpp new file mode 100644 index 0000000..65d89c4 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_dspEngine.cpp @@ -0,0 +1,392 @@ +/** +* @file qtdsp_dspEngine.cpp +* @brief QtDSP DSP engine class +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-04-07 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * The ProcessFrequencyShift method is adpated from cuteSDR by (C) Moe Wheatley, AE4JY. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#define LOG_DSP_ENGINE + +// use: DSP_ENGINE_DEBUG << "debug message"; + +#include "qtdsp_dspEngine.h" + + +QDSPEngine::QDSPEngine(QObject *parent, int rx, int size) + : QObject(parent) + , set(Settings::instance()) + , m_qtdspOn(false) + , m_rx(rx) + , m_size(size) + , m_samplerate(set->getSampleRate()) + , m_fftMultiplcator(1) + , m_volume(0.0f) +{ + qRegisterMetaType >(); + qRegisterMetaType(); + + fft = new QFFT(m_size); + filter = new QFilter(this, m_size, 2, 12);//8); + wpagc = new QWPAGC(this, m_size); + spectrum = new PowerSpectrum(this, m_size*2); + + QString str = "Initializing DSP engine for rx %1: 8k FFT ...please wait"; + set->setSystemMessage(str.arg(m_rx), 0); + + if (m_rx == 0) { + + spectrum2 = new PowerSpectrum(this, m_size*4); + + str = "Initializing DSP engine for rx %1: 16k FFT ...please wait"; + set->setSystemMessage(str.arg(m_rx), 0); + spectrum4 = new PowerSpectrum(this, m_size*8); + + str = "Initializing DSP engine for rx %1: 32k FFT ...please wait"; + set->setSystemMessage(str.arg(m_rx), 0); + spectrum8 = new PowerSpectrum(this, m_size*16); + } + + m_spectrumSize = m_size*4; + + signalmeter = new SignalMeter(this, m_size); + demod = new Demodulation(this, m_size); + + + m_rxData = set->getReceiverDataList().at(rx); + m_agcMode = m_rxData.agcMode; + + wpagc->setReceiver(m_rx); + + InitCPX(tmp1CPX, m_size, 0.0f); + InitCPX(tmp2CPX, m_size, 0.0f); + + osc1cpx.re = 1.0f; + osc1cpx.im = 0.0f; + + m_NcoInc = 0.0; + m_NcoTime = 0.0; + m_NcoFreq = 0.0; + m_CWoffset = 0.0; + + //DSP_ENGINE_DEBUG << "set NCO to " << m_rxData.vfoFrequency - m_rxData.ctrFrequency; + setNCOFrequency(m_rx, m_rxData.vfoFrequency - m_rxData.ctrFrequency); + + DSP_ENGINE_DEBUG << "init DSPEngine with size: " << m_size; + SleeperThread::msleep(100); + + setupConnections(); +} + +QDSPEngine::~QDSPEngine() { + + tmp1CPX.clear(); + tmp2CPX.clear(); + + //if (agc) + // delete agc; + + if (fft) + delete fft; + + if (filter) + delete filter; + + if (wpagc) + delete wpagc; + + if (spectrum) + delete spectrum; + + if (signalmeter) + delete signalmeter; + + if (demod) + delete demod; +} + +void QDSPEngine::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(ncoFrequencyChanged(int, long)), + this, + SLOT(setNCOFrequency(int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleSizeChanged(int, int)), + this, + SLOT(setSampleSize(int, int))); + + CHECKED_CONNECT( + wpagc, + SIGNAL(agcMaximumGainChanged(qreal)), + this, + SLOT(setAGCMaximumGain(qreal))); + + CHECKED_CONNECT( + wpagc, + SIGNAL(agcHangThresholdChanged(qreal)), + this, + SLOT(setAGCHangThreshold(qreal))); + +// CHECKED_CONNECT( +// wpagc, +// SIGNAL(hangLeveldBLineChanged(qreal)), +// this, +// SLOT(setAGCHangLeveldBLine(qreal))); +// +// CHECKED_CONNECT( +// wpagc, +// SIGNAL(minimumVoltageChanged(QObject *, int, qreal)), +// this, +// SLOT(setAGCThresholdLine(QObject *, int, qreal))); + + CHECKED_CONNECT( + wpagc, + SIGNAL(displayValues(QObject *, int, qreal, qreal)), + this, + SLOT(setAGCLineValues(QObject *, int, qreal, qreal))); +} + +void QDSPEngine::processDSP(CPX &in, CPX &out, int size) { + + m_mutex.lock(); + + switch (m_fftMultiplcator) { + + case 1: + spectrum->ProcessSpectrum(in, size*2, 1); + break; + + case 2: + spectrum2->ProcessSpectrum(in, size*4, 3); + break; + + case 4: + spectrum4->ProcessSpectrum(in, size*8, 7); + break; + + case 8: + spectrum8->ProcessSpectrum(in, size*16, 15); + break; + } + + if (m_NcoFreq != 0) + ProcessFrequencyShift(in, in, size); + + filter->ProcessFilter(in, tmp1CPX, size); + signalmeter->ProcessBlock(tmp1CPX, size); + wpagc->ProcessAGC(tmp1CPX, tmp2CPX, size); + demod->ProcessBlock(tmp2CPX, out, size); + + //memcpy(out.data(), in.data(), size * sizeof(cpx)); + //out = in; + + for (int i = 0; i < size; i++) { + + out[i] = ScaleCPX(out.at(i), m_volume); + } + m_mutex.unlock(); +} + +int QDSPEngine::getSpectrum(qVectorFloat &buffer, int mult) { + + if (m_rx == 0) { + + m_fftMultiplcator = mult; + switch (m_fftMultiplcator) { + + case 1: + return spectrum->spectrumResult(buffer, 0); + break; + + case 2: + return spectrum2->spectrumResult(buffer, 2048); + break; + + case 4: + return spectrum4->spectrumResult(buffer, 6144); + break; + + case 8: + return spectrum8->spectrumResult(buffer, 14336); + break; + + default: + return spectrum->spectrumResult(buffer, 0); + break; + } + } + else { + + return spectrum->spectrumResult(buffer, 0); + } +} + +float QDSPEngine::getSMeterInstValue() { + + return signalmeter->getInstFValue(); +} + +void QDSPEngine::setVolume(float value) { + + if (m_volume == value) return; + + m_volume = value; +} + +void QDSPEngine::setQtDSPStatus(bool value) { + + m_qtdspOn = value; +} + +void QDSPEngine::setDSPMode(DSPMode mode) { + + demod->setDemodMode(mode); +} + +void QDSPEngine::setAGCMode(AGCMode mode) { + + wpagc->setMode(mode); +} + +void QDSPEngine::setAGCMaximumGain(qreal value) { + + qreal maxGain = 20.0 * log10(value); + set->setAGCMaximumGain_dB(this, m_rx, maxGain); +} + +void QDSPEngine::setAGCHangThreshold(qreal value) { + + set->setAGCHangThresholdSlider(this, m_rx, value); +} + +void QDSPEngine::setAGCLineValues(QObject *sender, int rx, qreal thresh, qreal hang) { + + if (m_rx != rx) return; + + qreal noiseOffset = 10.0 * log10(qAbs(filter->filterHi() - filter->filterLo()) * 2 * m_size / m_samplerate); + qreal threshold = 20.0 * log10(thresh) - noiseOffset + AGCOFFSET; + + set->setAGCLineLevels(sender, m_rx, threshold, hang + AGCOFFSET); +} + +void QDSPEngine::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (m_samplerate == value) return; + + m_mutex.lock(); + switch (value) { + + case 48000: + m_samplerate = value; + break; + + case 96000: + m_samplerate = value; + break; + + case 192000: + m_samplerate = value; + break; + + case 384000: + m_samplerate = value; + break; + + default: + DSP_ENGINE_DEBUG << "invalid sample rate (possible values are: 48, 96, 192, or 384 kHz)!\n"; + break; + } + + //DSP_ENGINE_DEBUG << "set sample rate to " << m_samplerate; + //setNCOFrequency(m_rx, m_rxData.vfoFrequency - m_rxData.ctrFrequency); + m_NcoInc = TWOPI * m_NcoFreq/m_samplerate; + m_OscCos = qCos(m_NcoInc); + m_OscSin = qSin(m_NcoInc); + + filter->setSampleRate(this, m_samplerate); + demod->setSampleRate(this, m_samplerate); + wpagc->setSampleRate(this, m_samplerate); + + m_mutex.unlock(); + +} + +void QDSPEngine::setNCOFrequency(int rx, long ncoFreq) { + + if (m_rx != rx) return; + + qreal tmp = ncoFreq + m_CWoffset; + + m_NcoFreq = tmp; + m_NcoInc = TWOPI * m_NcoFreq/m_samplerate; + m_OscCos = qCos(m_NcoInc); + m_OscSin = qSin(m_NcoInc); + + //DSP_ENGINE_DEBUG << "NCO: " << m_NcoFreq; +} + +void QDSPEngine::setSampleSize(int rx, int size) { + + Q_UNUSED(rx) + + if (m_rx == 0) { + + m_mutex.lock(); + m_spectrumSize = size; + m_mutex.unlock(); + } +} + +void QDSPEngine::ProcessFrequencyShift(CPX &in, CPX &out, int size) { + + cpx tmp; + CPX Osc; + + Osc.resize(size); + + for (int i = 0; i < size; i++) { + + tmp = in.at(i); + + qreal OscGn; + Osc[i].re = osc1cpx.re * m_OscCos - osc1cpx.im * m_OscSin; + Osc[i].im = osc1cpx.im * m_OscCos + osc1cpx.re * m_OscSin; + + OscGn = 1.95 - (osc1cpx.re * osc1cpx.re + osc1cpx.im * osc1cpx.im); + + osc1cpx.re = OscGn * Osc.at(i).re; + osc1cpx.im = OscGn * Osc.at(i).im; + + //Cpx multiply by shift frequency + out[i].re = ((tmp.re * Osc.at(i).re) - (tmp.im * Osc.at(i).im)); + out[i].im = ((tmp.re * Osc.at(i).im) + (tmp.im * Osc.at(i).re)); + } +} + diff --git a/Source/src/QtDSP/qtdsp_dspEngine.h b/Source/src/QtDSP/qtdsp_dspEngine.h new file mode 100644 index 0000000..c6fc4ac --- /dev/null +++ b/Source/src/QtDSP/qtdsp_dspEngine.h @@ -0,0 +1,133 @@ +/** +* @file qtdsp_dspEngine.h +* @brief header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-04-07 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_DSP_ENGINE_H +#define _QTDSP_DSP_ENGINE_H + +#define AGCOFFSET -18.0//-63.0 + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include + +#include "../cusdr_settings.h" +#include "qtdsp_qComplex.h" +#include "qtdsp_filter.h" +#include "qtdsp_fft.h" +#include "qtdsp_wpagc.h" +#include "qtdsp_powerSpectrum.h" +#include "qtdsp_signalMeter.h" +#include "qtdsp_demodulation.h" + + +#ifdef LOG_DSP_ENGINE +# define DSP_ENGINE_DEBUG qDebug().nospace() << "DSPEngine::\t" +#else +# define DSP_ENGINE_DEBUG nullDebug() +#endif + + +class QDSPEngine : public QObject { + + Q_OBJECT + +public: + QDSPEngine(QObject* parent = 0, int rx = 0, int size = 0); + ~QDSPEngine(); + + QFFT* fft; + QFilter* filter; + QWPAGC* wpagc; + PowerSpectrum* spectrum; + PowerSpectrum* spectrum2; + PowerSpectrum* spectrum4; + PowerSpectrum* spectrum8; + SignalMeter* signalmeter; + Demodulation* demod; + + void processDSP(CPX &in, CPX &out, int size); + + int getSpectrum(qVectorFloat &buffer, int mult); + float getSMeterInstValue(); + +public slots: + bool getQtDSPStatus() { return m_qtdspOn; } + + void setNCOFrequency(int rx, long value); + void setSampleRate(QObject *sender, int value); + void setSampleSize(int rx, int size); + void setQtDSPStatus(bool value); + void setVolume(float value); + void setDSPMode(DSPMode mode); + void setAGCMode(AGCMode mode); + +private: + Settings* set; + TReceiver m_rxData; + AGCMode m_agcMode; + + CPX tmp1CPX; + CPX tmp2CPX; + cpx osc1cpx; + + QMutex m_mutex; + + bool m_qtdspOn; + + int m_rx; + int m_size; + int m_spectrumSize; + int m_samplerate; + int m_fftMultiplcator; + + float m_volume; + qreal m_NcoFreq; + qreal m_NcoInc; + qreal m_NcoTime; + qreal m_CWoffset; + qreal m_OscCos; + qreal m_OscSin; + //qreal m_calOffset; + + void ProcessFrequencyShift(CPX &in, CPX &out, int size); + void setupConnections(); + +private slots: + void setAGCMaximumGain(qreal); + void setAGCHangThreshold(qreal); + //void setAGCHangLeveldBLine(qreal value); + //void setAGCThresholdLine(QObject *sender, int rx, qreal value); + void setAGCLineValues(QObject *sender, int rx, qreal thresh, qreal hang); +}; + +#endif // _QTDSP_DSP_ENGINE_H diff --git a/Source/src/QtDSP/qtdsp_dualModeAverager.cpp b/Source/src/QtDSP/qtdsp_dualModeAverager.cpp new file mode 100644 index 0000000..4f01f04 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_dualModeAverager.cpp @@ -0,0 +1,116 @@ +/** +* @file qtdsp_dualModeAverager.cpp +* @brief Dual mode averager class for QtDSP; + Dual-Mode Averaging implmemented following "Understanding Digital Signal Processing" by Richard G. Lyons, 3rd ed., p.791 +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-07-12 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qtdsp_dualModeAverager.h" + +DualModeAverager::DualModeAverager(int rx, int size) + : QObject() + , set(Settings::instance()) + , m_receiver(rx) + , m_size(size) + , m_length(set->getSpectrumAveragingCnt(m_receiver)) +{ + m_tmp.resize(m_size); + m_tmp.fill(-20.0); + + cnt = 0; + k = 1.0f/m_length; + + CHECKED_CONNECT( + set, + SIGNAL(spectrumAveragingCntChanged(QObject*, int, int)), + this, + SLOT(setAveragingLength(QObject*, int, int))); + + /*CHECKED_CONNECT( + set, + SIGNAL(widebandAveragingCntChanged(QObject*, int)), + this, + SLOT(setWidebandAveragingLength(QObject*, int)));*/ +} + +DualModeAverager::~DualModeAverager() { + + m_tmp.clear(); +} + +void DualModeAverager::ProcessDBAverager(qVectorFloat &in, qVectorFloat &out) { + + mutex.lock(); + if (cnt < m_length) { + + for (int i = 0; i < m_size; i++) + out[i] = m_tmp.at(i) + k * in.at(i); + + cnt++; + } + else { + + for (int i = 0; i < m_size; i++) + out[i] = m_tmp.at(i) + k * (in.at(i) - m_tmp.at(i)); + } + mutex.unlock(); + + m_tmp = out; +} + +void DualModeAverager::setAveragingLength(QObject* sender, int rx, int value) { + + Q_UNUSED (sender) + + if (m_receiver != rx) return; + + mutex.lock(); + m_length = value; + k = 1.0f/m_length; + cnt = 0; + + m_tmp.fill(0.0f); + mutex.unlock(); +} + +//void DualModeAverager::setWidebandAveragingLength(QObject* sender, int value) { +// +// Q_UNUSED (sender) +// +// mutex.lock(); +// m_length = value; +// k = 1.0f/m_length; +// cnt = 0; +// +// m_tmp.fill(0.0f); +// mutex.unlock(); +//} + +void DualModeAverager::clearBuffer() { + + m_tmp.clear(); + m_tmp.resize(m_size); + m_tmp.fill(-20.0); + +} diff --git a/Source/src/QtDSP/qtdsp_dualModeAverager.h b/Source/src/QtDSP/qtdsp_dualModeAverager.h new file mode 100644 index 0000000..b463e66 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_dualModeAverager.h @@ -0,0 +1,64 @@ +/** +* @file qtdsp_dualModeAverager.h +* @brief Dual mode averager header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-07-12 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_DUAL_MODE_AVERAGER_H +#define _QTDSP_DUAL_MODE_AVERAGER_H + +#include + +#include "../cusdr_settings.h" + +class DualModeAverager : public QObject { + + Q_OBJECT + +public: + DualModeAverager(int rx = 0, int size = 0); + ~DualModeAverager(); + + void ProcessDBAverager(qVectorFloat &in, qVectorFloat &out); + void clearBuffer(); + //void setAveragingLength(int value); + +private: + Settings* set; + QMutex mutex; + qVectorFloat m_tmp; + + int m_receiver; + int m_size; + int m_length; + int cnt; + + float k; + +private slots: + void setAveragingLength(QObject* sender, int rx, int value); + //void setWidebandAveragingLength(QObject* sender, int value); +}; + +#endif // _QTDSP_DUAL_MODE_AVERAGER_H diff --git a/Source/src/QtDSP/qtdsp_fft.cpp b/Source/src/QtDSP/qtdsp_fft.cpp new file mode 100644 index 0000000..afdf060 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_fft.cpp @@ -0,0 +1,90 @@ +/** +* @file qtdsp_fft.cpp +* @brief QFFT FFTW class for QtDSP +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qtdsp_fft.h" +#include + +#include + +QFFT::QFFT(int size) + : QObject() + , m_size(size) + , half_sz(size/2) +{ + cpxbuf = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * m_size); + plan_fwd = fftwf_plan_dft_1d(m_size , cpxbuf, cpxbuf, FFTW_FORWARD, FFTW_MEASURE); + plan_rev = fftwf_plan_dft_1d(m_size , cpxbuf, cpxbuf, FFTW_BACKWARD, FFTW_MEASURE); + + memset(cpxbuf, 0, m_size * sizeof(cpxbuf)); + + InitCPX(buf, m_size, 0.0f); +} + +QFFT::~QFFT() { + + fftwf_destroy_plan(plan_fwd); + fftwf_destroy_plan(plan_rev); + + if (cpxbuf) + fftwf_free(cpxbuf); + + buf.clear(); +} + +void QFFT::DoFFTWForward(CPX &in, CPX &out, int size) { + memcpy(cpxbuf, in.data(), sizeof(cpx) * size); + fftwf_execute(plan_fwd); + memcpy(out.data(), cpxbuf, sizeof(cpx) * size); +} + + +void QFFT::DoFFTWInverse(CPX &in, CPX &out, int size) { + + memcpy(cpxbuf, in.data(), sizeof(cpx) * size); + fftwf_execute(plan_rev); + memcpy(out.data(), cpxbuf, sizeof(cpx) * size); +} + + +void QFFT::DoFFTWMagnForward(CPX &in, int size, float baseline, float correction, float *fbr) { + + memcpy(cpxbuf, in.data(), sizeof(cpx) * size); + + fftwf_execute(plan_fwd); + + for (int i = 0, j = size-1; i < size; i++, j--) { + + *(buf.data()+j) = *(cpx *)(cpxbuf+i); + } + + for (int i = 0, j = half_sz; i < half_sz; i++, j++) { + + *(fbr+i) = 10.0 * log10(MagCPX(*(buf.data()+j)) + baseline) + correction; + *(fbr+j) = 10.0 * log10(MagCPX(*(buf.data()+i)) + baseline) + correction; + } +} diff --git a/Source/src/QtDSP/qtdsp_fft.cpp.orig b/Source/src/QtDSP/qtdsp_fft.cpp.orig new file mode 100644 index 0000000..7924358 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_fft.cpp.orig @@ -0,0 +1,91 @@ +/** +* @file qtdsp_fft.cpp +* @brief QFFT FFTW class for QtDSP +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qtdsp_fft.h" +#include + +#include + +QFFT::QFFT(int size) + : QObject() + , m_size(size) + , half_sz(size/2) +{ + cpxbuf = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * m_size); + plan_fwd = fftwf_plan_dft_1d(m_size , cpxbuf, cpxbuf, FFTW_FORWARD, FFTW_MEASURE); + plan_rev = fftwf_plan_dft_1d(m_size , cpxbuf, cpxbuf, FFTW_BACKWARD, FFTW_MEASURE); + + memset(cpxbuf, 0, m_size * sizeof(cpxbuf)); + + InitCPX(buf, m_size, 0.0f); +} + +QFFT::~QFFT() { + + fftwf_destroy_plan(plan_fwd); + fftwf_destroy_plan(plan_rev); + + if (cpxbuf) + fftwf_free(cpxbuf); + + buf.clear(); +} + +void QFFT::DoFFTWForward(CPX &in, CPX &out, int size) { + + memcpy(cpxbuf, in.data(), sizeof(cpx) * size); + fftwf_execute(plan_fwd); + memcpy(out.data(), cpxbuf, sizeof(cpx) * size); +} + + +void QFFT::DoFFTWInverse(CPX &in, CPX &out, int size) { + + memcpy(cpxbuf, in.data(), sizeof(cpx) * size); + fftwf_execute(plan_rev); + memcpy(out.data(), cpxbuf, sizeof(cpx) * size); +} + + +void QFFT::DoFFTWMagnForward(CPX &in, int size, float baseline, float correction, float *fbr) { + + memcpy(cpxbuf, in.data(), sizeof(cpx) * size); + + fftwf_execute(plan_fwd); + + for (int i = 0, j = size-1; i < size; i++, j--) { + + *(buf.data()+j) = *(cpx *)(cpxbuf+i); + } + + for (int i = 0, j = half_sz; i < half_sz; i++, j++) { + + *(fbr+i) = 10.0 * log10(MagCPX(*(buf.data()+j)) + baseline) + correction; + *(fbr+j) = 10.0 * log10(MagCPX(*(buf.data()+i)) + baseline) + correction; + } +} diff --git a/Source/src/QtDSP/qtdsp_fft.h b/Source/src/QtDSP/qtdsp_fft.h new file mode 100644 index 0000000..99c883f --- /dev/null +++ b/Source/src/QtDSP/qtdsp_fft.h @@ -0,0 +1,64 @@ +/** +* @file qtdsp_fft.h +* @brief QFFT header FFTW for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_FFT_H +#define _QTDSP_FFT_H + +#include + +#include +#include "fftw3.h" +#include "qtdsp_qComplex.h" + + +class QFFT : public QObject { + + Q_OBJECT + +public: + QFFT(int size = 0); + ~QFFT(); + +public slots: + void DoFFTWForward(CPX &in, CPX &out, int size); + void DoFFTWInverse(CPX &in, CPX &out, int size); + void DoFFTWMagnForward(CPX &in, int size, float baseline, float correction, float* fbr); + +private: + fftwf_complex *cpxbuf; + + fftwf_plan plan_fwd; + fftwf_plan plan_rev; + + CPX buf; + + int m_size; + int half_sz; +}; + +#endif // _QTDSP_FFT_H diff --git a/Source/src/QtDSP/qtdsp_fft.h.orig b/Source/src/QtDSP/qtdsp_fft.h.orig new file mode 100644 index 0000000..33dc713 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_fft.h.orig @@ -0,0 +1,64 @@ +/** +* @file qtdsp_fft.h +* @brief QFFT header FFTW for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_FFT_H +#define _QTDSP_FFT_H + +#include + +#include +#include +#include "qtdsp_qComplex.h" + + +class QFFT : public QObject { + + Q_OBJECT + +public: + QFFT(int size = 0); + ~QFFT(); + +public slots: + void DoFFTWForward(CPX &in, CPX &out, int size); + void DoFFTWInverse(CPX &in, CPX &out, int size); + void DoFFTWMagnForward(CPX &in, int size, float baseline, float correction, float* fbr); + +private: + fftwf_complex *cpxbuf; + + fftwf_plan plan_fwd; + fftwf_plan plan_rev; + + CPX buf; + + int m_size; + int half_sz; +}; + +#endif // _QTDSP_FFT_H diff --git a/Source/src/QtDSP/qtdsp_filter.cpp b/Source/src/QtDSP/qtdsp_filter.cpp new file mode 100644 index 0000000..6242645 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_filter.cpp @@ -0,0 +1,682 @@ +/** +* @file qtdsp_filter.cpp +* @brief Filter class for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#include "qtdsp_filter.h" + +//#include + +#define LOG_QTDSP_FILTER + +// use: FILTER_DEBUG + +#ifndef NULL +#define NULL 0 +#endif + + +QFilter::QFilter(QObject *parent, int size, const int ftype, const int wtype) + : QObject(parent) + , set(Settings::instance()) + , m_streamMode(true) + , m_size(size) + , m_ftype(ftype) + , m_wtype(wtype) + , m_samplerate(set->getSampleRate()) + , m_filter_lo(-3050.0f) + , m_filter_hi(-150.0f) +{ + InitCPX(ovlp, m_size, 0.0f); + InitCPX(tmp, m_size, 0.0f); + InitCPX(res, m_size, 0.0f); + InitCPX(filter, m_size * 2, 0.0f); + InitCPX(tmp0, m_size * 2, 0.0f); + InitCPX(tmp1, m_size * 2, 0.0f); + InitCPX(tmp2, m_size * 2, 0.0f); + InitCPX(tmpfilt0, m_size * 2, 0.0f); + InitCPX(tmpfilt1, m_size * 2, 0.0f); + + ovlpfft = new QFFT(m_size * 2); + filtfft = new QFFT(m_size * 2); + + MakeFilter(m_filter_lo, m_filter_hi, m_ftype, m_wtype); +} + +QFilter::~QFilter() { + + if (ovlpfft) delete ovlpfft; + if (filtfft) delete filtfft; + + ovlp.clear(); + filter.clear(); + tmpfilt0.clear(); + tmpfilt1.clear(); + tmp.clear(); + tmp0.clear(); + tmp1.clear(); + +} + +void QFilter::DoConvolutionCPX() { + + mutex.lock(); + for (int i = 0; i < m_size * 2; i++) //convolution in frequency space here + { + tmp0[i].re = (filter.at(i).re * tmp1.at(i).re) - (filter.at(i).im * tmp1.at(i).im); + tmp0[i].im = (filter.at(i).re * tmp1.at(i).im) + (filter.at(i).im * tmp1.at(i).re); + } + mutex.unlock(); +} + +void QFilter::DoOverlapAddCPX() { + + //SSEAddCPX(tmp0, tmp1, ovlp, m_size); + for (int i = 0; i < m_size; i++) { + + //tmp0[i] = AddCPX(tmp1.at(i), ovlp.at(i)); + //ovlp[i] = tmp1.at(i + m_size); + res[i] = AddCPX(tmp2.at(i), ovlp.at(i)); + ovlp[i] = tmp2.at(i + m_size); + } +} + +void QFilter::ProcessFilter(CPX &in, CPX &out, int bsize) { + + Q_UNUSED (bsize) + + memcpy(tmp0.data(), in.data(), sizeof(cpx) * m_size); + ovlpfft->DoFFTWForward(tmp0, tmp1, m_size * 2); + DoConvolutionCPX(); + ovlpfft->DoFFTWInverse(tmp0, tmp1, m_size * 2); + + if (m_streamMode) { + + //Normalize(tmp1, tmp2, m_size * 2); + + // Overlap-Add + for (int i = 0; i < m_size; i++) { + + out[i] = AddCPX(tmp1.at(i), ovlp.at(i)); + ovlp[i] = tmp1.at(i + m_size); + } + //DoOverlapAddCPX(); + //Normalize(tmp0, out, m_size * 2); + //memcpy(out.data(), res.data(), sizeof(cpx) * m_size); + } + else { + + memcpy(out.data(), tmp1.data(), sizeof(cpx) * m_size); + } +} + +void QFilter::ProcessChirpFilter(CPX &in, CPX &out, int bsize) { + + Q_UNUSED(in) + Q_UNUSED(out) + Q_UNUSED(bsize) +} + +void QFilter::ProcessForwardFilter(CPX &in, CPX &out, int bsize) { + + Q_UNUSED (bsize) + + //memcpy(tmp0, in, sizeof(CPX) * m_size); + memcpy(tmp0.data(), in.data(), sizeof(cpx) * m_size); + ovlpfft->DoFFTWForward(tmp0, tmp1, m_size * 2); + + DoConvolutionCPX(); + //ovlpfft->DoFFTWInverse(tmp0, tmp1, m_size * 2); + + if (m_streamMode) { + + DoOverlapAddCPX(); + //memcpy(out, tmp0, sizeof(CPX) * m_size); + memcpy(out.data(), tmp0.data(), sizeof(cpx) * m_size); + } + else { + + //memcpy(out, tmp1, sizeof(CPX) * m_size); + memcpy(out.data(), tmp1.data(), sizeof(cpx) * m_size); + } +} + +int QFilter::ProcessAndDecimate(CPX &in, CPX &out, int bsize) { + + Q_UNUSED(in) + Q_UNUSED(bsize) + + //memset(tmp0, 0, sizeof(CPX) * m_size * 2); + //memset(tmp1, 0, sizeof(CPX) * m_size * 2); + //memcpy(tmp0, in, sizeof(CPX) * m_size); + tmp0.resize(m_size * 2); + tmp1.resize(m_size * 2); + tmp0.resize(m_size); + + ovlpfft->DoFFTWForward(tmp0, tmp1, m_size * 2); + DoConvolutionCPX(); + ovlpfft->DoFFTWInverse(tmp0, tmp1, m_size * 2); + + if (m_streamMode) { + + DoOverlapAddCPX(); + for (int i = 0, j = 0; i < m_size; i+=2, j++) { + + *(out.data()+j) = *(tmp0.data()+i); + } + } + else { + + for (int i = 0, j = 0; i < m_size; i+=2, j++) { + + *(out.data()+j) = *(tmp1.data()+i); + } + } + return m_size/2; +} + +void QFilter::Normalize(CPX &in, CPX &out, int size) { + + float norm = 1.0f/size; + for (int i = 0; i < size; i++) { + + out[i].re = in.at(i).re * norm; + out[i].im = in.at(i).im * norm; + } +} + +void QFilter::Decimate(CPX &in, CPX &out, int downrate) { + + int newsize = qRound((float) m_size/downrate); + + //memset(out, 0, newsize * sizeof(CPX)); + //memset(tmp, 0, m_size * sizeof(CPX)); + out.resize(newsize); + tmp.resize(m_size); + //memcpy(tmp, in, m_size * sizeof(CPX)); + memcpy(tmp.data(), in.data(), m_size * sizeof(cpx)); + + for (int j = 0; j < newsize; j++) { + for (int k = 0; k < downrate; k++) { + //for (int k = 0; k < downrate - 1; k++) { + + if (j * downrate + k < m_size) { + + out[j].re += tmp.at(j * downrate + k).re; + out[j].im += tmp.at(j * downrate + k).im; + } + } + } +} + +void QFilter::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_samplerate = (float)value; + //FILTER_DEBUG << "set sample rate to " << m_samplerate; + MakeFilter(m_filter_lo, m_filter_hi, m_ftype, m_wtype); +} + +void QFilter::setFilterLo(const float value) { + + if (value != m_filter_lo) { + + m_filter_lo = value; + MakeFilter(m_filter_lo, m_filter_hi, m_ftype, m_wtype); + } +} + +void QFilter::setFilterHi(const float value) { + + if (value != m_filter_hi) { + + m_filter_hi = value; + MakeFilter(m_filter_lo, m_filter_hi, m_ftype, m_wtype); + } +} + +void QFilter::setFilter(const float loval, const float hival) { + + if (m_filter_lo != loval || m_filter_hi != hival) { + + m_filter_lo = loval; + m_filter_hi = hival; + MakeFilter(m_filter_lo, m_filter_hi, m_ftype, m_wtype); + } +} + +float QFilter::filterLo() const { + + return m_filter_lo; +} + +float QFilter::filterHi() const { + + return m_filter_hi; +} + +int QFilter::isStreamMode() const { + + return m_streamMode; +} + +void QFilter::setStreamMode(int value) { + + m_streamMode = value; +} + +void QFilter::MakeFilter(const float lo, const float hi, const int ftype = 2, const int wtype = 12) { + + // size x 4 adjusts for no gain + //float one_over_norm = 1.0 / (m_size * 4); + float one_over_norm = 1.0 / (m_size * 2); + + filter.resize(m_size * 2); + tmpfilt0.resize(m_size * 2); + tmpfilt1.resize(m_size * 2); + + switch (ftype) { + + case 1: // lowpass + MakeFirLowpass( hi, + m_samplerate, + wtype, + tmpfilt0, + m_size); + break; + case 2: // bandpass + MakeFirBandpass(lo, + hi, + m_samplerate, + wtype, + tmpfilt0, + m_size); + break; + case 3: // loadable coeff + LoadFilter(tmpfilt0); + break; + case 4: // bandstop + MakeFirBandstop(lo, + hi, + m_samplerate, + tmpfilt0, + m_size); + break; + default: + MakeFirBandpass(lo, + hi, + m_samplerate, + wtype, + tmpfilt0, + m_size); + break; + } + + mutex.lock(); + //filtfft->DoFFTWForward(tmpfilt0, tmpfilt1, m_size * 2); + filtfft->DoFFTWForward(tmpfilt0, filter, m_size * 2); + + for (int i = 0; i < m_size * 2; i++) { + + filter[i].re *= one_over_norm; + filter[i].im *= one_over_norm; + } + mutex.unlock(); + + // Do compensation here instead of in inverse FFT + //filter_mutex.lock(); + //SSEScaleCPX(filter, tmpfilt1, one_over_norm, m_size * 2); + //filter_mutex.unlock(); +} + +//void QFilter::LoadFilter(CPX * taps) { +void QFilter::LoadFilter(CPX &taps) { + + if (FILTERCOEFFSIZE > m_size) return; + + for (int i = 0; i < FILTERCOEFFSIZE; i++) { + + taps[i].re = FILTERCOEFF[i]; + taps[i].im = FILTERCOEFF[i]; + } +} + +void QFilter::MakeFirLowpass(float cutoff, + float samplerate, + int wtype, + float *taps_re, + float *taps_im, + int length) +{ + + //float window[length]; + float * window = 0; + + float fc = cutoff / samplerate; + + if (fc > 0.5) + return; + + int midpoint = length >> 1; + + window = (float *)malloc(length * sizeof(float)); + + if (!window) return; + + MakeWindow(wtype, length, &window[0]); + + for (int i = 1; i <= length; i++) { + + int j = i - 1; + if (i != midpoint) { + + taps_re[j] = (sin(TWOPI * (i - midpoint) * fc) / (ONEPI * (i - midpoint))) * window[j]; + taps_im[j] = (cos(TWOPI * (i - midpoint) * fc) / (ONEPI * (i - midpoint))) * window[j]; + } + else { + + taps_re[midpoint - 1] = 2.0 * fc; + taps_im[midpoint - 1] = 2.0 * fc; + } + } + free(window); +} + +void QFilter::MakeFirLowpass(float cutoff, + float samplerate, + int wtype, + CPX &taps, + int length) +{ + + //float window[length]; + float * window = 0; + + float fc = cutoff / samplerate; + + if (fc > 0.5) + return; + + int midpoint = length >> 1; + + window = (float *)malloc(length * sizeof(float)); + + if (!window) + return; + + MakeWindow(wtype, length, &window[0]); + + for (int i = 1; i <= length; i++) { + + int j = i - 1; + if (i != midpoint) { + + taps[j].re = (sin(TWOPI * (i - midpoint) * fc) / (ONEPI * (i - midpoint))) * window[j]; + taps[j].im = (cos(TWOPI * (i - midpoint) * fc) / (ONEPI * (i - midpoint))) * window[j]; + } + else { + + taps[midpoint - 1].re = 2.0 * fc; + //taps[midpoint - 1].re = 2.0 * fc; + taps[midpoint - 1].im = 2.0 * fc; + } + } + free(window); +} + +void QFilter::MakeFirBandpass(float lo, + float hi, + float samplerate, + int wtype, + float * taps_re, + float * taps_im, + int length) +{ + + //float window[length]; + float * window = 0; + + float fl = lo / samplerate; + float fh = hi / samplerate; + float fc = (fh - fl) / 2.0; + float ff = (fl + fh) * ONEPI; + + int midpoint = length >> 1; + + window = (float *)malloc(length * sizeof(float)); + + if (!window) return; + + MakeWindow(wtype, length, &window[0]); + + for (int i = 1; i <= length; i++) { + + int j = i - 1; + int k = i - midpoint; + float temp = 0.0; + float phase = k * ff * -1; + if (i != midpoint) + temp = ((sin(TWOPI * k * fc) / (ONEPI * k))) * window[j]; + else + temp = 2.0 * fc; + temp *= 2.0; + taps_re[j] = temp * (cos(phase)); + taps_im[j] = temp * (sin(phase)); + } + free(window); +} + +void QFilter::MakeFirBandpass(float lo, + float hi, + float samplerate, + int wtype, + CPX &taps, + int length) +{ + + //float window[length]; + float *window = 0; + + float fl = lo / samplerate; + float fh = hi / samplerate; + float fc = (fh - fl) / 2.0f; + float ff = (fl + fh) * ONEPI; + + int midpoint = length >> 1; + + window = (float *)malloc(length * sizeof(float)); + + if (!window) return; + + MakeWindow(wtype, length, &window[0]); + + for (int i = 1; i <= length; i++) { + + int j = i - 1; + int k = i - midpoint; + float temp = 0.0; + float phase = k * ff * -1; + + if (i != midpoint) + temp = ((qSin(TWOPI * k * fc) / (ONEPI * k))) * window[j]; + else + temp = 2.0 * fc; + + temp *= 2.0; + + taps[j].re = temp * (qCos(phase)); + taps[j].im = temp * (qSin(phase)); + } + free(window); +} + +void QFilter::MakeFirBandstop(float lo, float hi, float samplerate, CPX &taps, int length) { + + //float window[length]; + float * window = 0; + + float fl = lo / samplerate; + float fh = hi / samplerate; + float fc = (fh - fl) / 2.0; + float ff = (fl + fh) * ONEPI; + + int midpoint = (length >> 1) | 1; + + window = (float *)malloc(length * sizeof(float)); + + if (!window) return; + + MakeWindow(12, length, &window[0]); + + for (int i = 1; i <= length; i++) { + + int j = i - 1; + int k = i - midpoint; + float temp = 0.0; + float phase = k * ff * -1.0; + + if (i != midpoint) { + + temp = ((sin(TWOPI * k * fc) / (ONEPI * k))) * window[j]; + taps[j].re = -2.0 * temp * (cos(phase)); + taps[j].im = -2.0 * temp * (sin(phase)); + } + else { + + temp = 4.0 * fc; + taps[midpoint - 1].re = 1.0 - taps[midpoint - 1].re; + taps[midpoint - 1].im = 0.0 - taps[midpoint - 1].im; + } + } + free(window); +} + +void QFilter::MakeWindow(int wtype, int size, float *window) { + + int i, j, midn, midp1, midm1; + float freq, rate, sr1, angle, expn, expsum, cx, two_pi; + + midn = size / 2; + midp1 = (size + 1) / 2; + midm1 = (size - 1) / 2; + two_pi = 8.0f * qAtan(1.0); + freq = two_pi / size; + rate = 1.0 / midn; + angle = 0.0; + expn = log(2.0) / midn + 1.0; + expsum = 1.0; + + switch (wtype) { + + case 1: // RECTANGULAR_WINDOW + for (i = 0; i < size; i++) + window[i] = 1.0; + break; + case 2: // HANNING_WINDOW + for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq) + window[j] = (window[i] = 0.5 - 0.5 * cos(angle)); + break; + case 3: // WELCH_WINDOW + for (i = 0, j = size - 1; i <= midn; i++, j--) + window[j] = (window[i] = 1.0 - (float)sqrt((float)((i - midm1) / midp1))); + break; + case 4: // PARZEN_WINDOW + for (i = 0, j = size - 1; i <= midn; i++, j--) + window[j] = (window[i] = 1.0 - ((float)fabs((float)(i - midm1) / midp1))); + break; + case 5: // BARTLETT_WINDOW + for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += rate) + window[j] = (window[i] = angle); + break; + case 6: // HAMMING_WINDOW + for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq) + window[j] = (window[i] = 0.5F - 0.46 * cos(angle)); + break; + case 7: // BLACKMAN2_WINDOW + for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq) { + cx = cos(angle); + window[j] = (window[i] = (.34401 + (cx * (-.49755 + (cx * .15844))))); + } + break; + case 8: // BLACKMAN3_WINDOW + for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq) { + cx = cos(angle); + window[j] = (window[i] = (.21747 + (cx * (-.45325 + (cx * (.28256 - (cx * .04672))))))); + } + break; + case 9: // BLACKMAN4_WINDOW + for (i = 0, j = size - 1, angle = 0.0; i <= midn; i++, j--, angle += freq) + { + cx = cos(angle); + window[j] = (window[i] = + (.084037 + + (cx * + (-.29145 + + (cx * + (.375696 + (cx * (-.20762 + (cx * .041194))))))))); + } + break; + case 10: // EXPONENTIAL_WINDOW + for (i = 0, j = size - 1; i <= midn; i++, j--) { + window[j] = (window[i] = expsum - 1.0); + expsum *= expn; + } + break; + case 11: // RIEMANN_WINDOW + sr1 = two_pi / size; + for (i = 0, j = size - 1; i <= midn; i++, j--) { + if (i == midn) window[j] = (window[i] = 1.0); + else { + cx = sr1 * (midn - i); + window[i] = sin(cx) / cx; + window[j] = window[i]; + } + } + break; + case 12: // BLACKMANHARRIS_WINDOW + { + float + a0 = 0.35875f, + a1 = 0.48829f, + a2 = 0.14128f, + a3 = 0.01168f; + + + for (i = 0; i < size; i++) + { + window[i] = a0 - a1* qCos(TWOPI * (i+0.5)/size) + + a2* qCos(2.0 * TWOPI * (i+0.5)/size) + - a3* qCos(3.0 * TWOPI * (i+0.5)/size); + } + } + break; + + default: + return; + } +} diff --git a/Source/src/QtDSP/qtdsp_filter.h b/Source/src/QtDSP/qtdsp_filter.h new file mode 100644 index 0000000..4706bb3 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_filter.h @@ -0,0 +1,153 @@ +/** +* @file qtdsp_filter.h +* @brief Filter header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_FILTER_H +#define _QTDSP_FILTER_H + +//#include +//#include +//#include +#include +//#include +#include "qtdsp_fft.h" +#include "qtdsp_qComplex.h" +#include "qtdsp_invsinc_coeff.h" +#include "../cusdr_settings.h" + +//#include +//#include + +#ifdef LOG_QTDSP_FILTER +# define FILTER_DEBUG qDebug().nospace() << "QtDSP_Filter::\t" +#else +# define FILTER_DEBUG nullDebug() +#endif + + + +#define BLACKMANHARRIS_WINDOW 12 + +class QFilter : public QObject { + + Q_OBJECT + +public: + QFilter(QObject *parent = 0, int size = 0, const int ftype = 2, const int wtype = 12); + ~QFilter(); + +private: + Settings *set; + + QMutex mutex; + + bool m_streamMode; + + int m_size; + int m_ftype; + int m_wtype; + + float m_samplerate; + float m_filter_lo; + float m_filter_hi; + + CPX ovlp; + CPX filter; + CPX res; + CPX tmpfilt0; + CPX tmpfilt1; + CPX tmp; + CPX tmp0; + CPX tmp1; + CPX tmp2; + + QFFT *ovlpfft; + QFFT *filtfft; + +private slots: + void LoadFilter(CPX &taps); + void MakeFirLowpass(float cutoff, + float samplerate, + int wtype, + float *taps_re, + float *taps_im, + int length); + + void MakeFirLowpass(float cutoff, + float samplerate, + int wtype, + CPX &taps, + int length); + + void MakeFirBandpass(float lo, + float hi, + float samplerate, + int wtype, + float *taps_re, + float *taps_im, + int length); + + void MakeFirBandpass(float lo, + float hi, + float samplerate, + int wtype, + CPX &taps, + int length); + + void MakeFirBandstop(float lo, + float hi, + float samplerate, + CPX &taps, + int length); + + //void DoConvolutionCPX(); + void DoOverlapAddCPX(); + +public slots: + void setSampleRate(QObject *sender, int value); + + void MakeFilter(const float lo, const float hi, const int ftype, const int wtype); + static void MakeWindow(int wtype, int size, float * window); + + void ProcessFilter(CPX &in, CPX &out, int bsize); + void ProcessForwardFilter(CPX &in, CPX &out, int bsize); + void ProcessChirpFilter(CPX &in, CPX &out, int bsize); + int ProcessAndDecimate(CPX &in, CPX &out, int bsize); + void Decimate(CPX &in, CPX &out, int downrate); + void DoConvolutionCPX(); + void Normalize(CPX &in, CPX &out, int size); + + float filterLo() const ; + float filterHi() const ; + int isStreamMode() const; + void setFilterLo(const float value); + void setFilterHi(const float value); + void setFilter(const float loval, const float hival); + void setStreamMode(int value); +}; + +#endif // _QTDSP_FILTER_H diff --git a/Source/src/QtDSP/qtdsp_invsinc_coeff.h b/Source/src/QtDSP/qtdsp_invsinc_coeff.h new file mode 100644 index 0000000..a1df037 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_invsinc_coeff.h @@ -0,0 +1,141 @@ +/** +* @file qtdsp_invsinc_coeff.h +* @brief Filter coefficients header file for QtDSP +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-18 +*/ + +/* + * Copyright (C) 2007, 2008 Philip A Covington, N8VB + * + * adapted for cuSDR by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_INVSINC_COEFF_H +#define _QTDSP_INVSINC_COEFF_H + +#define FILTERCOEFFSIZE 512 + +const float FILTERCOEFF[512] = { + + -7.298647688e-005f, -0.0006591212004f, -0.002619047416f, -0.006309854332f, -0.0100497622f, + -0.01030933112f, -0.00512559386f, 0.002354965545f, 0.005713210441f, 0.002275705803f, + -0.003084241645f, -0.003601335222f, 0.0007034620503f, 0.003363352269f, 0.0008431510651f, + -0.002575940453f, -0.001681111869f, 0.001701403758f, 0.002036997117f, -0.0009210249991f, + -0.002096840879f, 0.0002871879842f, 0.001987287775f, 0.0001987546857f, -0.001792274415f, + -0.0005589024513f, 0.001559824217f, 0.0008162951563f, -0.001320442185f, -0.000995823415f, + 0.001087572658f, 0.001113920705f, -0.0008722782368f, -0.001188867842f, 0.0006758925156f, + 0.001231985865f, -0.000498666428f, -0.001251817564f, 0.0003399479028f, 0.001254849718f, + -0.0001991765457f, -0.001247569569f, 7.392977568e-005f, 0.001235375414f, 4.123276085e-005f, + -0.001217678422f, -0.0001465942914f, 0.001196535421f, 0.000243384231f, -0.00117429113f, + -0.0003348062455f, 0.001149932388f, 0.0004205152218f, -0.00112563686f, -0.0005032685003f, + 0.001100820256f, 0.0005843482213f, -0.001074886066f, -0.0006646135589f, 0.001047056401f, + 0.0007442943752f, -0.00101693254f, -0.0008235950954f, 0.0009842554573f, 0.0009030248038f, + -0.0009477832355f, -0.0009810557822f, 0.0009091657703f, 0.001059165923f, -0.0008679664461f, + -0.001138553023f, 0.00082209229f, 0.001217685989f, -0.0007719836431f, -0.001296614995f, + 0.0007174044149f, 0.001375256572f, -0.0006578231696f, -0.001452584052f, 0.000594522804f, + 0.001530058333f, -0.0005264937645f, -0.001608328195f, 0.0004511743609f, 0.001684416085f, + -0.0003703148686f, -0.001758773113f, 0.0002839826047f, 0.001831884147f, -0.0001910350693f, + -0.001902386313f, 9.27066576e-005f, 0.001972250175f, 1.451703884e-005f,-0.002037639031f, + -0.0001286926563f, 0.002098251833f, 0.0002489787876f, -0.002154306741f, -0.0003754671779f, + 0.002205130411f, 0.0005068014725f, -0.002253053477f, -0.0006465745391f, 0.002294297796f, + 0.0007927893312f, -0.00232853787f, -0.000944050902f, 0.002357372548f, 0.001102598035f, + -0.002377682133f, -0.001264899038f, 0.002393632894f, 0.001436556573f, -0.002398973331f, + -0.001613004017f, 0.002395873656f, 0.001796123339f, -0.002380831633f, -0.001981404843f, + 0.002357972786f, 0.002172444016f, -0.00232419977f, -0.002367483685f, 0.002279908862f, + 0.002567417221f, -0.002222327981f, -0.002768594073f, 0.00215465948f, 0.002974577248f, + -0.002071162919f, -0.003176601371f, 0.001984296367f, 0.003392344108f, -0.001870410633f, + -0.003593309782f, 0.001762269414f, 0.003818378551f, -0.001613235101f, -0.004014817532f, + 0.001478523714f, 0.004237284884f, -0.001307581435f, -0.004444869235f, 0.001126970164f, + 0.004649222363f, -0.0009381354903f, -0.004864084534f, 0.0007162823458f, 0.005058682058f, + -0.0004906012327f, -0.005254743621f, 0.0002504401491f, 0.005455542356f, 2.14788397e-005f, + -0.005635460373f, -0.0003002338926f, 0.005811699666f, 0.0005916802911f, -0.005991247483f, + -0.0009132201085f, 0.006154606584f, 0.001253017108f, -0.006301850546f, -0.001601491706f, + 0.006448314991f, 0.001975012943f, -0.006583563052f, -0.002374651376f, 0.00669672247f, + 0.002787304111f, -0.006796817295f, -0.003215527395f, 0.006888513919f, 0.003669659607f, + -0.006961984094f, -0.004147280473f, 0.007011558395f, 0.004639521241f, -0.007045097649f, + -0.005150847603f, 0.007064725272f, 0.005690811202f, -0.007059961092f, -0.006256772671f, + 0.007024813443f, 0.006840964779f, -0.00696356874f, -0.007443124428f, 0.006882129703f, + 0.008074145764f, -0.00677188905f, -0.00873577781f, 0.006622628309f, 0.009418459609f, + -0.006438742857f, -0.01012247056f, 0.006224870216f, 0.01085730083f, -0.005974722095f, + -0.01162762847f, 0.005678492598f, 0.01243014261f, -0.005333583802f, -0.01326503698f, + 0.004937817343f, 0.01413488016f, -0.004487683997f, -0.01504271384f, 0.003980736714f, + 0.01599739864f, -0.003406297183f, -0.0170029439f, 0.002752586966f, 0.01805772632f, + -0.002016746672f, -0.01917018928f, 0.00119104574f, 0.02035386302f, -0.0002581478329f, + -0.02161752619f, -0.0007987120189f, 0.02297377214f, 0.00200156169f, -0.02443705499f, + -0.003379397793f, 0.02601802349f, 0.004954055417f, -0.02774950489f, -0.0067701675f, + 0.02966706641f, 0.00888942834f, -0.03181019425f, -0.01138752978f, 0.03424045816f, + 0.01438213047f, -0.03702627495f, -0.01802601293f, 0.04027441144f, 0.02255047485f, + -0.04414317012f, -0.02832753956f, 0.04885149002f, 0.03595076501f, -0.0547539629f, + -0.04649358243f, 0.06237275898f, 0.06197695807f, -0.07256446034f, -0.08679046482f, + 0.0865688622f, 0.1321066916f, -0.1050333083f, -0.2351729274f, 0.1105839834f, + 0.6013018489f, 0.6013018489f, 0.1105839834f, -0.2351729274f, -0.1050333083f, + 0.1321066916f, 0.0865688622f, -0.08679046482f, -0.07256446034f, 0.06197695807f, + 0.06237275898f, -0.04649358243f, -0.0547539629f, 0.03595076501f, 0.04885149002f, + -0.02832753956f, -0.04414317012f, 0.02255047485f, 0.04027441144f, -0.01802601293f, + -0.03702627495f, 0.01438213047f, 0.03424045816f, -0.01138752978f, -0.03181019425f, + 0.00888942834f, 0.02966706641f, -0.0067701675f, -0.02774950489f, 0.004954055417f, + 0.02601802349f, -0.003379397793f, -0.02443705499f, 0.00200156169f, 0.02297377214f, + -0.0007987120189f, -0.02161752619f, -0.0002581478329f, 0.02035386302f, 0.00119104574f, + -0.01917018928f, -0.002016746672f, 0.01805772632f, 0.002752586966f, -0.0170029439f, + -0.003406297183f, 0.01599739864f, 0.003980736714f, -0.01504271384f, -0.004487683997f, + 0.01413488016f, 0.004937817343f, -0.01326503698f, -0.005333583802f, 0.01243014261f, + 0.005678492598f, -0.01162762847f, -0.005974722095f, 0.01085730083f, 0.006224870216f, + -0.01012247056f, -0.006438742857f, 0.009418459609f, 0.006622628309f, -0.00873577781f, + -0.00677188905f, 0.008074145764f, 0.006882129703f, -0.007443124428f, -0.00696356874f, + 0.006840964779f, 0.007024813443f, -0.006256772671f, -0.007059961092f, 0.005690811202f, + 0.007064725272f, -0.005150847603f, -0.007045097649f, 0.004639521241f, 0.007011558395f, + -0.004147280473f, -0.006961984094f, 0.003669659607f, 0.006888513919f, -0.003215527395f, + -0.006796817295f, 0.002787304111f, 0.00669672247f, -0.002374651376f, -0.006583563052f, + 0.001975012943f, 0.006448314991f, -0.001601491706f, -0.006301850546f, 0.001253017108f, + 0.006154606584f, -0.0009132201085f, -0.005991247483f, 0.0005916802911f, 0.005811699666f, + -0.0003002338926f, -0.005635460373f, 2.14788397e-005f, 0.005455542356f, 0.0002504401491f, + -0.005254743621f, -0.0004906012327f, 0.005058682058f, 0.0007162823458f, -0.004864084534f, + -0.0009381354903f, 0.004649222363f, 0.001126970164f, -0.004444869235f, -0.001307581435f, + 0.004237284884f, 0.001478523714f, -0.004014817532f, -0.001613235101f, 0.003818378551f, + 0.001762269414f, -0.003593309782f, -0.001870410633f, 0.003392344108f, 0.001984296367f, + -0.003176601371f, -0.002071162919f, 0.002974577248f, 0.00215465948f, -0.002768594073f, + -0.002222327981f, 0.002567417221f, 0.002279908862f, -0.002367483685f, -0.00232419977f, + 0.002172444016f, 0.002357972786f, -0.001981404843f, -0.002380831633f, 0.001796123339f, + 0.002395873656f, -0.001613004017f, -0.002398973331f, 0.001436556573f, 0.002393632894f, + -0.001264899038f, -0.002377682133f, 0.001102598035f, 0.002357372548f, -0.000944050902f, + -0.00232853787f, 0.0007927893312f, 0.002294297796f, -0.0006465745391f, -0.002253053477f, + 0.0005068014725f, 0.002205130411f, -0.0003754671779f, -0.002154306741f, 0.0002489787876f, + 0.002098251833f, -0.0001286926563f, -0.002037639031f, 1.451703884e-005f, 0.001972250175f, + 9.27066576e-005f, -0.001902386313f, -0.0001910350693f, 0.001831884147f, 0.0002839826047f, + -0.001758773113f, -0.0003703148686f, 0.001684416085f, 0.0004511743609f, -0.001608328195f, + -0.0005264937645f, 0.001530058333f, 0.000594522804f, -0.001452584052f, -0.0006578231696f, + 0.001375256572f, 0.0007174044149f, -0.001296614995f, -0.0007719836431f, 0.001217685989f, + 0.00082209229f, -0.001138553023f, -0.0008679664461f, 0.001059165923f, 0.0009091657703f, + -0.0009810557822f, -0.0009477832355f, 0.0009030248038f, 0.0009842554573f, -0.0008235950954f, + -0.00101693254f, 0.0007442943752f, 0.001047056401f, -0.0006646135589f, -0.001074886066f, + 0.0005843482213f, 0.001100820256f, -0.0005032685003f, -0.00112563686f, 0.0004205152218f, + 0.001149932388f, -0.0003348062455f, -0.00117429113f, 0.000243384231f, 0.001196535421f, + -0.0001465942914f, -0.001217678422f, 4.123276085e-005f, 0.001235375414f, 7.392977568e-005f, + -0.001247569569f, -0.0001991765457f, 0.001254849718f, 0.0003399479028f, -0.001251817564f, + -0.000498666428f, 0.001231985865f, 0.0006758925156f, -0.001188867842f, -0.0008722782368f, + 0.001113920705f, 0.001087572658f, -0.000995823415f, -0.001320442185f, 0.0008162951563f, + 0.001559824217f, -0.0005589024513f, -0.001792274415f, 0.0001987546857f, 0.001987287775f, + 0.0002871879842f, -0.002096840879f, -0.0009210249991f, 0.002036997117f, 0.001701403758f, + -0.001681111869f, -0.002575940453f, 0.0008431510651f, 0.003363352269f, 0.0007034620503f, + -0.003601335222f, -0.003084241645f, 0.002275705803f, 0.005713210441f, 0.002354965545f, + -0.00512559386f, -0.01030933112f, -0.0100497622f, -0.006309854332f, -0.002619047416f, + -0.0006591212004f, -7.298647688e-005f +}; + +#endif // _QTDSP_INVSINC_COEFF_H diff --git a/Source/src/QtDSP/qtdsp_powerSpectrum.cpp b/Source/src/QtDSP/qtdsp_powerSpectrum.cpp new file mode 100644 index 0000000..c12713a --- /dev/null +++ b/Source/src/QtDSP/qtdsp_powerSpectrum.cpp @@ -0,0 +1,212 @@ +/** +* @file qtdsp_powerSpectrum.cpp +* @brief Power Spectrum class for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-14 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#define LOG_POWERSPECTRUM + +#include "qtdsp_powerSpectrum.h" + +PowerSpectrum::PowerSpectrum(QObject *parent, int size) + : QObject(parent) + , set(Settings::instance()) + , first(true) + , m_size(size) + , m_spectrumSize(size*2) + , m_psswitch(0) + , m_averages(4) + , m_samplerate(set->getSampleRate()) + , m_baseline((float)1.0e-15) + , m_correction(0.0f) +{ + m_window = new float[m_size]; + m_fPsdBm = new float[m_size * 2]; + m_fAvePsdBm = new float[m_size * 2]; + + windowCPX.resize(m_size); + tmpCPX.resize(m_size * 2); + dataCPX.resize(0); + + zero.re = 0.0f; + zero.im = 0.0f; + + m_fft = new QFFT(m_size * 2); + + memset(m_fPsdBm, 0, m_size * 2 * sizeof(float)); + memset(m_fAvePsdBm, 0, m_size * 2 * sizeof(float)); + memset(m_window, 0, m_size * sizeof(float)); + + QFilter::MakeWindow(BLACKMANHARRIS_WINDOW, size, m_window); + + for (int i = 0; i < m_size; i++) { + + windowCPX[i].re = m_window[i]; + windowCPX[i].im = m_window[i]; + } + + cnt = 0; +} + +PowerSpectrum::~PowerSpectrum() { + + if (m_fft) + delete m_fft; + + windowCPX.clear(); + tmpCPX.clear(); + dataCPX.clear(); + + if (m_window) + delete m_window; + + if (m_fPsdBm) + delete m_fPsdBm; + + if (m_fAvePsdBm) + delete m_fAvePsdBm; +} + +void PowerSpectrum::setupConnections() { +} + +//void PowerSpectrum::ProcessSpectrum(CPX &in, int size) { +// +// Q_UNUSED(size) +// +// if (first && dataCPX.size() == 0) { +// +// dataCPX << in; +// first = false; +// return; +// } +// else { +// +// dataCPX << in; +// tmpCPX.fill(zero, m_size*2); +// +// if (dataCPX.size() == m_size) { +// +// for (int i = 0; i < m_size; i++) +// tmpCPX[i] = MultCPX(dataCPX.at(i), windowCPX.at(i)); +// +// m_mutex.lock(); +// m_fft->DoFFTWMagnForward(tmpCPX, m_size * 2, m_baseline, m_correction, m_fPsdBm); +// m_mutex.unlock(); +// } +// +// first = true; +// dataCPX.resize(0); +// } +//} + +void PowerSpectrum::ProcessSpectrum(CPX &in, int size, int maxCnt) { + + Q_UNUSED(size) + + if (cnt < maxCnt) { // maxCnt = 1: 4096, maxCnt = 3: 8192, maxCnt = 7: 16384 + + dataCPX << in; + //first = false; + cnt++; + return; + } + else { + + dataCPX << in; + tmpCPX.fill(zero, m_size*2); + + if (dataCPX.size() == m_size) { + + for (int i = 0; i < m_size; i++) + tmpCPX[i] = MultCPX(dataCPX.at(i), windowCPX.at(i)); + + m_mutex.lock(); + m_fft->DoFFTWMagnForward(tmpCPX, m_size * 2, m_baseline, m_correction, m_fPsdBm); + m_mutex.unlock(); + } + + //first = true; + cnt = 0; + dataCPX.resize(0); + } +} + +void PowerSpectrum::setBaseLine(float value) { + + m_baseline = value; +} + +void PowerSpectrum::setCorrection(float value) { + + m_correction = value; +} + +void PowerSpectrum::setPsOn(int value) { + + m_psswitch = value; +} + +//int PowerSpectrum::psdBmResults(float* buffer) { +// +// if (buffer == NULL) return 0; +// +// m_mutex.lock(); +// memcpy(buffer, m_fPsdBm, dBmSize() * sizeof(float)); +// m_mutex.unlock(); +// +// return dBmSize(); +//} + +int PowerSpectrum::spectrumResult(qVectorFloat &buffer, int shift) { + + if (buffer.size() == 0) return 0; + + m_mutex.lock(); + + memcpy( + (float *) buffer.data(), + (float *) &m_fPsdBm[shift], + 4096 * sizeof(float)); + + m_mutex.unlock(); + + return buffer.size(); +} + +void PowerSpectrum::setAverages(int value) { + + m_averages = value; +} + +float PowerSpectrum::grabPsPoint(int index) { + + return m_fPsdBm[index]; +} + +int PowerSpectrum::dBmSize() const { + + return m_spectrumSize; +} + diff --git a/Source/src/QtDSP/qtdsp_powerSpectrum.h b/Source/src/QtDSP/qtdsp_powerSpectrum.h new file mode 100644 index 0000000..01326b9 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_powerSpectrum.h @@ -0,0 +1,108 @@ +/** +* @file qtdsp_powerSpectrum.h +* @brief Power Spectrum header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-14 +*/ + +/* + * Copyright (C) 2007, 2008, 2009, 2010 Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_POWERSPECTRUM_H +#define _QTDSP_POWERSPECTRUM_H + +#include "qtdsp_qComplex.h" +#include "qtdsp_fft.h" +#include "qtdsp_filter.h" +#include "../cusdr_settings.h" + +#include +#include + + +#ifdef LOG_POWERSPECTRUM +# define POWERSPECTRUM_DEBUG qDebug().nospace() << "PowerSpectrum::\t" +#else +# define POWERSPECTRUM_DEBUG nullDebug() +#endif + + +class PowerSpectrum : public QObject { + + Q_OBJECT + +public: + PowerSpectrum(QObject *parent = 0, int size = 0); + ~PowerSpectrum(); + + void ProcessSpectrum(CPX &in, int size, int maxCnt); + + //int psdBmResults(float *buffer); + int spectrumResult(qVectorFloat &buffer, int shift); + + float grabPsPoint(int index); + + void setBaseLine(float value); + void setCorrection(float value); + void setPsOn(int value); + void setAverages(int value); + + int dBmSize() const;// { return m_size * 2; } + int psIsOn() const { return m_psswitch; } + int averages() const { return m_averages; } + float baseLine() const { return m_baseline; } + float correction() const { return m_correction; } + +public slots: + //void setSampleSize(int rx, int size); + +private: + Settings* set; + + QMutex m_mutex; + + cpx zero; + CPX windowCPX; + CPX tmpCPX; + CPX dataCPX; + + QFFT* m_fft; + + bool first; + + int m_size; + int m_spectrumSize; + int m_psswitch; + int m_averages; + int cnt; + + float m_samplerate; + float m_baseline; + float m_correction; + + float* m_window; + float* m_fPsdBm; + float* m_fAvePsdBm; + + void setupConnections(); +}; + +#endif // _QTDSP_POWERSPECTRUM_H diff --git a/Source/src/QtDSP/qtdsp_qComplex.h b/Source/src/QtDSP/qtdsp_qComplex.h new file mode 100644 index 0000000..a3315a1 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_qComplex.h @@ -0,0 +1,146 @@ +/** +* @file qtdsp_qComplex.h +* @brief qComplex type header for QtDSP +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-09-22 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * Based on the complex type CPX by Philip A Covington, p.covington@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_QCOMPLEX_H +#define _QTDSP_QCOMPLEX_H + +#include +#include +#include +#include +#include + +using namespace std; + +#undef max + +typedef struct _QCOMPLEX { + + float re; + float im; + +} cpx; + +Q_DECLARE_METATYPE (cpx) +Q_DECLARE_TYPEINFO(cpx, Q_MOVABLE_TYPE); + +typedef QVector CPX; + +Q_DECLARE_METATYPE (CPX) + +inline void InitCPX(CPX &vec, int size, float value) { + + cpx zero; + zero.re = value; zero.im = value; + + vec.resize(size); + vec.fill(zero); +} + +inline cpx ToCPX(qreal x, qreal y) { + + cpx z; + z.re = x; + z.im = y; + + return z; +} + +inline cpx ScaleCPX(const cpx &c, float a) { + + cpx z; + z.re = a * c.re; + z.im = a * c.im; + + return z; +} + +inline cpx AddCPX(cpx x, cpx y) { + + cpx z; + z.re = x.re + y.re; + z.im = x.im + y.im; + + return z; +} + +inline void PlusCPX(CPX &a, CPX &b, CPX &c) { + + CPX z; + z.resize(0); + + int sa = a.size(); + int sb = b.size(); + + if (sa != sb) return; + + z.resize(sa); + for (int i = 0; i < sa; i++) { + + z[i].re = a.at(i).re + b.at(i).re; + z[i].im = a.at(i).im + b.at(i).im; + + c[i].re = z.at(i).re; + c[i].im = z.at(i).im; + } +} + +inline cpx MultCPX(cpx x, cpx y) { + + cpx z; + z.re = x.re * y.re - x.im * y.im; + z.im = x.im * y.re + x.re * y.im; + return z; +} + +inline float MagCPX(cpx z) { + + return (float) (z.re * z.re + z.im * z.im); +} + +inline float SqrMagCPX(cpx z) { + + return (float) sqrt(z.re * z.re + z.im * z.im); +} + +inline QString ValidQReal(qreal value) { + + if (value != value) { + return "NaN"; + } + else if (value > numeric_limits::max()){ + return "+Inf"; + } + else if (value < -numeric_limits::max()){ + return "-Inf"; + } + else + return ""; +} + +#endif // _QTDSP_QCOMPLEX_H diff --git a/Source/src/QtDSP/qtdsp_signalMeter.cpp b/Source/src/QtDSP/qtdsp_signalMeter.cpp new file mode 100644 index 0000000..523b4e6 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_signalMeter.cpp @@ -0,0 +1,74 @@ +/** +* @file qtdsp_signalMeter.cpp +* @brief Signal Meter class for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-19 +*/ + +/* + * Copyright (C) 2007, 2008, Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * With Algorithms borrowed from DttSP + * Copyright (C) 2004, 2005, 2006 by Frank Brickle, AB2KT and Bob McGwier, N4HY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "qtdsp_signalMeter.h" + +SignalMeter::SignalMeter(QObject *parent, int size) + : QObject(parent) + , set(Settings::instance()) + , m_size(size) + , m_instValue(-80.0) + //, m_correction(59.0f) + , m_correction(-8.0f) +{ +} + +SignalMeter::~SignalMeter() { +} + +void SignalMeter::ProcessBlock(CPX &in, int bsize) { + + Q_UNUSED(bsize) + + float tmp = 0.0f; + + for (int i = 0; i < m_size; i++) + tmp += (in.at(i).re * in.at(i).re + in.at(i).im * in.at(i).im); + + m_instValue = (float)(10.0f * log10(tmp + 1.5E-45)); +} + +float SignalMeter::getInstFValue() const { + + return m_instValue + m_correction; +} + +float SignalMeter::getCorrection() const { + + return m_correction; +} + +void SignalMeter::setCorrection(const float value) { + + if (m_correction == value) return; + + m_correction = value; +} diff --git a/Source/src/QtDSP/qtdsp_signalMeter.h b/Source/src/QtDSP/qtdsp_signalMeter.h new file mode 100644 index 0000000..dc3366a --- /dev/null +++ b/Source/src/QtDSP/qtdsp_signalMeter.h @@ -0,0 +1,69 @@ +/** +* @file qtdsp_signalMeter.h +* @brief Signal meter header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-19 +*/ + +/* + * Copyright (C) 2007, 2008, Philip A Covington, N8VB + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * With Algorithms borrowed from DttSP + * Copyright (C) 2004, 2005, 2006 by Frank Brickle, AB2KT and Bob McGwier, N4HY + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _QTDSP_SIGNALMETER_H +#define _QTDSP_SIGNALMETER_H + +#define SPECDBMOFFSET 100.50 + +#include +#include "qtdsp_qComplex.h" +#include "../cusdr_settings.h" + +#include +#include + +class SignalMeter : public QObject { + + Q_OBJECT + +public: + SignalMeter(QObject *parent = 0, int size = 0); + ~SignalMeter(); + + void ProcessBlock(CPX &in, int bsize); + + float getInstFValue() const; + float getCorrection() const; + +public slots: + void setCorrection(const float value); + +private: + Settings *set; + + int m_size; + + float m_instValue; + float m_correction; +}; + +#endif // _QTDSP_SIGNALMETER_H diff --git a/Source/src/QtDSP/qtdsp_wpagc.cpp b/Source/src/QtDSP/qtdsp_wpagc.cpp new file mode 100644 index 0000000..e70f8e6 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_wpagc.cpp @@ -0,0 +1,630 @@ +/** +* @file qtdsp_wpagc.cpp +* @brief Warren Pratt's ingenious AGC class for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-14 +*/ + +/* + * Copyright (C) 2011, 2012 Warren Pratt, NR0V + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The author can be reached by email at + * + * warren@wpratt.com + */ +#define LOG_WPAGC + +#include "qtdsp_wpagc.h" + +QWPAGC::QWPAGC(QObject *parent, int size) + : QObject(parent) + , set(Settings::instance()) + , m_size(size) + , m_samplerate(set->getSampleRate()) + , m_nTau(4) + , m_outIndex(-1) + , m_inIndex(0) + , m_attackBuffersize(0) + , m_state(0) + , m_hangCounter(0) + , m_decayType(0) + , m_fixedGain(1000) + , m_tauAttack(0.001) + , m_tauDecay(0.250) + //, m_maxGain(100000.0) + , m_varGain(1.0) + , m_minVolts(0.0) + + // Warren NR0V reports that this change needs to be made in order for things to be + // in the right position on the screen and other factors: + , m_maxInput(500.0) + + , m_out_targ(1.0) + , m_out_target(0.0) + , m_inv_max_input(0.0) + , m_slope_constant(0.0) + , m_ring_max(0.0) + , m_attack_mult(0.0) + , m_decay_mult(0.0) + , m_volts(0.0) + , m_save_volts(0.0) + , m_abs_out_sample(0.0) + , m_tau_fast_backaverage(0.250) + , m_fast_backmult(0.0) + , m_onemfast_backmult(1.0) + , m_fast_backaverage(0.0) + , m_tau_fast_decay(0.005) + , m_fast_decay_mult(0.0) + , m_pop_ratio(5.0) + , m_hang_backaverage(0.0) + , m_tau_hang_backmult(0.500) + , m_hang_backmult(0.0) + , m_onemhang_backmult(1.0) + , m_hangtime(0.250) + , m_hangThresh(0.01) + , m_hangLevel(0.0) + , m_tau_hang_decay(0.100) + , m_hang_decay_mult(0.0) + , SinAverage(0.637) +{ + InitCPX(buf, m_size, 0.0f); + InitCPX(ring, RINGBUFFERSIZE, 0.0f); + + outSample.re = 0.0f; + outSample.im = 0.0f; + + absRing.resize(RINGBUFFERSIZE); + absRing.fill(0.0); + + initWcpAGC(); +} + +QWPAGC::~QWPAGC() { + + buf.clear(); + ring.clear(); +} + +//void QWPAGC::setupConnections() { +// +//} + +void QWPAGC::ProcessAGC(CPX &in, CPX &out, int size) { + + Q_UNUSED(size) + + if (m_agcMode == agcOFF) { + + for (int i = 0; i < m_size; i++) + out[i] = ScaleCPX(in.at(i), m_fixedGain); + + return; + } + + memcpy(buf.data(), in.data(), sizeof(cpx) * m_size); + + int i, j, k; + //qreal mult; + + mutex.lock(); + for (i = 0; i < m_size; i++) { + + if (++m_outIndex >= RINGBUFFERSIZE) + m_outIndex -= RINGBUFFERSIZE; + + if (++m_inIndex >= RINGBUFFERSIZE) + m_inIndex -= RINGBUFFERSIZE; + + outSample.re = ring.at(m_outIndex).re; + outSample.im = ring.at(m_outIndex).im; + + //m_abs_out_sample = absRing[m_out_index]; + m_abs_out_sample = absRing.at(m_outIndex); + + ring[m_inIndex].re = buf.at(i).re; + ring[m_inIndex].im = buf.at(i).im; + + absRing[m_inIndex] = qMax(qAbs(ring.at(m_inIndex).re), qAbs(ring.at(m_inIndex).im)); + + m_fast_backaverage = m_fast_backmult * m_abs_out_sample + m_onemfast_backmult * m_fast_backaverage; + m_hang_backaverage = m_hang_backmult * m_abs_out_sample + m_onemhang_backmult * m_hang_backaverage; + + if ((m_abs_out_sample >= m_ring_max) && (m_abs_out_sample > 0)) { + + m_ring_max = 0.0; + k = m_outIndex; + + for (j = 0; j < m_attackBuffersize; j++) { + + if (++k == RINGBUFFERSIZE) + k = 0; + if (absRing[k] > m_ring_max) + //m_ring_max = absRing[k]; + m_ring_max = absRing.at(k); + } + } + + if (absRing[m_inIndex] > m_ring_max) + //m_ring_max = absRing[m_in_index]; + m_ring_max = absRing.at(m_inIndex); + + if (m_hangCounter > 0) + --m_hangCounter; + + switch (m_state) { + + case 0: + + if (m_ring_max >= m_volts) { + + m_volts += (m_ring_max - m_volts) * m_attack_mult; + } + else { + if (m_volts > m_pop_ratio * m_fast_backaverage) { + + m_state = 1; + m_volts += (m_ring_max - m_volts) * m_fast_decay_mult; + } + else { + + if (m_hang_backaverage > m_hangLevel) { + + m_state = 2; + m_hangCounter = (int)(m_hangtime * m_samplerate); + m_decayType = 1; + } + else { + + m_state = 3; + m_volts += (m_ring_max - m_volts) * m_decay_mult; + m_decayType = 0; + } + } + } + break; + + case 1: + + if (m_ring_max >= m_volts) { + + m_state = 0; + m_volts += (m_ring_max - m_volts) * m_attack_mult; + } + else { + + if (m_volts > m_save_volts) { + + m_volts += (m_ring_max - m_volts) * m_fast_decay_mult; + } + else { + + if (m_hangCounter > 0) { + + m_state = 2; + } + else { + + if (m_decayType == 0) { + + m_state = 3; + m_volts += (m_ring_max - m_volts) * m_decay_mult; + } + else { + + m_state = 4; + m_volts += (m_ring_max - m_volts) * m_hang_decay_mult; + } + } + } + } + break; + + case 2: + + if (m_ring_max >= m_volts) { + + m_state = 0; + m_save_volts = m_volts; + m_volts += (m_ring_max - m_volts) * m_attack_mult; + } + else { + + if (m_hangCounter == 0) { + + m_state = 4; + m_volts += (m_ring_max - m_volts) * m_hang_decay_mult; + } + } + break; + + case 3: + + if (m_ring_max >= m_volts) { + + m_state = 0; + m_save_volts = m_volts; + m_volts += (m_ring_max - m_volts) * m_attack_mult; + } + else { + + m_volts += (m_ring_max - m_volts) * m_decay_mult; + } + break; + + case 4: + + if (m_ring_max >= m_volts) { + + m_state = 0; + m_save_volts = m_volts; + m_volts += (m_ring_max - m_volts) * m_attack_mult; + } + else { + + m_volts += (m_ring_max - m_volts) * m_hang_decay_mult; + } + + break; + } // end switch on state + + if (m_volts < m_minVolts) + m_volts = m_minVolts; + + mult = (m_out_target - m_slope_constant * qMin(0.0, log10 (m_inv_max_input * m_volts))) / m_volts; + + out[i].re = (float)(outSample.re * mult); + out[i].im = (float)(outSample.im * mult); + } + mutex.unlock(); +} + +void QWPAGC::initWcpAGC() { + + m_outIndex = -1; + m_ring_max = 0.0; + m_volts = 0.0; + m_save_volts = 0.0; + m_fast_backaverage = 0.0; + m_hang_backaverage = 0.0; + m_hangCounter = 0; + m_state = 0; + + //memset(absRing, 0, RINGBUFFERSIZE * sizeof(qreal)); + absRing.fill(0.0); + for (int i = 0; i < RINGBUFFERSIZE; i++) { + + ring[i].re = 0.0f; + ring[i].im = 0.0f; + } + + outSample.re = 0.0f; + outSample.im = 0.0f; + m_abs_out_sample = 0.0f; + m_decayType = 0; +} + +void QWPAGC::loadWcpAGC() { + + qreal tmp; + m_attackBuffersize = (int)qCeil(m_samplerate * m_nTau * m_tauAttack); + + m_inIndex = m_attackBuffersize + m_outIndex; + + m_attack_mult = 1.0 - qExp(-1.0 / (m_samplerate * m_tauAttack)); + m_decay_mult = 1.0 - qExp(-1.0 / (m_samplerate * m_tauDecay)); + m_fast_decay_mult = 1.0 - qExp(-1.0 / (m_samplerate * m_tau_fast_decay)); + m_fast_backmult = 1.0 - qExp(-1.0 / (m_samplerate * m_tau_fast_backaverage)); + m_onemfast_backmult = 1.0 - m_fast_backmult; + + m_out_target = m_out_targ * (1.0 - qExp(-m_nTau)) * 0.99; + m_minVolts = m_out_target / (m_varGain * m_maxGain); + + //WPAGC_DEBUG << "emit m_min_volts = " << m_min_volts; + //WPAGC_DEBUG << "emit m_max_gain = " << maxGain; + //emit minimumVoltageChanged(this, m_receiver, m_min_volts); + //emit agcMaximumGainChanged(m_max_gain); + + tmp = log10(m_out_target / (m_maxInput * m_varGain * m_maxGain)); + if (tmp == 0.0) + tmp = 1.5E-45; + + m_slope_constant = (m_out_target * (1.0 - (1.0 / m_varGain))) / tmp; + //m_slope_constant = (m_out_target * (1.0 - (1.0 / m_var_gain))) / (tmp + 1.5E-45); + + m_inv_max_input = 1.0 / m_maxInput; + + tmp = qPow(10.0, ((m_agcHangEnable ? m_hangThresh : 1.0) - 1.0) / 0.125); + m_hangLevel = (m_maxInput * tmp + (m_out_target / (m_varGain * m_maxGain)) * (1.0 - tmp)) * SinAverage; + + // send the hang level value out for display + //WPAGC_DEBUG << "hangLevel_dB = " << 20.0 * log10(m_hangLevel / SinAverage); + //emit hangLeveldBLineChanged(20.0 * log10(m_hangLevel / SinAverage)); + + m_hang_backmult = 1.0 - qExp(-1.0 / (m_samplerate * m_tau_hang_backmult)); + m_onemhang_backmult = 1.0 - m_hang_backmult; + + m_hang_decay_mult = 1.0 - qExp(-1.0 / (m_samplerate * m_tau_hang_decay)); + + emit displayValues(this, m_receiver, m_minVolts, 20.0 * log10(m_hangLevel / SinAverage)); +} + +void QWPAGC::setReceiver(int rx) { + + m_receiver = rx; +} + +void QWPAGC::setMode(AGCMode mode) { + + //mutex.lock(); + if ((m_agcMode == (AGCMode) agcOFF) && (mode != 0)) initWcpAGC(); + + m_agcMode = mode; + + switch (mode) { + + case agcOFF: + break; + + case agcSLOW: + + m_agcHangEnable = true; + m_hangtime = 1.0; + m_tauDecay = 0.500; + break; + + case agcMED: + + m_agcHangEnable = false; + m_hangtime = 0.0; + m_tauDecay = 0.250; + break; + + case agcFAST: + + m_agcHangEnable = false; + m_hangtime = 0.0; + m_tauDecay = 0.050; + break; + + case agcLONG: + + m_agcHangEnable = true; + m_hangtime = 2.0; + m_tauDecay = 2.0; + break; + + case agcUser: + + m_agcHangEnable = true; + m_hangtime = 2.0; + m_tauDecay = 2.0; + break; + + default: + + m_agcHangEnable = true; + m_hangtime = 2.0; + m_tauDecay = 2.0; + break; + } + //mutex.unlock(); +} + +void QWPAGC::setAGCHangEnable(bool value) { + + m_agcHangEnable = value; +} + +// fixed_gain when AGC is OFF (set to 'fixed'), linear +void QWPAGC::setAGCFixedGain(qreal value) { + + m_fixedGain = value; +} + +qreal QWPAGC::getAGCFixedGain() { + + return m_fixedGain; +} + +// fixed_gain when AGC is OFF (set to 'fixed'), in dB +void QWPAGC::setAGCFixedGainDb(qreal value) { + + qreal tmp = value; + if (tmp > 60.0) tmp = 60.0; + + m_fixedGain = qPow(10.0, tmp / 20.0); + //WPAGC_DEBUG << "m_fixedGain = " << m_fixedGain; +} + +qreal QWPAGC::getAGCFixedGainDb() { + + return 20.0 * log10(m_fixedGain); +} + +void QWPAGC::setSampleRate(QObject *sender, int value) { + + Q_UNUSED(sender) + + //mutex.lock(); + m_samplerate = value; + initWcpAGC(); + loadWcpAGC(); + //mutex.unlock(); +} + +// attack time constant in SECONDS +void QWPAGC::setTauAttack(qreal value) { + + mutex.lock(); + m_tauAttack = value; + loadWcpAGC(); + mutex.unlock(); +} + +qreal QWPAGC::getTauAttack() { + + return m_tauAttack; +} + +//decay time constant in SECONDS +void QWPAGC::setTauDecay(qreal value) { + + mutex.lock(); + m_tauDecay = value; + loadWcpAGC(); + mutex.unlock(); +} + +qreal QWPAGC::getTauDecay() { + + return m_tauDecay; +} + +// maximum AGC gain = gain below the "knee", linear +bool QWPAGC::setMaximumGain(qreal value) { + + mutex.lock(); + m_maxGain = value; + + if (ValidQReal(m_maxGain) == "NaN" || ValidQReal(m_maxGain) == "+Inf" || (m_maxGain <= 0)) { + + mutex.unlock(); + return false; // illegal values! + } + else + loadWcpAGC(); + + mutex.unlock(); + return true; +} + +qreal QWPAGC::getAGCMaximumGain_dBm() { + + return 20.0 * log10(m_maxGain); +} + +// maximum AGC gain = gain below the "knee", in dB +bool QWPAGC::setMaximumGainDb(qreal value) { + + mutex.lock(); + m_maxGain = qPow(10.0, value / 20.0); + //WPAGC_DEBUG << "maxGain from Slider = " << m_maxGain << " (" << value << " dB)"; + if (ValidQReal(m_maxGain) == "NaN" || ValidQReal(m_maxGain) == "+Inf" || (m_maxGain <= 0)) { + + mutex.unlock(); + WPAGC_DEBUG << "illegal value for maximum gain !"; + return false; // illegal values! + } + else + loadWcpAGC(); + + mutex.unlock(); + return true; +} + +// variable AGC gain = "Slope", linear +void QWPAGC::setVarGain(qreal value) { + + mutex.lock(); + m_varGain = value; + loadWcpAGC(); + mutex.unlock(); +} + +// variable AGC gain = "Slope", in dB +void QWPAGC::setVarGainDb(qreal value) { + + mutex.lock(); + m_varGain = qPow(10.0, value / 20.0); + loadWcpAGC(); + mutex.unlock(); +} + +// for hang threshold slider, range 0.0 to 1.0 +void QWPAGC::setHangThresh(qreal value) { + + mutex.lock(); + //WPAGC_DEBUG << "m_hang_thresh = " << value; + m_hangThresh = value; + loadWcpAGC(); + mutex.unlock(); +} + +// hangtime in SECONDS +void QWPAGC::setHangTime(qreal value) { + + mutex.lock(); + m_hangtime = value; + loadWcpAGC(); + mutex.unlock(); +} + +// for line on bandscope +void QWPAGC::setHangLevelDb(qreal value) { + + mutex.lock(); + if (m_maxInput > m_minVolts) { + + // BUG: found by Warren, 15 Jan 2012: 'SinAverage' term NOT needed! + // double convert = SinAverage * qPow(10.0, value / 20.0); + qreal convert = qPow(10.0, value / 20.0); + qreal tmp = qMax(1.0e-8, (convert - m_minVolts) / (m_maxInput - m_minVolts)); + m_hangThresh = 1.0 + 0.125 * log10(tmp); + } + else + m_hangThresh = 1.0; + + loadWcpAGC(); + mutex.unlock(); + + emit agcHangThresholdChanged(m_hangThresh * 100.0); +} + +// for line on bandscope +qreal QWPAGC::getHangLevelDb() { + + return 20.0 * log10(m_hangLevel / SinAverage); +} + +// for line on bandscope +//qreal QWPAGC::getAGCThreshDb(qreal filt_high, qreal filt_low, int spec_size) { +// +// qreal noise_offset = 10.0 * log10(qAbs(filt_high - filt_low) * spec_size / m_samplerate); +// return 20.0 * log10(m_min_volts) - noise_offset; +//} + +// for line on bandscope +void QWPAGC::setAGCThreshDb(qreal filt_high, qreal filt_low, int spec_size, qreal thresh) { + + mutex.lock(); + qreal noise_offset = 10.0 * log10(qAbs(filt_high - filt_low) * spec_size / m_samplerate); + m_maxGain = m_out_target / (m_varGain * qPow(10.0, (thresh + noise_offset) / 20.0)); + + loadWcpAGC(); + mutex.unlock(); + + //WPAGC_DEBUG << "maxGain = " << m_maxGain; + emit agcMaximumGainChanged(m_maxGain); +} + +void QWPAGC::filterChanged() { + + emit displayValues(this, m_receiver, m_minVolts, 20.0 * log10(m_hangLevel / SinAverage)); +} diff --git a/Source/src/QtDSP/qtdsp_wpagc.h b/Source/src/QtDSP/qtdsp_wpagc.h new file mode 100644 index 0000000..2ffe4d1 --- /dev/null +++ b/Source/src/QtDSP/qtdsp_wpagc.h @@ -0,0 +1,178 @@ +/** +* @file qtdsp_wpagc.h +* @brief Warren Pratt's ingenious AGC header file for QtDSP +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-05-14 +*/ + +/* + * Copyright (C) 2011, 2012 Warren Pratt, NR0V + * + * adapted for QtDSP by (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * The author can be reached by email at + * + * warren@wpratt.com + */ + +#ifndef _QTDSP_WPAGC_H +#define _QTDSP_WPAGC_H + +#include "qtdsp_qComplex.h" +#include "../cusdr_settings.h" + +#include +#include + +#define RINGBUFFERSIZE 19200 +#define SINAVERAGE 0.637f + +#ifdef LOG_WPAGC +# define WPAGC_DEBUG qDebug().nospace() << "WPAGC::\t" +#else +# define WPAGC_DEBUG nullDebug() +#endif + + +class QWPAGC : public QObject { + + Q_OBJECT + +public: + QWPAGC(QObject *parent = 0, int size = 0); + ~QWPAGC(); + + void ProcessAGC(CPX &in, CPX &out, int size); + + qreal getAGCFixedGain(); + qreal getAGCFixedGainDb(); + qreal getAGCMaximumGain_dBm(); + qreal getTauAttack(); + qreal getTauDecay(); + + void setReceiver(int rx); + +public slots: + void setSampleRate(QObject *sender, int value); + void setMode(AGCMode mode); + void setAGCHangEnable(bool value); + void setAGCFixedGain(qreal value); + void setAGCFixedGainDb(qreal value); + void setTauAttack(qreal value); + void setTauDecay(qreal value); + bool setMaximumGain(qreal value); + bool setMaximumGainDb(qreal value); + void setVarGain(qreal value); + void setVarGainDb(qreal value); + void setHangThresh(qreal value); + void setHangTime(qreal value); + void setHangLevelDb(qreal value); + void setAGCThreshDb(qreal filt_high, qreal filt_low, int spec_size, qreal thresh); + void filterChanged(); + + //qreal getAGCThreshDb(qreal filt_high, qreal filt_low, int spec_size); + qreal getHangLevelDb(); + +private: + Settings *set; + + QMutex mutex; + //QVector m_abs_ring; + + AGCMode m_agcMode; + + CPX ring; + CPX buf; + cpx outSample; + + bool m_agcHangEnable; + + int m_size; + int m_receiver; + int m_samplerate; + int m_nTau; + int m_outIndex; + int m_inIndex; + int m_attackBuffersize; + int m_state; + int m_hangCounter; + int m_decayType; + + qreal m_fixedGain; + qreal m_tauAttack; + qreal m_tauDecay; + + qreal m_maxGain; + qreal m_varGain; + qreal m_minVolts; + qreal m_maxInput; + qreal m_out_targ; + qreal m_out_target; + qreal m_inv_max_input; + qreal m_slope_constant; + qreal m_ring_max; + + //qreal absRing[RINGBUFFERSIZE]; + QVector absRing; + + qreal m_attack_mult; + qreal m_decay_mult; + qreal m_volts; + qreal m_save_volts; + qreal m_abs_out_sample; + qreal m_tau_fast_backaverage; + qreal m_fast_backmult; + qreal m_onemfast_backmult; + qreal m_fast_backaverage; + qreal m_tau_fast_decay; + qreal m_fast_decay_mult; + qreal m_pop_ratio; + + qreal m_hang_backaverage; + qreal m_tau_hang_backmult; + qreal m_hang_backmult; + qreal m_onemhang_backmult; + + qreal mult; + + qreal m_hangtime; + qreal m_hangThresh; + qreal m_hangLevel; + + qreal m_tau_hang_decay; + qreal m_hang_decay_mult; + + // average of the absolute value of a sin wave of magnitude 1.0 + qreal SinAverage;// = 0.637; + + void initWcpAGC(); + void loadWcpAGC(); + + bool getAGCHangEnable() { return m_agcHangEnable; } + +private slots: + +signals: + void agcMaximumGainChanged(qreal value); + void agcHangThresholdChanged(qreal value); + void hangLeveldBLineChanged(qreal value); + void minimumVoltageChanged(QObject* sender, int rx, qreal value); + void displayValues(QObject* sender, int rx, qreal minVoltage, qreal hangLevel); +}; + +#endif // _QTDSP_WPAGC_H diff --git a/Source/src/Util/cusdr_buttons.cpp b/Source/src/Util/cusdr_buttons.cpp new file mode 100644 index 0000000..dbfc6c1 --- /dev/null +++ b/Source/src/Util/cusdr_buttons.cpp @@ -0,0 +1,223 @@ +/** +* @file cusdr_buttons.cpp +* @brief Button implementation class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-28 +*/ + +/* + * adapted from: http://www.qtcentre.org/wiki/index.php?title=AeroButton + * Copyright (C) 2008 Jim Daniel + * + * (C) 2010, 2011 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cusdr_buttons.h" + +AeroButton::AeroButton(QWidget *parent) + : QPushButton(parent) + ,m_state(OFF) + ,m_hovered(false) + ,m_pressed(false) + ,m_color(QColor(150, 150, 150)) + ,m_color_on(QColor(85, 210, 250)) + //,m_color_on(QColor(105, 105, 250)) + ,m_highlight(QColor(0x91, 0xeb, 0xff)) + ,m_shadow(Qt::black) + ,m_textcolor(QColor(255, 255, 255)) + ,m_opacity(1.0) + ,m_glass(true) + ,m_roundness(0){} + +AeroButton::AeroButton(const QString &text, QWidget *parent) + : QPushButton(text, parent) + ,m_state(OFF) + ,m_hovered(false) + ,m_pressed(false) + ,m_color(QColor(90, 90, 90)) + ,m_color_on(QColor(85, 210, 250)) + //,m_color_on(QColor(105, 105, 250)) + ,m_highlight(QColor(0x91, 0xeb, 0xff)) + ,m_shadow(Qt::black) + ,m_textcolor(QColor(255, 255, 255)) + ,m_opacity(1.0) + ,m_glass(true) + ,m_roundness(0){} + +AeroButton::AeroButton(const QIcon &icon, const QString &text, QWidget *parent) + : QPushButton(icon, text, parent) + ,m_state(OFF) + ,m_hovered(false) + ,m_pressed(false) + ,m_color(QColor(150, 150, 150)) + ,m_color_on(QColor(85, 210, 250)) + //,m_color_on(QColor(105, 105, 250)) + ,m_highlight(QColor(0x91, 0xeb, 0xff)) + ,m_shadow(Qt::black) + ,m_textcolor(QColor(255, 255, 255)) + ,m_icon(icon) + ,m_opacity(1.0) + ,m_glass(true) + ,m_roundness(0){} + + +AeroButton::~AeroButton(){} + +void AeroButton::paintEvent(QPaintEvent * pe) +{ + Q_UNUSED(pe); + + QPainter painter(this); + painter.setRenderHint(QPainter::Antialiasing); + + //test for state changes + QColor button_color; + if(this->isEnabled()) + { + if (m_state == ON) { + + m_hovered ? button_color = m_highlight : button_color = m_color_on; + } + else if (m_state == OFF) { + + m_hovered ? button_color = m_highlight : button_color = m_color; + } + + if(m_pressed) + { + button_color = m_highlight.darker(250); + } + } + else + { + button_color = QColor(50, 50, 50); + } + + QRect button_rect = this->geometry(); + + //outline + painter.setPen(QPen(QBrush(Qt::black), 2.0)); + QPainterPath outline; + outline.addRoundRect(0, 0, button_rect.width(), button_rect.height(), m_roundness, m_roundness); + painter.setOpacity(m_opacity); + painter.drawPath(outline); + + //gradient + QLinearGradient gradient(0, 0, 0, button_rect.height()); + gradient.setSpread(QGradient::ReflectSpread); + gradient.setColorAt(0.0, button_color); + gradient.setColorAt(0.4, m_shadow); + gradient.setColorAt(0.6, m_shadow); + gradient.setColorAt(1.0, button_color); + + QBrush brush(gradient); + painter.setBrush(brush); + painter.setPen(QPen(QBrush(button_color), 2.0)); + + //main button + QPainterPath painter_path; + painter_path.addRoundRect(1, 1, button_rect.width() - 2, button_rect.height() - 2, m_roundness, m_roundness); + painter.setClipPath(painter_path); + + painter.setOpacity(m_opacity); + painter.drawRoundRect(1, 1, button_rect.width() - 2, button_rect.height() - 2, m_roundness, m_roundness); + + //glass highlight + painter.setBrush(QBrush(Qt::white)); + painter.setPen(QPen(QBrush(Qt::white), 0.01)); + painter.setOpacity(0.30); + if (m_glass) + painter.drawRect(1, 1, button_rect.width() - 2, (button_rect.height() / 2) - 2); + + //text + QString text = this->text(); + if(!text.isNull()) + { + QFont font = this->font(); + painter.setFont(font); + //painter.setPen(Qt::white); + painter.setPen(m_textcolor); + painter.setOpacity(1.0); + painter.drawText(0, 0, button_rect.width(), button_rect.height(), Qt::AlignCenter, text); + } + + //icon + //QIcon icon = this->icon(); + QIcon icon = m_icon; + if(!icon.isNull()) + { + QSize icon_size = this->iconSize(); + QRect icon_position = this->calculateIconPosition(button_rect, icon_size); + //painter.setOpacity(1.0); + m_hovered ? painter.setOpacity(1.0) : painter.setOpacity(0.7); + painter.drawPixmap(icon_position, QPixmap(icon.pixmap(icon_size))); + //painter.drawPixmap(QRect(0, 0, icon_size.width(), icon_size.height()), QPixmap(icon.pixmap(icon_size))); + } +} + +//void AeroButton::setBtnState( BtnState state ) { m_btnState = state; } + +AeroButton::BtnState AeroButton::btnState() const { return m_state; } + +void AeroButton::enterEvent(QEvent * e) +{ + m_hovered = true; + this->repaint(); + + QPushButton::enterEvent(e); +} + +void AeroButton::leaveEvent(QEvent * e) +{ + m_hovered = false; + this->repaint(); + + QPushButton::leaveEvent(e); +} + +void AeroButton::mousePressEvent(QMouseEvent * e) +{ + m_pressed = true; + this->repaint(); + + QPushButton::mousePressEvent(e); +} + +void AeroButton::mouseReleaseEvent(QMouseEvent * e) +{ + m_pressed = false; + this->repaint(); + + QPushButton::mouseReleaseEvent(e); +} + +QRect AeroButton::calculateIconPosition(QRect button_rect, QSize icon_size) +{ + int x = (button_rect.width() / 2) - (icon_size.width() / 2); + int y = (button_rect.height() / 2) - (icon_size.height() / 2); + int width = icon_size.width(); + int height = icon_size.height(); + + QRect icon_position; + icon_position.setX(x); + icon_position.setY(y); + icon_position.setWidth(width); + icon_position.setHeight(height); + + return icon_position; +} diff --git a/Source/src/Util/cusdr_buttons.h b/Source/src/Util/cusdr_buttons.h new file mode 100644 index 0000000..e8a23b0 --- /dev/null +++ b/Source/src/Util/cusdr_buttons.h @@ -0,0 +1,100 @@ +/** +* @file cusdr_buttons.h +* @brief Button implementation header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-28 +*/ + +/* + * adapted from: http://www.qtcentre.org/wiki/index.php?title=AeroButton + * Copyright (C) 2008 Jim Daniel + * + * (C) 2010, 2011 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_BUTTON +#define CUSDR_BUTTON + +//#include +#include +#include + + +class AeroButton : public QPushButton +{ + Q_OBJECT + +public: + AeroButton(QWidget* parent = 0); + AeroButton(const QString &text, QWidget* parent = 0); + AeroButton(const QIcon &icon, const QString &text, QWidget* parent = 0); + + ~AeroButton(); + + enum BtnState { OFF, ON }; + + void setBtnState(BtnState state) { m_state = state; } + BtnState btnState() const; + + void setColor(QColor &color) { m_color = color; } + void setColorOn(QColor &color) { m_color_on = color; } + void setTextColor(QColor &color) { m_textcolor = color; } + void setHighlight(QColor &highlight) { m_highlight = highlight; } + void setShadow(QColor &shadow) { m_shadow = shadow; } + void setGlass(bool glass) { m_glass = glass; } + + //Range: 0.0 [invisible] - 1.0 [opaque] + void setOpacity(qreal opacity) { m_opacity = opacity; } + + //Range: 0 [rectangle] - 99 [oval] + void setRoundness(int roundness) { m_roundness = roundness; } + void setIcon(QIcon icon) { m_icon = icon; } + +protected: + void paintEvent(QPaintEvent *pe); + + void enterEvent(QEvent *e); + void leaveEvent(QEvent *e); + + void mousePressEvent(QMouseEvent *e); + void mouseReleaseEvent(QMouseEvent *e); + +private: + QRect calculateIconPosition(QRect button_rect, QSize icon_size); + +private: + BtnState m_state; + + bool m_hovered; + bool m_pressed; + + QColor m_color; + QColor m_color_on; + QColor m_highlight; + QColor m_shadow; + QColor m_textcolor; + + QIcon m_icon; + + qreal m_opacity; + + bool m_glass; + int m_roundness; +}; + +#endif // CUSDR_BUTTON diff --git a/Source/src/Util/cusdr_colorTriangle.cpp b/Source/src/Util/cusdr_colorTriangle.cpp new file mode 100644 index 0000000..cd59e98 --- /dev/null +++ b/Source/src/Util/cusdr_colorTriangle.cpp @@ -0,0 +1,1523 @@ +/** +* @file cusdr_colorTriangle.cpp +* @brief Color triangle class for cuSDR +*/ + +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#include "cusdr_colorTriangle.h" + +#include +//#include +#include +#include +//#include +//#include +//#include +//#include +//#include +#include +#include +//#include +//#include +//#include +//#include +//#include + +//#include + +/*! \class QtColorTriangle + + \brief The QtColorTriangle class provides a triangular color + selection widget. + + This widget uses the HSV color model, and is therefore useful for + selecting colors by eye. + + The triangle in the center of the widget is used for selecting + saturation and value, and the surrounding circle is used for + selecting hue. + + Use setColor() and color() to set and get the current color. + + \img colortriangle.png +*/ + +/*! \fn QtColorTriangle::colorChanged(const QColor &color) + + Whenever the color triangles color changes this signal is emitted + with the new \a color. +*/ + +const double PI = 3.14159265358979323846264338327950288419717; +const double TWOPI = 2.0*PI; + +/* + Used to store color values in the range 0..255 as doubles. +*/ +struct DoubleColor +{ + double r, g, b; + + DoubleColor() : r(0.0), g(0.0), b(0.0) {} + DoubleColor(double red, double green, double blue) : r(red), g(green), b(blue) {} + DoubleColor(const DoubleColor &c) : r(c.r), g(c.g), b(c.b) {} +}; + +/* + Used to store pairs of DoubleColor and DoublePoint in one structure. +*/ +struct Vertex { + DoubleColor color; + QPointF point; + + Vertex(const DoubleColor &c, const QPointF &p) : color(c), point(p) {} + Vertex(const QColor &c, const QPointF &p) + : color(DoubleColor((double) c.red(), (double) c.green(), + (double) c.blue())), point(p) {} +}; + +/*! \internal + +Swaps the Vertex at *a with the one at *b. + */ +static void swap(Vertex **a, Vertex **b) +{ + Vertex *tmp = *a; + *a = *b; + *b = tmp; +} + +/*! + Constructs a color triangle widget with the given \a parent. +*/ +QtColorTriangle::QtColorTriangle(QWidget *parent) + : QWidget(parent), bg(sizeHint(), QImage::Format_RGB32), selMode(Idle) +{ + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + setFocusPolicy(Qt::StrongFocus); + + mustGenerateBackground = true; + + QColor tmp; + tmp.setHsv(76, 184, 206); + setColor(tmp); +} + +/*! + Destructs the color triangle. +*/ +QtColorTriangle::~QtColorTriangle() +{ +} + +/*! + \internal + + Generates the first background image. +*/ +void QtColorTriangle::polish() +{ + outerRadius = (contentsRect().width() - 1) / 2; + if ((contentsRect().height() - 1) / 2 < outerRadius) + outerRadius = (contentsRect().height() - 1) / 2; + + penWidth = (int) qFloor(outerRadius / 50.0); + ellipseSize = (int) qFloor(outerRadius / 12.5); + + double cx = (double) contentsRect().center().x(); + double cy = (double) contentsRect().center().y(); + + pa = QPointF(cx + (qCos(a) * (outerRadius - (outerRadius / 5.0))), + cy - (qSin(a) * (outerRadius - (outerRadius / 5.0)))); + pb = QPointF(cx + (qCos(b) * (outerRadius - (outerRadius / 5.0))), + cy - (qSin(b) * (outerRadius - (outerRadius / 5.0)))); + pc = QPointF(cx + (qCos(c) * (outerRadius - (outerRadius / 5.0))), + cy - (qSin(c) * (outerRadius - (outerRadius / 5.0)))); + pd = QPointF(cx + (qCos(a) * (outerRadius - (outerRadius / 10.0))), + cy - (qSin(a) * (outerRadius - (outerRadius / 10.0)))); + + // Find the current position of the selector + selectorPos = pointFromColor(curColor); + + update(); +} + +/*! \reimp + */ +QSize QtColorTriangle::sizeHint() const +{ + return QSize(80, 80); +} + +/*! + Forces the triangle widget to always be square. Returns the value + \a w. +*/ +int QtColorTriangle::heightForWidth(int w) const +{ + return w; +} + +/*! + \internal + + Generates a new static background image. This function is called + initially, and in resizeEvent. +*/ +void QtColorTriangle::genBackground() +{ + // Find the inner radius of the hue donut. + double innerRadius = outerRadius - outerRadius / 5; + + // Create an image of the same size as the contents rect. + bg = QImage(contentsRect().size(), QImage::Format_RGB32); + QPainter p(&bg); + p.setRenderHint(QPainter::Antialiasing); + //p.fillRect(bg.rect(), QColor::fromRgb(190,206,188)); + p.fillRect(bg.rect(), QColor::fromRgb(10,10,10)); + + //p.setPen(QColor::fromRgb(59,90,74)); + p.setPen(QColor::fromRgb(0,0,0)); + p.drawRect(bg.rect()); + + QConicalGradient gradient(bg.rect().center(), 90); + QColor color; + for (double i = 0; i <= 1.0; i += 0.1) { +#if QT_VERSION < 0x040100 + color.setHsv(int(i * 360.0), 255, 255); +#else + color.setHsv(int(360.0 - (i * 360.0)), 255, 255); +#endif + gradient.setColorAt(i, color); + } + + QRectF innerRadiusRect(bg.rect().center().x() - innerRadius, bg.rect().center().y() - innerRadius, + innerRadius * 2 + 1, innerRadius * 2 + 1); + QRectF outerRadiusRect(bg.rect().center().x() - outerRadius, bg.rect().center().y() - outerRadius, + outerRadius * 2 + 1, outerRadius * 2 + 1); + QPainterPath path; + path.addEllipse(innerRadiusRect); + path.addEllipse(outerRadiusRect); + + p.save(); + p.setClipPath(path); + p.fillRect(bg.rect(), gradient); + p.restore(); + + double penThickness = bg.width() / 400.0; + for (int f = 0; f <= 5760; f += 20) { + int value = int((0.5 + cos(((f - 1800) / 5760.0) * TWOPI) / 2) * 255.0); + + color.setHsv(int((f / 5760.0) * 360.0), 128 + (255 - value)/2, 255 - (255 - value)/4); + p.setPen(QPen(color, penThickness)); + p.drawArc(innerRadiusRect, 1440 - f, 20); + + color.setHsv(int((f / 5760.0) * 360.0), 128 + value/2, 255 - value/4); + p.setPen(QPen(color, penThickness)); + p.drawArc(outerRadiusRect, 2880 - 1440 - f, 20); + } + return; +} + +/*! + \internal + + Selects new hue or saturation/value values, depending on where the + mouse button was pressed initially. +*/ +void QtColorTriangle::mouseMoveEvent(QMouseEvent *e) +{ + if ((e->buttons() & Qt::LeftButton) == 0) + return; + + QPointF depos((double) e->pos().x(), (double) e->pos().y()); + bool newColor = false; + + if (selMode == SelectingHue) { + // If selecting hue, find the new angles for the points a,b,c + // of the triangle. The following update() will then redraw + // the triangle. + a = angleAt(depos, contentsRect()); + b = a + TWOPI / 3.0; + c = b + TWOPI / 3.0; + if (b > TWOPI) b -= TWOPI; + if (c > TWOPI) c -= TWOPI; + + double am = a - PI/2; + if (am < 0) am += TWOPI; + + curHue = 360 - (int) (((am) * 360.0) / TWOPI); + int h,s,v; + curColor.getHsv(&h, &s, &v); + + if (curHue != h) { + newColor = true; + curColor.setHsv(curHue, s, v); + } + + double cx = (double) contentsRect().center().x(); + double cy = (double) contentsRect().center().y(); + + pa = QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 5.0)))); + pb = QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(b) * (outerRadius - (outerRadius / 5.0)))); + pc = QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(c) * (outerRadius - (outerRadius / 5.0)))); + pd = QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 10.0)))); + + selectorPos = pointFromColor(curColor); + } else { + Vertex aa(Qt::black, pa); + Vertex bb(Qt::black, pb); + Vertex cc(Qt::black, pc); + + Vertex *p1 = &aa; + Vertex *p2 = &bb; + Vertex *p3 = &cc; + if (p1->point.y() > p2->point.y()) swap(&p1, &p2); + if (p1->point.y() > p3->point.y()) swap(&p1, &p3); + if (p2->point.y() > p3->point.y()) swap(&p2, &p3); + + selectorPos = movePointToTriangle(depos.x(), depos.y(), aa, bb, cc); + QColor col = colorFromPoint(selectorPos); + if (col != curColor) { + // Ensure that hue does not change when selecting + // saturation and value. + int h,s,v; + col.getHsv(&h, &s, &v); + curColor.setHsv(curHue, s, v); + newColor = true; + } + } + + if (newColor) + emit colorChanged(curColor); + + update(); +} + +/*! + \internal + + When the left mouse button is pressed, this function determines + what part of the color triangle the cursor is, and from that it + initiates either selecting the hue (outside the triangle's area) + or the saturation/value (inside the triangle's area). +*/ +void QtColorTriangle::mousePressEvent(QMouseEvent *e) +{ + // Only respond to the left mouse button. + if (e->button() != Qt::LeftButton) + return; + + QPointF depos((double) e->pos().x(), (double) e->pos().y()); + double rad = radiusAt(depos, contentsRect()); + bool newColor = false; + + // As in mouseMoveEvent, either find the a,b,c angles or the + // radian position of the selector, then order an update. + if (rad > (outerRadius - (outerRadius / 5))) { + selMode = SelectingHue; + + a = angleAt(depos, contentsRect()); + b = a + TWOPI / 3.0; + c = b + TWOPI / 3.0; + if (b > TWOPI) b -= TWOPI; + if (c > TWOPI) c -= TWOPI; + + double am = a - PI/2; + if (am < 0) am += TWOPI; + + curHue = 360 - (int) ((am * 360.0) / TWOPI); + int h,s,v; + curColor.getHsv(&h, &s, &v); + + if (h != curHue) { + newColor = true; + curColor.setHsv(curHue, s, v); + } + + double cx = (double) contentsRect().center().x(); + double cy = (double) contentsRect().center().y(); + + pa = QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 5.0)))); + pb = QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(b) * (outerRadius - (outerRadius / 5.0)))); + pc = QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(c) * (outerRadius - (outerRadius / 5.0)))); + pd = QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 10.0)))); + + selectorPos = pointFromColor(curColor); + emit colorChanged(curColor); + } else { + selMode = SelectingSatValue; + + Vertex aa(Qt::black, pa); + Vertex bb(Qt::black, pb); + Vertex cc(Qt::black, pc); + + Vertex *p1 = &aa; + Vertex *p2 = &bb; + Vertex *p3 = &cc; + if (p1->point.y() > p2->point.y()) swap(&p1, &p2); + if (p1->point.y() > p3->point.y()) swap(&p1, &p3); + if (p2->point.y() > p3->point.y()) swap(&p2, &p3); + + selectorPos = movePointToTriangle(depos.x(), depos.y(), aa, bb, cc); + QColor col = colorFromPoint(selectorPos); + if (col != curColor) { + curColor = col; + newColor = true; + } + } + + if (newColor) + emit colorChanged(curColor); + + update(); +} + +/*! + \internal + + Stops selecting of colors with the mouse. +*/ +void QtColorTriangle::mouseReleaseEvent(QMouseEvent *e) +{ + if (e->button() == Qt::LeftButton) + selMode = Idle; +} + +/*! + \internal +*/ +void QtColorTriangle::keyPressEvent(QKeyEvent *e) +{ + switch (e->key()) { + case Qt::Key_Left: { + --curHue; + if (curHue < 0) curHue += 360; + int h,s,v; + curColor.getHsv(&h, &s, &v); + QColor tmp; + tmp.setHsv(curHue, s, v); + setColor(tmp); + } + break; + case Qt::Key_Right: { + ++curHue; + if (curHue > 359) curHue -= 360; + int h,s,v; + curColor.getHsv(&h, &s, &v); + QColor tmp; + tmp.setHsv(curHue, s, v); + setColor(tmp); + } + break; + case Qt::Key_Up: { + int h,s,v; + curColor.getHsv(&h, &s, &v); + QColor tmp; + if (e->modifiers() & Qt::ShiftModifier) { + if (s > 5) s -= 5; + else s = 0; + } else { + if (v > 5) v -= 5; + else v = 0; + } + tmp.setHsv(curHue, s, v); + setColor(tmp); + } + break; + case Qt::Key_Down: { + int h,s,v; + curColor.getHsv(&h, &s, &v); + QColor tmp; + if (e->modifiers() & Qt::ShiftModifier) { + if (s < 250) s += 5; + else s = 255; + } else { + if (v < 250) v += 5; + else v = 255; + } + tmp.setHsv(curHue, s, v); + setColor(tmp); + } + break; + }; +} + +/*! + \internal + + Regenerates the background image and sends an update. +*/ +void QtColorTriangle::resizeEvent(QResizeEvent *) +{ + outerRadius = (contentsRect().width() - 10) / 2; + if ((contentsRect().height() - 1) / 2 < outerRadius) + outerRadius = (contentsRect().height() - 10) / 2; + + penWidth = (int) floor(outerRadius / 50.0); + ellipseSize = (int) floor(outerRadius / 12.5); + + double cx = (double) contentsRect().center().x(); + double cy = (double) contentsRect().center().y(); + + pa = QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 5.0)))); + pb = QPointF(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(b) * (outerRadius - (outerRadius / 5.0)))); + pc = QPointF(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(c) * (outerRadius - (outerRadius / 5.0)))); + pd = QPointF(cx + (cos(a) * (outerRadius - (outerRadius / 10.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 10.0)))); + + // Find the current position of the selector + selectorPos = pointFromColor(curColor); + + mustGenerateBackground = true; + update(); +} + +/*! \reimp + +First copies a background image of the hue donut and its + background color onto the frame, then draws the color triangle, + and finally the selectors. +*/ +void QtColorTriangle::paintEvent(QPaintEvent *e) +{ + QPainter p(this); + if (e->rect().intersects(contentsRect())) + p.setClipRegion(e->region().intersected(contentsRect())); + if (mustGenerateBackground) { + genBackground(); + mustGenerateBackground = false; + } + + // Blit the static generated background with the hue gradient onto + // the double buffer. + QImage buf = bg.copy(); + + // Draw the trigon + int h,s,v; + curColor.getHsv(&h, &s, &v); + + // Find the color with only the hue, and max value and saturation + QColor hueColor; + hueColor.setHsv(curHue, 255, 255); + + // Draw the triangle + drawTrigon(&buf, pa, pb, pc, hueColor); + + // Slow step: convert the image to a pixmap + QPixmap pix = QPixmap::fromImage(buf); + QPainter painter(&pix); + painter.setRenderHint(QPainter::Antialiasing); + + // Draw an outline of the triangle + QColor halfAlpha(0, 0, 0, 128); + painter.setPen(QPen(halfAlpha, 0)); + painter.drawLine(pa, pb); + painter.drawLine(pb, pc); + painter.drawLine(pc, pa); + + int ri, gi, bi; + hueColor.getRgb(&ri, &gi, &bi); + if ((ri * 30) + (gi * 59) + (bi * 11) > 12800) + painter.setPen(QPen(Qt::black, penWidth)); + else + painter.setPen(QPen(Qt::white, penWidth)); + painter.drawEllipse((int) (pd.x() - ellipseSize / 2.0), + (int) (pd.y() - ellipseSize / 2.0), + ellipseSize, ellipseSize); + + curColor.getRgb(&ri, &gi, &bi); + + // Find a color for painting the selector based on the brightness + // value of the color. + if ((ri * 30) + (gi * 59) + (bi * 11) > 12800) + painter.setPen(QPen(Qt::black, penWidth)); + else + painter.setPen(QPen(Qt::white, penWidth)); + + // Draw the selector ellipse. + painter.drawEllipse(QRectF(selectorPos.x() - ellipseSize / 2.0, + selectorPos.y() - ellipseSize / 2.0, + ellipseSize + 0.5, ellipseSize + 0.5)); + + // Blit + p.drawPixmap(contentsRect().topLeft(), pix); +} + +/*! \internal + +Draws a trigon (polygon with three corners \a pa, \a pb and \a pc + and three edges), using \a painter. + + Fills the trigon with a gradient, where the \a pa point has the + color \a color, \a pb is black and \a bc is white. Bilinear + gradient. +*/ +void QtColorTriangle::drawTrigon(QImage *buf, const QPointF &pa, + const QPointF &pb, const QPointF &pc, + const QColor &color) +{ + // Create three Vertex objects. A Vertex contains a double-point + // coordinate and a color. + // pa is the tip of the arrow + // pb is the black corner + // pc is the white corner + Vertex aa(color, pa); + Vertex bb(Qt::black, pb); + Vertex cc(Qt::white, pc); + + // Sort. Make p1 above p2, which is above p3 (using y coordinate). + // Bubble sorting is fastest here. + Vertex *p1 = &aa; + Vertex *p2 = &bb; + Vertex *p3 = &cc; + if (p1->point.y() > p2->point.y()) swap(&p1, &p2); + if (p1->point.y() > p3->point.y()) swap(&p1, &p3); + if (p2->point.y() > p3->point.y()) swap(&p2, &p3); + + // All the three y deltas are >= 0 + double p1p2ydist = p2->point.y() - p1->point.y(); + double p1p3ydist = p3->point.y() - p1->point.y(); + double p2p3ydist = p3->point.y() - p2->point.y(); + double p1p2xdist = p2->point.x() - p1->point.x(); + double p1p3xdist = p3->point.x() - p1->point.x(); + double p2p3xdist = p3->point.x() - p2->point.x(); + + // The first x delta decides wether we have a lefty or a righty + // trigon. + bool lefty = p1p2xdist < 0; + + // Left and right colors and X values. The key in this map is the + // y values. Our goal is to fill these structures with all the + // information needed to do a single pass top-to-bottom, + // left-to-right drawing of the trigon. + QVarLengthArray leftColors; + QVarLengthArray rightColors; + QVarLengthArray leftX; + QVarLengthArray rightX; + + leftColors.resize(int(floor(p3->point.y() + 1))); + rightColors.resize(int(floor(p3->point.y() + 1))); + leftX.resize(int(floor(p3->point.y() + 1))); + rightX.resize(int(floor(p3->point.y() + 1))); + + // Scan longy - find all left and right colors and X-values for + // the tallest edge (p1-p3). + DoubleColor source; + DoubleColor dest; + double r, g, b; + double rdelta, gdelta, bdelta; + double x; + double xdelta; + int y1, y2; + + // Initialize with known values + x = p1->point.x(); + source = p1->color; + dest = p3->color; + r = source.r; + g = source.g; + b = source.b; + y1 = (int) floor(p1->point.y()); + y2 = (int) floor(p3->point.y()); + + // Find slopes (notice that if the y dists are 0, we don't care + // about the slopes) + xdelta = p1p3ydist == 0.0 ? 0.0 : p1p3xdist / p1p3ydist; + rdelta = p1p3ydist == 0.0 ? 0.0 : (dest.r - r) / p1p3ydist; + gdelta = p1p3ydist == 0.0 ? 0.0 : (dest.g - g) / p1p3ydist; + bdelta = p1p3ydist == 0.0 ? 0.0 : (dest.b - b) / p1p3ydist; + + // Calculate gradients using linear approximation + int y; + for (y = y1; y < y2; ++y) { + if (lefty) { + rightColors[y] = DoubleColor(r, g, b); + rightX[y] = x; + } else { + leftColors[y] = DoubleColor(r, g, b); + leftX[y] = x; + } + + r += rdelta; + g += gdelta; + b += bdelta; + x += xdelta; + } + + // Scan top shorty - find all left and right colors and x-values + // for the topmost of the two not-tallest short edges. + x = p1->point.x(); + source = p1->color; + dest = p2->color; + r = source.r; + g = source.g; + b = source.b; + y1 = (int) floor(p1->point.y()); + y2 = (int) floor(p2->point.y()); + + // Find slopes (notice that if the y dists are 0, we don't care + // about the slopes) + xdelta = p1p2ydist == 0.0 ? 0.0 : p1p2xdist / p1p2ydist; + rdelta = p1p2ydist == 0.0 ? 0.0 : (dest.r - r) / p1p2ydist; + gdelta = p1p2ydist == 0.0 ? 0.0 : (dest.g - g) / p1p2ydist; + bdelta = p1p2ydist == 0.0 ? 0.0 : (dest.b - b) / p1p2ydist; + + // Calculate gradients using linear approximation + for (y = y1; y < y2; ++y) { + if (lefty) { + leftColors[y] = DoubleColor(r, g, b); + leftX[y] = x; + } else { + rightColors[y] = DoubleColor(r, g, b); + rightX[y] = x; + } + + r += rdelta; + g += gdelta; + b += bdelta; + x += xdelta; + } + + // Scan bottom shorty - find all left and right colors and + // x-values for the bottommost of the two not-tallest short edges. + x = p2->point.x(); + source = p2->color; + dest = p3->color; + r = source.r; + g = source.g; + b = source.b; + y1 = (int) floor(p2->point.y()); + y2 = (int) floor(p3->point.y()); + + // Find slopes (notice that if the y dists are 0, we don't care + // about the slopes) + xdelta = p2p3ydist == 0.0 ? 0.0 : p2p3xdist / p2p3ydist; + rdelta = p2p3ydist == 0.0 ? 0.0 : (dest.r - r) / p2p3ydist; + gdelta = p2p3ydist == 0.0 ? 0.0 : (dest.g - g) / p2p3ydist; + bdelta = p2p3ydist == 0.0 ? 0.0 : (dest.b - b) / p2p3ydist; + + // Calculate gradients using linear approximation + for (y = y1; y < y2; ++y) { + if (lefty) { + leftColors[y] = DoubleColor(r, g, b); + leftX[y] = x; + } else { + rightColors[y] = DoubleColor(r, g, b); + rightX[y] = x; + } + + r += rdelta; + g += gdelta; + b += bdelta; + x += xdelta; + } + + // Inner loop. For each y in the left map of x-values, draw one + // line from left to right. + const int p3yfloor = int(floor(p3->point.y())); + for (int y = int(floor(p1->point.y())); y < p3yfloor; ++y) { + double lx = leftX[y]; + double rx = rightX[y]; + + int lxi = (int) floor(lx); + int rxi = (int) floor(rx); + DoubleColor rc = rightColors[y]; + DoubleColor lc = leftColors[y]; + + // if the xdist is 0, don't draw anything. + double xdist = rx - lx; + if (xdist != 0.0) { + double r = lc.r; + double g = lc.g; + double b = lc.b; + double rdelta = (rc.r - r) / xdist; + double gdelta = (rc.g - g) / xdist; + double bdelta = (rc.b - b) / xdist; + + QRgb *scanline = reinterpret_cast(buf->scanLine(y)); + scanline += lxi; + + // Inner loop 2. Draws the line from left to right. + for (int i = lxi; i < rxi; ++i) { + *scanline++ = qRgb((int) r, (int) g, (int) b); + r += rdelta; + g += gdelta; + b += bdelta; + } + } + } +} + +/*! \internal + +Sets the color of the triangle to \a col. + */ +void QtColorTriangle::setColor(const QColor &col) +{ + if (col == curColor) + return; + + curColor = col; + + int h, s, v; + curColor.getHsv(&h, &s, &v); + + // Never use an invalid hue to display colors + if (h != -1) + curHue = h; + + a = (((360 - curHue) * TWOPI) / 360.0); + a += PI / 2.0; + if (a > TWOPI) a -= TWOPI; + + b = a + TWOPI/3; + c = b + TWOPI/3; + + if (b > TWOPI) b -= TWOPI; + if (c > TWOPI) c -= TWOPI; + + double cx = (double) contentsRect().center().x(); + double cy = (double) contentsRect().center().y(); + double innerRadius = outerRadius - (outerRadius / 5.0); + double pointerRadius = outerRadius - (outerRadius / 10.0); + + pa = QPointF(cx + (cos(a) * innerRadius), cy - (sin(a) * innerRadius)); + pb = QPointF(cx + (cos(b) * innerRadius), cy - (sin(b) * innerRadius)); + pc = QPointF(cx + (cos(c) * innerRadius), cy - (sin(c) * innerRadius)); + pd = QPointF(cx + (cos(a) * pointerRadius), cy - (sin(a) * pointerRadius)); + + selectorPos = pointFromColor(curColor); + update(); + + emit colorChanged(curColor); +} + +/*! \internal + +Returns the current color of the triangle. + */ +QColor QtColorTriangle::color() const +{ + return curColor; +} + +/*! + \internal + + Returns the distance from \a pos to the center of \a rect. +*/ +double QtColorTriangle::radiusAt(const QPointF &pos, const QRect &rect) const +{ + double mousexdist = pos.x() - (double) rect.center().x(); + double mouseydist = pos.y() - (double) rect.center().y(); + return sqrt(mousexdist * mousexdist + mouseydist * mouseydist); +} + +/*! + \internal + + With origin set to the center of \a rect, this function returns + the angle in radians between the line that starts at (0,0) and + ends at (1,0) and the line that stars at (0,0) and ends at \a pos. +*/ +double QtColorTriangle::angleAt(const QPointF &pos, const QRect &rect) const +{ + double mousexdist = pos.x() - (double) rect.center().x(); + double mouseydist = pos.y() - (double) rect.center().y(); + double mouserad = sqrt(mousexdist * mousexdist + mouseydist * mouseydist); + if (mouserad == 0.0) + return 0.0; + + double angle = acos(mousexdist / mouserad); + if (mouseydist >= 0) + angle = TWOPI - angle; + + return angle; +} + +/*! \internal + +Returns a * a. + */ +inline double qsqr(double a) +{ + return a * a; +} + +/*! \internal + +Returns the length of the vector (x,y). + */ +inline double vlen(double x, double y) +{ + return sqrt(qsqr(x) + qsqr(y)); +} + +/*! \internal + +Returns the vector product of (x1,y1) and (x2,y2). + */ +inline double vprod(double x1, double y1, double x2, double y2) +{ + return x1 * x2 + y1 * y2; +} + +/*! \internal + +Returns true if the point cos(p),sin(p) is on the arc between + cos(a1),sin(a1) and cos(a2),sin(a2); otherwise returns false. +*/ +bool angleBetweenAngles(double p, double a1, double a2) +{ + if (a1 > a2) { + a2 += TWOPI; + if (p < PI) p += TWOPI; + } + + return p >= a1 && p < a2; +} + +/*! \internal + + A line from a to b is one of several lines in an equilateral + polygon, and they are drawn counter clockwise. This line therefore + has one side facing in and one facing out of the polygon. This + function determines wether (x,y) is on the inside or outside of + the given line, defined by the "from" coordinate (ax,ay) and the + "to" coordinate (bx,by). + + The point (px,py) is the intersection between the a-b line and the + perpendicular projection of (x,y) onto that line. + + Returns true if (x,y) is above the line; otherwise returns false. + + If ax and bx are equal and ay and by are equal (line is a point), + this function will return true if (x,y) is equal to this point. +*/ +static bool pointAbovePoint(double x, double y, double px, double py, + double ax, double ay, double bx, double by) +{ + bool result = false; + + if (floor(ax) > floor(bx)) { + if (floor(ay) < floor(by)) { + // line is draw upright-to-downleft + if (floor(x) < floor(px) || floor(y) < floor(py)) + result = true; + } else if (floor(ay) > floor(by)) { + // line is draw downright-to-upleft + if (floor(x) > floor(px) || floor(y) < floor(py)) + result = true; + } else { + // line is flat horizontal + if (y < ay) result = true; + } + } else if (floor(ax) < floor(bx)) { + if (floor(ay) < floor(by)) { + // line is draw upleft-to-downright + if (floor(x) < floor(px) || floor(y) > floor(py)) + result = true; + } else if (floor(ay) > floor(by)) { + // line is draw downleft-to-upright + if (floor(x) > floor(px) || floor(y) > floor(py)) + result = true; + } else { + // line is flat horizontal + if (y > ay) + result = true; + } + } else { + // line is vertical + if (floor(ay) < floor(by)) { + if (x < ax) result = true; + } else if (floor(ay) > floor(by)) { + if (x > ax) result = true; + } else { + if (!(x == ax && y == ay)) + result = true; + } + } + + return result; +} + +/*! \internal + +if (ax,ay) to (bx,by) describes a line, and (x,y) is a point on + that line, returns -1 if (x,y) is outside the (ax,ay) bounds, 1 if + it is outside the (bx,by) bounds and 0 if (x,y) is within (ax,ay) + and (bx,by). +*/ +static int pointInLine(double x, double y, double ax, double ay, + double bx, double by) +{ + if (ax > bx) { + if (ay < by) { + // line is draw upright-to-downleft + + // if (x,y) is in on or above the upper right point, + // return -1. + if (y <= ay && x >= ax) + return -1; + + // if (x,y) is in on or below the lower left point, + // return 1. + if (y >= by && x <= bx) + return 1; + } else { + // line is draw downright-to-upleft + + // If the line is flat, only use the x coordinate. + if (floor(ay) == floor(by)) { + // if (x is to the right of the rightmost point, + // return -1. otherwise if x is to the left of the + // leftmost point, return 1. + if (x >= ax) + return -1; + else if (x <= bx) + return 1; + } else { + // if (x,y) is on or below the lower right point, + // return -1. + if (y >= ay && x >= ax) + return -1; + + // if (x,y) is on or above the upper left point, + // return 1. + if (y <= by && x <= bx) + return 1; + } + } + } else { + if (ay < by) { + // line is draw upleft-to-downright + + // If (x,y) is on or above the upper left point, return + // -1. + if (y <= ay && x <= ax) + return -1; + + // If (x,y) is on or below the lower right point, return + // 1. + if (y >= by && x >= bx) + return 1; + } else { + // line is draw downleft-to-upright + + // If the line is flat, only use the x coordinate. + if (floor(ay) == floor(by)) { + if (x <= ax) + return -1; + else if (x >= bx) + return 1; + } else { + // If (x,y) is on or below the lower left point, return + // -1. + if (y >= ay && x <= ax) + return -1; + + // If (x,y) is on or above the upper right point, return + // 1. + if (y <= by && x >= bx) + return 1; + } + } + } + + // No tests proved that (x,y) was outside [(ax,ay),(bx,by)], so we + // assume it's inside the line's bounds. + return 0; +} + +/*! \internal + + \a a, \a b and \a c are corner points of an equilateral triangle. + (\a x,\a y) is an arbitrary point inside or outside this triangle. + + If (x,y) is inside the triangle, this function returns the double + point (x,y). + + Otherwise, the intersection of the perpendicular projection of + (x,y) onto the closest triangle edge is returned, unless this + intersection is outside the triangle's bounds, in which case the + corner closest to the intersection is returned instead. + + Yes, it's trigonometry. +*/ +QPointF QtColorTriangle::movePointToTriangle(double x, double y, const Vertex &a, + const Vertex &b, const Vertex &c) const +{ + // Let v1A be the vector from (x,y) to a. + // Let v2A be the vector from a to b. + // Find the angle alphaA between v1A and v2A. + double v1xA = x - a.point.x(); + double v1yA = y - a.point.y(); + double v2xA = b.point.x() - a.point.x(); + double v2yA = b.point.y() - a.point.y(); + double vpA = vprod(v1xA, v1yA, v2xA, v2yA); + double cosA = vpA / (vlen(v1xA, v1yA) * vlen(v2xA, v2yA)); + double alphaA = acos(cosA); + + // Let v1B be the vector from x to b. + // Let v2B be the vector from b to c. + double v1xB = x - b.point.x(); + double v1yB = y - b.point.y(); + double v2xB = c.point.x() - b.point.x(); + double v2yB = c.point.y() - b.point.y(); + double vpB = vprod(v1xB, v1yB, v2xB, v2yB); + double cosB = vpB / (vlen(v1xB, v1yB) * vlen(v2xB, v2yB)); + double alphaB = acos(cosB); + + // Let v1C be the vector from x to c. + // Let v2C be the vector from c back to a. + double v1xC = x - c.point.x(); + double v1yC = y - c.point.y(); + double v2xC = a.point.x() - c.point.x(); + double v2yC = a.point.y() - c.point.y(); + double vpC = vprod(v1xC, v1yC, v2xC, v2yC); + double cosC = vpC / (vlen(v1xC, v1yC) * vlen(v2xC, v2yC)); + double alphaC = acos(cosC); + + // Find the radian angles between the (1,0) vector and the points + // A, B, C and (x,y). Use this information to determine which of + // the edges we should project (x,y) onto. + double angleA = angleAt(a.point, contentsRect()); + double angleB = angleAt(b.point, contentsRect()); + double angleC = angleAt(c.point, contentsRect()); + double angleP = angleAt(QPointF(x, y), contentsRect()); + + // If (x,y) is in the a-b area, project onto the a-b vector. + if (angleBetweenAngles(angleP, angleA, angleB)) { + // Find the distance from (x,y) to a. Then use the slope of + // the a-b vector with this distance and the angle between a-b + // and a-(x,y) to determine the point of intersection of the + // perpendicular projection from (x,y) onto a-b. + double pdist = sqrt(qsqr(x - a.point.x()) + qsqr(y - a.point.y())); + + // the length of all edges is always > 0 + double p0x = a.point.x() + ((b.point.x() - a.point.x()) / vlen(v2xB, v2yB)) * cos(alphaA) * pdist; + double p0y = a.point.y() + ((b.point.y() - a.point.y()) / vlen(v2xB, v2yB)) * cos(alphaA) * pdist; + + // If (x,y) is above the a-b line, which basically means it's + // outside the triangle, then return its projection onto a-b. + if (pointAbovePoint(x, y, p0x, p0y, a.point.x(), a.point.y(), b.point.x(), b.point.y())) { + // If the projection is "outside" a, return a. If it is + // outside b, return b. Otherwise return the projection. + int n = pointInLine(p0x, p0y, a.point.x(), a.point.y(), b.point.x(), b.point.y()); + if (n < 0) + return a.point; + else if (n > 0) + return b.point; + + return QPointF(p0x, p0y); + } + } else if (angleBetweenAngles(angleP, angleB, angleC)) { + // If (x,y) is in the b-c area, project onto the b-c vector. + double pdist = sqrt(qsqr(x - b.point.x()) + qsqr(y - b.point.y())); + + // the length of all edges is always > 0 + double p0x = b.point.x() + ((c.point.x() - b.point.x()) / vlen(v2xC, v2yC)) * cos(alphaB) * pdist; + double p0y = b.point.y() + ((c.point.y() - b.point.y()) / vlen(v2xC, v2yC)) * cos(alphaB) * pdist; + + if (pointAbovePoint(x, y, p0x, p0y, b.point.x(), b.point.y(), c.point.x(), c.point.y())) { + int n = pointInLine(p0x, p0y, b.point.x(), b.point.y(), c.point.x(), c.point.y()); + if (n < 0) + return b.point; + else if (n > 0) + return c.point; + return QPointF(p0x, p0y); + } + } else if (angleBetweenAngles(angleP, angleC, angleA)) { + // If (x,y) is in the c-a area, project onto the c-a vector. + double pdist = sqrt(qsqr(x - c.point.x()) + qsqr(y - c.point.y())); + + // the length of all edges is always > 0 + double p0x = c.point.x() + ((a.point.x() - c.point.x()) / vlen(v2xA, v2yA)) * cos(alphaC) * pdist; + double p0y = c.point.y() + ((a.point.y() - c.point.y()) / vlen(v2xA, v2yA)) * cos(alphaC) * pdist; + + if (pointAbovePoint(x, y, p0x, p0y, c.point.x(), c.point.y(), a.point.x(), a.point.y())) { + int n = pointInLine(p0x, p0y, c.point.x(), c.point.y(), a.point.x(), a.point.y()); + if (n < 0) + return c.point; + else if (n > 0) + return a.point; + return QPointF(p0x, p0y); + } + } + + // (x,y) is inside the triangle (inside a-b, b-c and a-c). + return QPointF(x, y); +} + +/*! \internal + + Given the color \a col, this function determines the point in the + equilateral triangle defined with (pa, pb, pc) that displays this + color. The function assumes the color at pa has a hue equal to the + hue of \a col, and that pb is black and pc is white. + + In this certain type of triangle, we observe that saturation grows + from the black-color edge towards the black-white edge. The value + grows from the black corner towards the white-color edge. Using + the intersection of the saturation and value points on the three + edges, we are able to determine the point with the same saturation + and value as \a col. +*/ +QPointF QtColorTriangle::pointFromColor(const QColor &col) const +{ + // Simplifications for the corner cases. + if (col == Qt::black) + return pb; + else if (col == Qt::white) + return pc; + + // Find the x and y slopes + double ab_deltax = pb.x() - pa.x(); + double ab_deltay = pb.y() - pa.y(); + double bc_deltax = pc.x() - pb.x(); + double bc_deltay = pc.y() - pb.y(); + double ac_deltax = pc.x() - pa.x(); + double ac_deltay = pc.y() - pa.y(); + + // Extract the h,s,v values of col. + int hue,sat,val; + col.getHsv(&hue, &sat, &val); + + // Find the line that passes through the triangle where the value + // is equal to our color's value. + double p1 = pa.x() + (ab_deltax * (double) (255 - val)) / 255.0; + double q1 = pa.y() + (ab_deltay * (double) (255 - val)) / 255.0; + double p2 = pb.x() + (bc_deltax * (double) val) / 255.0; + double q2 = pb.y() + (bc_deltay * (double) val) / 255.0; + + // Find the line that passes through the triangle where the + // saturation is equal to our color's value. + double p3 = pa.x() + (ac_deltax * (double) (255 - sat)) / 255.0; + double q3 = pa.y() + (ac_deltay * (double) (255 - sat)) / 255.0; + double p4 = pb.x(); + double q4 = pb.y(); + + // Find the intersection between these lines. + double x = 0; + double y = 0; + if (p1 != p2) { + double a = (q2 - q1) / (p2 - p1); + double c = (q4 - q3) / (p4 - p3); + double b = q1 - a * p1; + double d = q3 - c * p3; + + x = (d - b) / (a - c); + y = a * x + b; + } + else { + x = p1; + y = q3 + (x - p3) * (q4 - q3) / (p4 - p3); + } + + return QPointF(x, y); +} + +/*! \internal + + Determines the color in the color triangle at the point \a p. Uses + linear interpolation to find the colors to the left and right of + \a p, then uses the same technique to find the color at \a p using + these two colors. +*/ +QColor QtColorTriangle::colorFromPoint(const QPointF &p) const +{ + // Find the outer radius of the hue gradient. + int outerRadius = (contentsRect().width() - 1) / 2; + if ((contentsRect().height() - 1) / 2 < outerRadius) + outerRadius = (contentsRect().height() - 1) / 2; + + // Find the center coordinates + double cx = (double) contentsRect().center().x(); + double cy = (double) contentsRect().center().y(); + + // Find the a, b and c from their angles, the center of the rect + // and the radius of the hue gradient donut. + QPointF pa(cx + (cos(a) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(a) * (outerRadius - (outerRadius / 5.0)))); + QPointF pb(cx + (cos(b) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(b) * (outerRadius - (outerRadius / 5.0)))); + QPointF pc(cx + (cos(c) * (outerRadius - (outerRadius / 5.0))), + cy - (sin(c) * (outerRadius - (outerRadius / 5.0)))); + + // Find the hue value from the angle of the 'a' point. + double angle = a - PI/2.0; + if (angle < 0) angle += TWOPI; + double hue = (360.0 * angle) / TWOPI; + + // Create the color of the 'a' corner point. We know that b is + // black and c is white. + QColor color; + color.setHsv(360 - (int) floor(hue), 255, 255); + + // See also drawTrigon(), which basically does exactly the same to + // determine all colors in the trigon. + Vertex aa(color, pa); + Vertex bb(Qt::black, pb); + Vertex cc(Qt::white, pc); + + // Make sure p1 is above p2, which is above p3. + Vertex *p1 = &aa; + Vertex *p2 = &bb; + Vertex *p3 = &cc; + if (p1->point.y() > p2->point.y()) swap(&p1, &p2); + if (p1->point.y() > p3->point.y()) swap(&p1, &p3); + if (p2->point.y() > p3->point.y()) swap(&p2, &p3); + + // Find the slopes of all edges in the trigon. All the three y + // deltas here are positive because of the above sorting. + double p1p2ydist = p2->point.y() - p1->point.y(); + double p1p3ydist = p3->point.y() - p1->point.y(); + double p2p3ydist = p3->point.y() - p2->point.y(); + double p1p2xdist = p2->point.x() - p1->point.x(); + double p1p3xdist = p3->point.x() - p1->point.x(); + double p2p3xdist = p3->point.x() - p2->point.x(); + + // The first x delta decides wether we have a lefty or a righty + // trigon. A lefty trigon has its tallest edge on the right hand + // side of the trigon. The righty trigon has it on its left side. + // This property determines wether the left or the right set of x + // coordinates will be continuous. + bool lefty = p1p2xdist < 0; + + // Find whether the selector's y is in the first or second shorty, + // counting from the top and downwards. This is used to find the + // color at the selector point. + bool firstshorty = (p.y() >= p1->point.y() && p.y() < p2->point.y()); + + // From the y value of the selector's position, find the left and + // right x values. + double leftx; + double rightx; + if (lefty) { + if (firstshorty) { + leftx = p1->point.x(); + if (floor(p1p2ydist) != 0.0) { + leftx += (p1p2xdist * (p.y() - p1->point.y())) / p1p2ydist; + } else { + leftx = qMin(p1->point.x(), p2->point.x()); + } + } else { + leftx = p2->point.x(); + if (floor(p2p3ydist) != 0.0) { + leftx += (p2p3xdist * (p.y() - p2->point.y())) / p2p3ydist; + } else { + leftx = qMin(p2->point.x(), p3->point.x()); + } + } + + rightx = p1->point.x(); + rightx += (p1p3xdist * (p.y() - p1->point.y())) / p1p3ydist; + } else { + leftx = p1->point.x(); + leftx += (p1p3xdist * (p.y() - p1->point.y())) / p1p3ydist; + + if (firstshorty) { + rightx = p1->point.x(); + if (floor(p1p2ydist) != 0.0) { + rightx += (p1p2xdist * (p.y() - p1->point.y())) / p1p2ydist; + } else { + rightx = qMax(p1->point.x(), p2->point.x()); + } + } else { + rightx = p2->point.x(); + if (floor(p2p3ydist) != 0.0) { + rightx += (p2p3xdist * (p.y() - p2->point.y())) / p2p3ydist; + } else { + rightx = qMax(p2->point.x(), p3->point.x()); + } + } + } + + // Find the r,g,b values of the points on the trigon's edges that + // are to the left and right of the selector. + double rshort = 0, gshort = 0, bshort = 0; + double rlong = 0, glong = 0, blong = 0; + if (firstshorty) { + if (floor(p1p2ydist) != 0.0) { + rshort = p2->color.r * (p.y() - p1->point.y()) / p1p2ydist; + gshort = p2->color.g * (p.y() - p1->point.y()) / p1p2ydist; + bshort = p2->color.b * (p.y() - p1->point.y()) / p1p2ydist; + rshort += p1->color.r * (p2->point.y() - p.y()) / p1p2ydist; + gshort += p1->color.g * (p2->point.y() - p.y()) / p1p2ydist; + bshort += p1->color.b * (p2->point.y() - p.y()) / p1p2ydist; + } else { + if (lefty) { + if (p1->point.x() <= p2->point.x()) { + rshort = p1->color.r; + gshort = p1->color.g; + bshort = p1->color.b; + } else { + rshort = p2->color.r; + gshort = p2->color.g; + bshort = p2->color.b; + } + } else { + if (p1->point.x() > p2->point.x()) { + rshort = p1->color.r; + gshort = p1->color.g; + bshort = p1->color.b; + } else { + rshort = p2->color.r; + gshort = p2->color.g; + bshort = p2->color.b; + } + } + } + } else { + if (floor(p2p3ydist) != 0.0) { + rshort = p3->color.r * (p.y() - p2->point.y()) / p2p3ydist; + gshort = p3->color.g * (p.y() - p2->point.y()) / p2p3ydist; + bshort = p3->color.b * (p.y() - p2->point.y()) / p2p3ydist; + rshort += p2->color.r * (p3->point.y() - p.y()) / p2p3ydist; + gshort += p2->color.g * (p3->point.y() - p.y()) / p2p3ydist; + bshort += p2->color.b * (p3->point.y() - p.y()) / p2p3ydist; + } else { + if (lefty) { + if (p2->point.x() <= p3->point.x()) { + rshort = p2->color.r; + gshort = p2->color.g; + bshort = p2->color.b; + } else { + rshort = p3->color.r; + gshort = p3->color.g; + bshort = p3->color.b; + } + } else { + if (p2->point.x() > p3->point.x()) { + rshort = p2->color.r; + gshort = p2->color.g; + bshort = p2->color.b; + } else { + rshort = p3->color.r; + gshort = p3->color.g; + bshort = p3->color.b; + } + } + } + } + + // p1p3ydist is never 0 + rlong = p3->color.r * (p.y() - p1->point.y()) / p1p3ydist; + glong = p3->color.g * (p.y() - p1->point.y()) / p1p3ydist; + blong = p3->color.b * (p.y() - p1->point.y()) / p1p3ydist; + rlong += p1->color.r * (p3->point.y() - p.y()) / p1p3ydist; + glong += p1->color.g * (p3->point.y() - p.y()) / p1p3ydist; + blong += p1->color.b * (p3->point.y() - p.y()) / p1p3ydist; + + // rshort,gshort,bshort is the color on one of the shortys. + // rlong,glong,blong is the color on the longy. So depending on + // wether we have a lefty trigon or not, we can determine which + // colors are on the left and right edge. + double rl, gl, bl, rr, gr, br; + if (lefty) { + rl = rshort; gl = gshort; bl = bshort; + rr = rlong; gr = glong; br = blong; + } else { + rl = rlong; gl = glong; bl = blong; + rr = rshort; gr = gshort; br = bshort; + } + + // Find the distance from the left x to the right x (xdist). Then + // find the distances from the selector to each of these (saxdist + // and saxdist2). These distances are used to find the color at + // the selector. + double xdist = rightx - leftx; + double saxdist = p.x() - leftx; + double saxdist2 = xdist - saxdist; + + // Now determine the r,g,b values of the selector using a linear + // approximation. + double r, g, b; + if (xdist != 0.0) { + r = (saxdist2 * rl / xdist) + (saxdist * rr / xdist); + g = (saxdist2 * gl / xdist) + (saxdist * gr / xdist); + b = (saxdist2 * bl / xdist) + (saxdist * br / xdist); + } else { + // In theory, the left and right color will be equal here. But + // because of the loss of precision, we get an error on both + // colors. The best approximation we can get is from adding + // the two errors, which in theory will eliminate the error + // but in practise will only minimize it. + r = (rl + rr) / 2; + g = (gl + gr) / 2; + b = (bl + br) / 2; + } + + // Now floor the color components and fit them into proper + // boundaries. This again is to compensate for the error caused by + // loss of precision. + int ri = (int) floor(r); + int gi = (int) floor(g); + int bi = (int) floor(b); + if (ri < 0) ri = 0; + else if (ri > 255) ri = 255; + if (gi < 0) gi = 0; + else if (gi > 255) gi = 255; + if (bi < 0) bi = 0; + else if (bi > 255) bi = 255; + + // Voila, we have the color at the point of the selector. + return QColor(ri, gi, bi); +} diff --git a/Source/src/Util/cusdr_colorTriangle.h b/Source/src/Util/cusdr_colorTriangle.h new file mode 100644 index 0000000..e133a56 --- /dev/null +++ b/Source/src/Util/cusdr_colorTriangle.h @@ -0,0 +1,140 @@ +/** +* @file cusdr_colorTriangle.h +* @brief Color triangle header file for cuSDR +*/ + +/**************************************************************************** +** +** This file is part of a Qt Solutions component. +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Qt Software Information (qt-info@nokia.com) +** +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Solutions Commercial License Agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** Please note Third Party Software included with Qt Solutions may impose +** additional restrictions and it is the user's responsibility to ensure +** that they have met the licensing requirements of the GPL, LGPL, or Qt +** Solutions Commercial license and the relevant license of the Third +** Party Software they are using. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** +****************************************************************************/ + +#ifndef _CUSDR_COLORTRIANGLE_H +#define _CUSDR_COLORTRIANGLE_H + +#include +#include + +class QPointF; +struct Vertex; + +#if defined(Q_WS_WIN) +# if !defined(QT_QTCOLORTRIANGLE_EXPORT) && !defined(QT_QTCOLORTRIANGLE_IMPORT) +# define QT_QTCOLORTRIANGLE_EXPORT +# elif defined(QT_QTCOLORTRIANGLE_IMPORT) +# if defined(QT_QTCOLORTRIANGLE_EXPORT) +# undef QT_QTCOLORTRIANGLE_EXPORT +# endif +# define QT_QTCOLORTRIANGLE_EXPORT __declspec(dllimport) +# elif defined(QT_QTCOLORTRIANGLE_EXPORT) +# undef QT_QTCOLORTRIANGLE_EXPORT +# define QT_QTCOLORTRIANGLE_EXPORT __declspec(dllexport) +# endif +#else +# define QT_QTCOLORTRIANGLE_EXPORT +#endif + +class QT_QTCOLORTRIANGLE_EXPORT QtColorTriangle : public QWidget +{ + Q_OBJECT + +public: + QtColorTriangle(QWidget *parent = 0); + ~QtColorTriangle(); + + QSize sizeHint() const; + int heightForWidth(int w) const; + + void polish(); + QColor color() const; + +Q_SIGNALS: + void colorChanged(const QColor &col); + +public Q_SLOTS: + void setColor(const QColor &col); + QColor getColor() { return curColor; } + +protected: + void paintEvent(QPaintEvent *); + void mouseMoveEvent(QMouseEvent *); + void mousePressEvent(QMouseEvent *); + void mouseReleaseEvent(QMouseEvent *); + void keyPressEvent(QKeyEvent *e); + void resizeEvent(QResizeEvent *); + void drawTrigon(QImage *p, const QPointF &a, const QPointF &b, + const QPointF &c, const QColor &color); + +private: + double radiusAt(const QPointF &pos, const QRect &rect) const; + double angleAt(const QPointF &pos, const QRect &rect) const; + QPointF movePointToTriangle(double x, double y, const Vertex &a, + const Vertex &b, const Vertex &c) const; + + QPointF pointFromColor(const QColor &col) const; + QColor colorFromPoint(const QPointF &p) const; + + void genBackground(); + + QImage bg; + double a, b, c; + QPointF pa, pb, pc, pd; + + QColor curColor; + int curHue; + + bool mustGenerateBackground; + int penWidth; + int ellipseSize; + + int outerRadius; + QPointF selectorPos; + + enum SelectionMode { + Idle, + SelectingHue, + SelectingSatValue + } selMode; +}; + +#endif // _CUSDR_COLORTRIANGLE_H diff --git a/Source/src/Util/cusdr_cpuUsage.cpp b/Source/src/Util/cusdr_cpuUsage.cpp new file mode 100644 index 0000000..1858b5c --- /dev/null +++ b/Source/src/Util/cusdr_cpuUsage.cpp @@ -0,0 +1,316 @@ +/* + * Windows part for CPU usage by (c) 2009 Ben Watson + * + * taken from http://www.philosophicalgeek.com/2009/01/03/determine-cpu-usage-of-current-process-c-and-c/ + * + * adapted for cuSDR by (c) 2012 Hermann von Hasseln, DL3HVH + * + * + * Linux part for CPU usage by (c) by Fabian Holler + * + * taken from https://github.com/fho/code_snippets/blob/master/c/getusage.c + * + * adapted for cuSDR by (c) 2012 Andrea Montefusco, IW0HDV + * + */ + +#include "cusdr_cpuUsage.h" + +#if defined(Q_OS_LINUX) +#include +#include +#include +#include // bzero +#include // getpagesize +#include // strncat, strlen + +/* + * read /proc data into the passed struct pstat + * returns 0 on success, -1 on error +*/ +static int get_usage(const pid_t pid, struct pstat* result) { + + //convert pid to string + char pid_s[20]; + snprintf(pid_s, sizeof(pid_s), "%d", pid); + + char stat_filepath[30] = "/proc/"; strncat(stat_filepath, pid_s, + sizeof(stat_filepath) - strlen(stat_filepath) -1); + strncat(stat_filepath, "/stat", sizeof(stat_filepath) - + strlen(stat_filepath) -1); + + //Open /proc/stat and /proc/$pid/stat fds successive(dont want that cpu + //ticks increases too much during measurements) + //TODO: open /proc dir, to lock all files and read the results from the + //same timefragem + FILE *fpstat = fopen(stat_filepath, "r"); + + if (fpstat == NULL) { + + perror("FOPEN ERROR "); + return -1; + } + + FILE *fstat = fopen("/proc/stat", "r"); + if (fstat == NULL) { + + perror("FOPEN ERROR "); + fclose(fstat); + return -1; + } + + //read values from /proc/pid/stat + bzero(result, sizeof(struct pstat)); + long int rss; + if (fscanf(fpstat, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %lu" + "%lu %ld %ld %*d %*d %*d %*d %*u %lu %ld", + &result->utime_ticks, &result->stime_ticks, + &result->cutime_ticks, &result->cstime_ticks, &result->vsize, + &rss) == EOF) { + + fclose(fpstat); + return -1; + } + + fclose(fpstat); + result->rss = rss * getpagesize(); + + //read+calc cpu total time from /proc/stat + long unsigned int cpu_time[10]; + bzero(cpu_time, sizeof(cpu_time)); + + if (fscanf(fstat, "%*s %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu", + &cpu_time[0], &cpu_time[1], &cpu_time[2], &cpu_time[3], + &cpu_time[4], &cpu_time[5], &cpu_time[6], &cpu_time[7], + &cpu_time[8], &cpu_time[9]) == EOF) { + + fclose(fstat); + return -1; + } + + fclose(fstat); + + for (int i = 0; i < 10; i++) { + + result->cpu_total_time += cpu_time[i]; + } + return 0; +} + +/* +* calculates the actual CPU usage(cur_usage - last_usage) in percent +* cur_usage, last_usage: both last measured get_usage() results +* ucpu_usage, scpu_usage: result parameters: user and sys cpu usage in % +*/ +static void calc_cpu_usage(const struct pstat* cur_usage, const struct pstat* + last_usage, double* ucpu_usage, double* scpu_usage) { + + const long unsigned int total_time_diff = cur_usage->cpu_total_time - last_usage->cpu_total_time; + + *ucpu_usage = 100 * (((cur_usage->utime_ticks + cur_usage->cutime_ticks) + - (last_usage->utime_ticks + last_usage->cutime_ticks)) + / (double) total_time_diff); + + *scpu_usage = 100 * ((((cur_usage->stime_ticks + cur_usage->cstime_ticks) + - (last_usage->stime_ticks + last_usage->cstime_ticks))) / + (double) total_time_diff); +} + +CpuUsage :: CpuUsage (void) { + + pid = getpid(); + int rc = get_usage(pid, &cpst); + + if (rc < 0) { + + printf ("Error, check PID\n"); + } + else { + + lpst = cpst; + } +} + +short CpuUsage :: GetUsage (void) { + + int rc = get_usage(pid, &cpst); + + if (rc < 0) { + + printf ("Error, check PID\n"); + } + + double ucpu_usage; + double scpu_usage; + calc_cpu_usage (&cpst, &lpst, &ucpu_usage, &scpu_usage); + //printf ("usr: %7.2g sys: %7.2g", ucpu_usage, scpu_usage); + //printf (" T: %7.0f\n", (float)(ucpu_usage+scpu_usage)/2.0*10.0); + + lpst = cpst; + return (short) ((ucpu_usage+scpu_usage)/2.0*10.0); +} + +#endif + + +#ifdef TEST_MODULE + +int main (int argc, char **argv) { + + int pid; + struct pstat cpst; + struct pstat lpst; + + if (argc > 1 && sscanf (argv[1], "%d", &pid) == 1) { + + int rc = get_usage(pid, &cpst); + + if (rc < 0) { + + printf ("Error, check PID\n"); + return 254; + } + else { + + lpst = cpst; + } + } + else { + + return 255; + } + + for (;;) { + + sleep (1); + + int rc = get_usage(pid, &cpst); + + if (rc < 0) { + + printf ("Error, check PID\n"); + return 254; + } + + double ucpu_usage; + double scpu_usage; + calc_cpu_usage (&cpst, &lpst, &ucpu_usage, &scpu_usage); + printf ("usr: %7.2g sys: %7.2g", ucpu_usage, scpu_usage); + printf (" T: %7.0f\n", (float)(ucpu_usage+scpu_usage)/2.0*10.0); + + lpst = cpst; + } +} + +#endif + + +#if defined(Q_OS_WIN32) +//#error WWWWWWWW + +CpuUsage::CpuUsage(void) + :m_nCpuUsage(-1) + ,m_dwLastRun(0) + ,m_lRunCount(0) +{ + ZeroMemory(&m_ftPrevSysKernel, sizeof(FILETIME)); + ZeroMemory(&m_ftPrevSysUser, sizeof(FILETIME)); + + ZeroMemory(&m_ftPrevProcKernel, sizeof(FILETIME)); + ZeroMemory(&m_ftPrevProcUser, sizeof(FILETIME)); +} + + +/********************************************** +* CpuUsage::GetUsage +* returns the percent of the CPU that this process +* has used since the last time the method was called. +* If there is not enough information, -1 is returned. +* If the method is recalled to quickly, the previous value +* is returned. +***********************************************/ +short CpuUsage::GetUsage() { + + //create a local copy to protect against race conditions in setting the + //member variable + short nCpuCopy = m_nCpuUsage; + if (::InterlockedIncrement(&m_lRunCount) == 1) { + + /* + If this is called too often, the measurement itself will greatly affect the + results. + */ + + if (!EnoughTimePassed()) { + + ::InterlockedDecrement(&m_lRunCount); + return nCpuCopy; + } + + FILETIME ftSysIdle, ftSysKernel, ftSysUser; + FILETIME ftProcCreation, ftProcExit, ftProcKernel, ftProcUser; + + if (!GetSystemTimes(&ftSysIdle, &ftSysKernel, &ftSysUser) || + !GetProcessTimes(GetCurrentProcess(), &ftProcCreation, &ftProcExit, &ftProcKernel, &ftProcUser)) + { + ::InterlockedDecrement(&m_lRunCount); + return nCpuCopy; + } + + if (!IsFirstRun()) { + /* + CPU usage is calculated by getting the total amount of time the system has operated + since the last measurement (made up of kernel + user) and the total + amount of time the process has run (kernel + user). + */ + ULONGLONG ftSysKernelDiff = SubtractTimes(ftSysKernel, m_ftPrevSysKernel); + ULONGLONG ftSysUserDiff = SubtractTimes(ftSysUser, m_ftPrevSysUser); + + ULONGLONG ftProcKernelDiff = SubtractTimes(ftProcKernel, m_ftPrevProcKernel); + ULONGLONG ftProcUserDiff = SubtractTimes(ftProcUser, m_ftPrevProcUser); + + ULONGLONG nTotalSys = ftSysKernelDiff + ftSysUserDiff; + ULONGLONG nTotalProc = ftProcKernelDiff + ftProcUserDiff; + + if (nTotalSys > 0) { + + m_nCpuUsage = (short)((100.0 * nTotalProc) / nTotalSys); + } + } + + m_ftPrevSysKernel = ftSysKernel; + m_ftPrevSysUser = ftSysUser; + m_ftPrevProcKernel = ftProcKernel; + m_ftPrevProcUser = ftProcUser; + + m_dwLastRun = GetTickCount(); + + nCpuCopy = m_nCpuUsage; + } + + ::InterlockedDecrement(&m_lRunCount); + + return nCpuCopy; +} + +ULONGLONG CpuUsage::SubtractTimes(const FILETIME& ftA, const FILETIME& ftB) { + + LARGE_INTEGER a, b; + a.LowPart = ftA.dwLowDateTime; + a.HighPart = ftA.dwHighDateTime; + + b.LowPart = ftB.dwLowDateTime; + b.HighPart = ftB.dwHighDateTime; + + return a.QuadPart - b.QuadPart; +} + +bool CpuUsage::EnoughTimePassed() { + + const int minElapsedMS = 250;//milliseconds + + ULONGLONG dwCurrentTickCount = GetTickCount(); + return ((int)(dwCurrentTickCount - m_dwLastRun)) > minElapsedMS; +} + +#endif \ No newline at end of file diff --git a/Source/src/Util/cusdr_cpuUsage.h b/Source/src/Util/cusdr_cpuUsage.h new file mode 100644 index 0000000..abb6e34 --- /dev/null +++ b/Source/src/Util/cusdr_cpuUsage.h @@ -0,0 +1,87 @@ +/* + * Windows part for CPU usage by (c) 2009 Ben Watson + * + * taken from http://www.philosophicalgeek.com/2009/01/03/determine-cpu-usage-of-current-process-c-and-c/ + * + * adapted for cuSDR by (c) 2012 Hermann von Hasseln, DL3HVH + * + * + * Linux part for CPU usage by (c) by Fabian Holler + * + * taken from https://github.com/fho/code_snippets/blob/master/c/getusage.c + * + * adapted for cuSDR by (c) 2012 Andrea Montefusco, IW0HDV + * + */ + +#include // needed in order to get Q_OS_LINUX macro defined + +#if defined(Q_OS_WIN32) + +#pragma once + +//#define _WIN32_WINNT 0×0501 +#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +#endif + +#include + +class CpuUsage { + +public: + CpuUsage(void); + + short GetUsage(); + +private: + ULONGLONG SubtractTimes(const FILETIME& ftA, const FILETIME& ftB); + bool EnoughTimePassed(); + inline bool IsFirstRun() const { return (m_dwLastRun == 0); } + + //system total times + FILETIME m_ftPrevSysKernel; + FILETIME m_ftPrevSysUser; + + //process times + FILETIME m_ftPrevProcKernel; + FILETIME m_ftPrevProcUser; + + short m_nCpuUsage; + ULONGLONG m_dwLastRun; + + volatile LONG m_lRunCount; +}; + +#elif defined(Q_OS_LINUX) + +#include +#include + +struct pstat { + + long unsigned int utime_ticks; + long int cutime_ticks; + long unsigned int stime_ticks; + long int cstime_ticks; + long unsigned int vsize; // virtual memory size in bytes + long unsigned int rss; //Resident Set Size in bytes + + long unsigned int cpu_total_time; +}; + + +class CpuUsage { + +public: + CpuUsage(void); + + short GetUsage(void); + +private: + pid_t pid; + struct pstat cpst; + struct pstat lpst; +}; + +#endif diff --git a/Source/src/Util/cusdr_cpuUsage_unix.cpp b/Source/src/Util/cusdr_cpuUsage_unix.cpp new file mode 100644 index 0000000..4ee9a92 --- /dev/null +++ b/Source/src/Util/cusdr_cpuUsage_unix.cpp @@ -0,0 +1,42 @@ +#include +#include +#include + +#include "cusdr_cpuUsage_unix.h" +#include "cusdr_settings.h" + +cusdr_cpuUsage::cusdr_cpuUsage() +{ + ptick=0; + ptime=0.0; + CLOCK_TICK = sysconf(_SC_CLK_TCK); + + QTimer *timer = new QTimer(); + cusdr_cpuUsage::connect(timer, SIGNAL(timeout()), this, SLOT(getCPUUsage())); + + timer->start(1000); +} + +void cusdr_cpuUsage::getCPUUsage() +{ + clock_t tick; + double time; + double load; + + struct rusage usage; + struct tms systime; + + tick = times(&systime); + getrusage(RUSAGE_SELF, &usage); + + time = usage.ru_utime.tv_sec + usage.ru_utime.tv_usec * 1e-6 + + usage.ru_stime.tv_sec + usage.ru_stime.tv_usec * 1e-6; + + load = ((time-ptime)/(tick-ptick)) * CLOCK_TICK * 100; + + if(ptick && ptime) + Settings::instance()->setCPULoad((int) load); + + ptick=tick; + ptime=time; +} diff --git a/Source/src/Util/cusdr_cpuUsage_unix.h b/Source/src/Util/cusdr_cpuUsage_unix.h new file mode 100644 index 0000000..ade4a59 --- /dev/null +++ b/Source/src/Util/cusdr_cpuUsage_unix.h @@ -0,0 +1,24 @@ +#ifndef CUSDR_CPULOAD_H +#define CUSDR_CPULOAD_H + +#include +#include + +class cusdr_cpuUsage : public QThread +{ + Q_OBJECT +public: + clock_t ptick; + double ptime; + QTimer *timer; + + cusdr_cpuUsage(); + +private: + int CLOCK_TICK; + +private slots: + void getCPUUsage(); +}; + +#endif // CUSDR_CPULOAD_H diff --git a/Source/src/Util/cusdr_highResTimer.cpp b/Source/src/Util/cusdr_highResTimer.cpp new file mode 100644 index 0000000..bbb0c77 --- /dev/null +++ b/Source/src/Util/cusdr_highResTimer.cpp @@ -0,0 +1,109 @@ +/** +* @file cusdr_highResTimer.h +* @brief HPSDR high resolution timer header file +* @author Song Ho Ahn (song.ahn@gmail.com) +* @version +* @date 2006-01-13 +*/ + +/* + * High Resolution Timer. + * This timer is able to measure the elapsed time with 1 micro-second accuracy + * in both Windows, Linux and Unix system + * + * Copyright 2006 Song Ho Ahn (song.ahn@gmail.com) + * Copyright 2012 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cusdr_highResTimer.h" +#include + +HResTimer::HResTimer() { + +#ifdef WIN32 + QueryPerformanceFrequency(&frequency); + startCount.QuadPart = 0; + endCount.QuadPart = 0; +#else + startCount.tv_sec = startCount.tv_usec = 0; + endCount.tv_sec = endCount.tv_usec = 0; +#endif + + stopped = 0; + startTimeInMicroSec = 0; + endTimeInMicroSec = 0; +} + +HResTimer::~HResTimer() { + +} + +void HResTimer::start() { + + stopped = 0; // reset stop flag + +#ifdef WIN32 + QueryPerformanceCounter(&startCount); +#else + gettimeofday(&startCount, NULL); +#endif +} + +void HResTimer::stop() { + + stopped = 1; // set timer stopped flag + +#ifdef WIN32 + QueryPerformanceCounter(&endCount); +#else + gettimeofday(&endCount, NULL); +#endif +} + +double HResTimer::getElapsedTimeInMicroSec() { + +#ifdef WIN32 + if(!stopped) + QueryPerformanceCounter(&endCount); + + startTimeInMicroSec = startCount.QuadPart * (1000000.0 / frequency.QuadPart); + endTimeInMicroSec = endCount.QuadPart * (1000000.0 / frequency.QuadPart); +#else + if(!stopped) + gettimeofday(&endCount, NULL); + + startTimeInMicroSec = (startCount.tv_sec * 1000000.0) + startCount.tv_usec; + endTimeInMicroSec = (endCount.tv_sec * 1000000.0) + endCount.tv_usec; +#endif + + return endTimeInMicroSec - startTimeInMicroSec; +} + +double HResTimer::getElapsedTimeInMilliSec() { + + return this->getElapsedTimeInMicroSec() * 0.001; +} + +double HResTimer::getElapsedTimeInSec() { + + return this->getElapsedTimeInMicroSec() * 0.000001; +} + +double HResTimer::getElapsedTime() { + + return this->getElapsedTimeInSec(); +} diff --git a/Source/src/Util/cusdr_highResTimer.h b/Source/src/Util/cusdr_highResTimer.h new file mode 100644 index 0000000..2b100b7 --- /dev/null +++ b/Source/src/Util/cusdr_highResTimer.h @@ -0,0 +1,72 @@ +/** +* @file cusdr_highResTimer.h +* @brief HPSDR high resolution timer header file +* @author Song Ho Ahn (song.ahn@gmail.com) +* @version +* @date 2006-01-13 +*/ + +/* + * High Resolution Timer. + * This timer is able to measure the elapsed time with 1 micro-second accuracy + * in both Windows, Linux and Unix system + * + * Copyright 2006 Song Ho Ahn (song.ahn@gmail.com) + * Copyright 2012 adapted for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_HRES_TIMER_H +#define CUSDR_HRES_TIMER_H + +#ifdef WIN32 // Windows system specific +#include +#else // Unix based system specific +#include +#endif + + +class HResTimer { + +public: + HResTimer(); // default constructor + ~HResTimer(); // default destructor + + void start(); // start timer + void stop(); // stop the timer + double getElapsedTime(); // get elapsed time in second + double getElapsedTimeInSec(); // get elapsed time in second (same as getElapsedTime) + double getElapsedTimeInMilliSec(); // get elapsed time in milli-second + double getElapsedTimeInMicroSec(); // get elapsed time in micro-second + +protected: + +private: + double startTimeInMicroSec; // starting time in micro-second + double endTimeInMicroSec; // ending time in micro-second + int stopped; // stop flag + +#ifdef WIN32 + LARGE_INTEGER frequency; // ticks per second + LARGE_INTEGER startCount; // + LARGE_INTEGER endCount; // +#else + timeval startCount; // + timeval endCount; // +#endif +}; + +#endif // CUSDR_HRES_TIMER_H diff --git a/Source/src/Util/cusdr_image.cpp b/Source/src/Util/cusdr_image.cpp new file mode 100644 index 0000000..386dbab --- /dev/null +++ b/Source/src/Util/cusdr_image.cpp @@ -0,0 +1,96 @@ +/** +* @file cusdr_image.cpp +* @brief image definitions class for cuSDR +*/ + +/* + * This is an adaptation of Matteo Bertozzi's "Black Bar and Buttons" code. + * + * see: http://qt-apps.org/content/show.php/Black+Bar+and+Buttons?content=100399 + * + * Copyright 2009 Matteo Bertozzi + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cusdr_imageblur.h" +#include "cusdr_painter.h" +#include "cusdr_image.h" + +QHImage::QHImage (const QSize& size, Format format) + : QImage(size, format) +{ +} + +QHImage::QHImage (int width, int height, Format format) + : QImage(width, height, format) +{ +} + +QHImage::QHImage (uchar *data, int width, int height, Format format) + : QImage(data, width, height, format) +{ +} + +QHImage::QHImage (const uchar *data, int width, int height, Format format) + : QImage(data, width, height, format) +{ +} + +QHImage::QHImage (uchar *data, int width, int height, int bytesPerLine, Format format) + : QImage(data, width, height, bytesPerLine, format) +{ +} + +QHImage::QHImage (const uchar *data, int width, int height, int bytesPerLine, Format format) + : QImage(data, width, height, bytesPerLine, format) +{ +} + +QHImage::QHImage (const QString& fileName, const char *format) + : QImage(fileName, format) +{ +} + +QHImage::QHImage (const char *fileName, const char *format) + : QImage(fileName, format) +{ +} + +QHImage::QHImage (const QImage& image) + : QImage(image) +{ +} + +QHImage::~QHImage() { +} + + +void QHImage::expblur(int aprec, int zprec, int radius) { + ImageBlur::expblur(this, aprec, zprec, radius); +} +#include + +void QHImage::shadowBlur (int radius, const QColor& color) { + ImageBlur::expblur(this, 16, 7, radius); + + QHPainter p(this); + p.setCompositionMode(QPainter::CompositionMode_SourceIn); + p.fillRect(rect(), color); + p.end(); +} + + diff --git a/Source/src/Util/cusdr_image.h b/Source/src/Util/cusdr_image.h new file mode 100644 index 0000000..2aeb012 --- /dev/null +++ b/Source/src/Util/cusdr_image.h @@ -0,0 +1,52 @@ +/** +* @file cusdr_image.h +* @brief image definitions header file for cuSDR +*/ + +/* + * This is an adaptation of Matteo Bertozzi's "Black Bar and Buttons" code. + * + * see: http://qt-apps.org/content/show.php/Black+Bar+and+Buttons?content=100399 + * + * Copyright 2009 Matteo Bertozzi + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef CUSDR_IMAGE_H +#define CUSDR_IMAGE_H + +#include + +class QHImage : public QImage { + public: + QHImage (const QSize& size, Format format); + QHImage (int width, int height, Format format); + QHImage (uchar *data, int width, int height, Format format); + QHImage (const uchar *data, int width, int height, Format format); + QHImage (uchar *data, int width, int height, int bytesPerLine, Format format); + QHImage (const uchar *data, int width, int height, int bytesPerLine, Format format); + QHImage (const QString& fileName, const char *format = 0); + QHImage (const char *fileName, const char *format = 0); + QHImage (const QImage& image); + ~QHImage(); + + public: + void expblur(int aprec, int zprec, int radius); + void shadowBlur (int radius, const QColor& color); +}; + +#endif // CUSDR_IMAGE_H + diff --git a/Source/src/Util/cusdr_imageblur.cpp b/Source/src/Util/cusdr_imageblur.cpp new file mode 100644 index 0000000..a223536 --- /dev/null +++ b/Source/src/Util/cusdr_imageblur.cpp @@ -0,0 +1,139 @@ +/** +* @file cusdr_imageblur.cpp +* @brief image blur class for cuSDR +*/ + +/* + * This is an adaptation of Jani Huhtanen Exponential blur code. + * + * Copyright 2007 Jani Huhtanen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include + +#include "cusdr_imageblur.h" + +/* ============================================================================ + * PUBLIC Constructor/Destructors + */ +ImageBlur::ImageBlur (QImage *image, int aprec, int zprec) { + m_image = image; + m_aprec = aprec; + m_zprec = zprec; +} + +ImageBlur::~ImageBlur() { + m_image = NULL; +} + +/* ============================================================================ + * PUBLIC STATIC Methods + */ +void ImageBlur::expblur (QImage *image, int aprec, int zprec, int radius) { + ImageBlur imageBlur(image, aprec, zprec); + imageBlur.expblur(radius); +} + +/* ============================================================================ + * PUBLIC Methods + */ +void ImageBlur::expblur (int radius) { + if (radius < 1) + return; + + /* Calculate the alpha such that 90% of + * the kernel is within the radius. + * (Kernel extends to infinity) + */ + //int alpha = (int)((1 << m_aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f)))); + int alpha = (unsigned int)((1 << m_aprec) * (1.0f - std::exp(-2.3f / (radius + 1.f)))); + + for (int row = 0; row < m_image->height(); ++row) + blurrow(row, alpha); + + for (int col = 0; col < m_image->width(); ++col) + blurcol(col, alpha); +} + +/* ============================================================================ + * PRIVATE Methods + */ +void ImageBlur::blurcol (int col, int alpha) { + int zR, zG, zB, zA; + + QRgb *ptr = (QRgb *)m_image->bits(); + ptr += col; + + zR = *((unsigned char *)ptr ) << m_zprec; + zG = *((unsigned char *)ptr + 1) << m_zprec; + zB = *((unsigned char *)ptr + 2) << m_zprec; + zA = *((unsigned char *)ptr + 3) << m_zprec; + + for (int index = m_image->width(); + index < (m_image->height() - 1) * m_image->width(); + index += m_image->width()) + { + blurinner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); + } + + for (int index = (m_image->height() - 2) * m_image->width(); + index >= 0; + index -= m_image->width()) + { + blurinner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); + } +} + +void ImageBlur::blurrow (int line, int alpha) { + int zR, zG, zB, zA; + + QRgb *ptr = (QRgb *)m_image->scanLine(line); + + zR = *((unsigned char *)ptr ) << m_zprec; + zG = *((unsigned char *)ptr + 1) << m_zprec; + zB = *((unsigned char *)ptr + 2) << m_zprec; + zA = *((unsigned char *)ptr + 3) << m_zprec; + + for (int index = 1; index < m_image->width(); ++index) + blurinner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); + + for (int index = m_image->width() - 2; index >= 0; --index) + blurinner((unsigned char *)&ptr[index], zR, zG, zB, zA, alpha); +} + +void ImageBlur::blurinner ( unsigned char *bptr, + int &zR, int &zG, int &zB, int &zA, + int alpha) +{ + int R, G, B, A; + R = *bptr; + G = *(bptr + 1); + B = *(bptr + 2); + A = *(bptr + 3); + + zR += (alpha * ((R << m_zprec) - zR)) >> m_aprec; + zG += (alpha * ((G << m_zprec) - zG)) >> m_aprec; + zB += (alpha * ((B << m_zprec) - zB)) >> m_aprec; + zA += (alpha * ((A << m_zprec) - zA)) >> m_aprec; + + *bptr = zR >> m_zprec; + *(bptr+1) = zG >> m_zprec; + *(bptr+2) = zB >> m_zprec; + *(bptr+3) = zA >> m_zprec; +} + diff --git a/Source/src/Util/cusdr_imageblur.h b/Source/src/Util/cusdr_imageblur.h new file mode 100644 index 0000000..3f02988 --- /dev/null +++ b/Source/src/Util/cusdr_imageblur.h @@ -0,0 +1,57 @@ +/** +* @file cusdr_imageblur.h +* @brief image blur header file for cuSDR +*/ + +/* + * This is an adaptation of Jani Huhtanen Exponential blur code. + * + * Copyright 2007 Jani Huhtanen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _KDE_PLASMA_BLUR_H_ +#define _KDE_PLASMA_BLUR_H_ + +class QImage; + +class ImageBlur { + public: + ImageBlur (QImage *image, int aprec, int zprec); + ~ImageBlur(); + + public: + void expblur (int radius); + + public: + static void expblur (QImage *image, int aprec, int zprec, int radius); + + private: + void blurcol (int col, int alpha); + void blurrow (int line, int alpha); + + void blurinner (unsigned char *bptr, + int &zR, int &zG, int &zB, int &zA, + int alpha); + + private: + QImage *m_image; + int m_aprec; + int m_zprec; +}; + +#endif /* !_KDE_PLASMA_BLUR_H_ */ + diff --git a/Source/src/Util/cusdr_led.cpp b/Source/src/Util/cusdr_led.cpp new file mode 100644 index 0000000..2f8e370 --- /dev/null +++ b/Source/src/Util/cusdr_led.cpp @@ -0,0 +1,91 @@ +/** +* @file cusdr_led.cpp +* @brief LED objects +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#include +#include +#include + +#include "cusdr_led.h" +//#include "cusdr_settings.h" + + +QHLed::QHLed(const QString& text, QWidget *parent) : QAbstractButton (parent) { + + setText(text); + this->setEnabled(false); +} + +QHLed::~QHLed() { + +} + +void QHLed::setColors(const QColor bgr, const QColor pen) { + + penColor = pen; + + linearGrad = QLinearGradient(QPointF(0, 0), QPointF(0, 1)); + linearGrad.setCoordinateMode(QGradient::ObjectBoundingMode); + linearGrad.setSpread(QGradient::PadSpread); + linearGrad.setColorAt(0, bgr); + //linearGrad.setColorAt(0.8, QColor(0x31, 0x8b, 0xda)); + linearGrad.setColorAt(1, bgr); + update(); +} + +//void QHLed::changeColor (QColor color) { +//} + +void QHLed::setLEDText(const QString& text) { + + QHLed::setText(text); +} + +QSize QHLed::minimumSizeHint(void) const { + + QFontMetrics fontMetrics(QFont("Arial", 8, QFont::Bold)); + int width = fontMetrics.width(text()) + 12; + return(QSize(width, 13)); +} + +void QHLed::paintEvent(QPaintEvent *event) { + + int height = event->rect().height(); + int width = event->rect().width(); + + p = new QHPainter(this); + + p->setPen (QPen(penColor, 1)); + + p->fillRoundRect(QRect(0, 0, width, height), 1, 1, 1, 1, QBrush(linearGrad)); + + p->setFont (QFont("Arial", 8, -1, true)); + //p->setPen(QPen(m_btnPenColor, 1)); + //p->drawText(event->rect(), Qt::AlignCenter, text()); + p->drawText(event->rect(), Qt::AlignLeft, text()); + + p->end(); +} diff --git a/Source/src/Util/cusdr_led.h b/Source/src/Util/cusdr_led.h new file mode 100644 index 0000000..e3e3de8 --- /dev/null +++ b/Source/src/Util/cusdr_led.h @@ -0,0 +1,63 @@ +/** +* @file cusdr_led.h +* @brief header file for LED objects +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_LED_H +#define CUSDR_LED_H + +#include + +#include "cusdr_painter.h" + + +class QHLed : public QAbstractButton { + + Q_OBJECT + +public: + QHLed(const QString& text, QWidget *parent = 0); + ~QHLed(); + + QSize minimumSizeHint (void) const; + +public slots: + void setColors(const QColor bgColor, const QColor penColor); + void setLEDText(const QString& text); + +protected: + void paintEvent(QPaintEvent *event); + + +private: + QHPainter *p; + + QColor bgColor; + QColor penColor; + + QLinearGradient linearGrad; +}; + +#endif // CUSDR_LED_H diff --git a/Source/src/Util/cusdr_painter.cpp b/Source/src/Util/cusdr_painter.cpp new file mode 100644 index 0000000..fee1031 --- /dev/null +++ b/Source/src/Util/cusdr_painter.cpp @@ -0,0 +1,239 @@ +/** +* @file cusdr_painter.cpp +* @brief painter class for cuSDR +*/ + +/* + * This is an adaptation of Matteo Bertozzi's "Black Bar and Buttons" code. + * + * see: http://qt-apps.org/content/show.php/Black+Bar+and+Buttons?content=100399 + * + * Copyright 2009 Matteo Bertozzi + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#include "cusdr_painter.h" +#include "cusdr_image.h" + +QHPainter::QHPainter() + : QPainter() +{ + setRenderHint(QPainter::Antialiasing); + setRenderHint(QPainter::TextAntialiasing); +} + +QHPainter::QHPainter(QPaintDevice *device) + : QPainter(device) +{ + setRenderHint(QPainter::Antialiasing); + setRenderHint(QPainter::TextAntialiasing); +} + +QHPainter::~QHPainter() { +} + + +QPainterPath QHPainter::roundRectangle (const QRectF& rect, qreal radius) { + + return(roundRectangle(rect, radius, radius, radius, radius)); +} + +QPainterPath QHPainter::roundRectangle (const QRectF& rect, qreal leftRadius, qreal rightRadius) { + + return(roundRectangle(rect, leftRadius, leftRadius, rightRadius, rightRadius)); +} + +QPainterPath QHPainter::topShadowRectangle (const QRectF& rect, qreal radius) { + + return(topShadowRectangle(rect, radius, radius, radius, radius)); +} + +QPainterPath QHPainter::topShadowRectangle (const QRectF& rect, qreal leftRadius, qreal rightRadius) { + + return(topShadowRectangle(rect, leftRadius, leftRadius, rightRadius, rightRadius)); +} + +QPainterPath QHPainter::roundRectangle (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius) +{ + // Top Left Corner + // Top Side + // Top right corner + // Right side + // Bottom right corner + // Bottom side + // Bottom left corner + + QPainterPath path(QPoint(rect.left(), rect.top() + leftTopRadius)); + path.quadTo(rect.left(), rect.top(), rect.left() + leftTopRadius, rect.top()); + path.lineTo(rect.right() - rightTopRadius, rect.top()); + path.quadTo(rect.right(), rect.top(), rect.right(), rect.top() + rightTopRadius); + path.lineTo(rect.right(), rect.bottom() - rightBottomRadius); + path.quadTo(rect.right(), rect.bottom(), rect.right() - rightBottomRadius, rect.bottom()); + path.lineTo(rect.left() + leftBottomRadius, rect.bottom()); + path.quadTo(rect.left(), rect.bottom(), rect.left(), rect.bottom() - leftBottomRadius); + path.closeSubpath(); + + return(path); +} + +QPainterPath QHPainter::topShadowRectangle (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius) +{ + // Top Left Corner + // Top Side + // Top right corner + // Right side + // Bottom right corner + // Bottom side + // Bottom left corner + Q_UNUSED(rightBottomRadius) + + QPainterPath path(QPoint(rect.left(), rect.bottom() - leftBottomRadius)); + path.lineTo(rect.left(), rect.top() + leftTopRadius); + path.quadTo(rect.left(), rect.top(), rect.left() + leftTopRadius, rect.top()); + path.lineTo(rect.right() - rightTopRadius, rect.top()); + + return(path); +} + +void QHPainter::drawRoundRect (const QRectF& rect, qreal radius) { + drawPath(roundRectangle(rect, radius, radius, radius, radius)); +} + +void QHPainter::drawRoundRect (const QRectF& rect, + qreal leftRadius, + qreal rightRadius) +{ + drawPath(roundRectangle(rect, leftRadius, leftRadius, + rightRadius, rightRadius)); +} + +void QHPainter::drawRoundRect ( const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius) +{ + drawPath(roundRectangle(rect, leftTopRadius, leftBottomRadius, + rightTopRadius, rightBottomRadius)); +} + +void QHPainter::drawTopShadow (const QRectF& rect, qreal radius) { + + drawPath(topShadowRectangle(rect, radius, radius, radius, radius)); +} + +void QHPainter::drawTopShadow (const QRectF& rect, + qreal leftRadius, + qreal rightRadius) +{ + drawPath(topShadowRectangle(rect, leftRadius, leftRadius, + rightRadius, rightRadius)); +} + +void QHPainter::drawTopShadow ( const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius) +{ + drawPath(topShadowRectangle(rect, leftTopRadius, leftBottomRadius, + rightTopRadius, rightBottomRadius)); +} + +void QHPainter::drawShadowText (qreal x, qreal y, + const QString& text, + const QColor& shadowColor, + const QPointF& offset, + qreal radius) +{ + QPainter p; + + // Draw Text + QRect textRect = QFontMetrics(text).boundingRect(text); + QImage textImage(textRect.size(), QImage::Format_ARGB32_Premultiplied); + textImage.fill(Qt::transparent); + p.begin(&textImage); + p.setPen(pen()); + p.setFont(font()); + p.drawText(textImage.rect(), Qt::AlignLeft, text); + p.end(); + + // Draw Blurred Shadow + QHImage shadowImage(textRect.size() + QSize(radius * 2, radius * 2), + QImage::Format_ARGB32_Premultiplied); + shadowImage.fill(Qt::transparent); + p.begin(&shadowImage); + p.drawImage(radius, radius, textImage); + p.end(); + shadowImage.shadowBlur(radius, shadowColor); + + // Compose Text and Shadow + int addSizeX = (offset.x() > radius) ? (abs(offset.x()) - radius) : 0; + int addSizeY = (offset.y() > radius) ? (abs(offset.y()) - radius) : 0; + QSize finalSize = shadowImage.size() + QSize(addSizeX, addSizeY); + + QPointF shadowTopLeft(QPointF((finalSize.width() - shadowImage.width()) / 2.0, + (finalSize.height() - shadowImage.height()) / 2.0) + + (offset / 2.0)); + QPointF textTopLeft(QPointF((finalSize.width() - textImage.width()) / 2.0, + ((finalSize.height() - textImage.height()) / 2.0)) - + (offset / 2.0)); + + // Paint Text and Shadow + save(); + translate(x, y); + setCompositionMode(QPainter::CompositionMode_Xor); + drawImage(shadowTopLeft, shadowImage); + drawImage(textTopLeft, textImage); + restore(); +} + + +void QHPainter::fillRoundRect ( const QRectF& rect, + qreal radius, + const QBrush& brush) +{ + fillPath(roundRectangle(rect, radius, radius, radius, radius), brush); +} + +void QHPainter::fillRoundRect ( const QRectF& rect, + qreal leftRadius, + qreal rightRadius, + const QBrush& brush) +{ + fillPath(roundRectangle(rect, leftRadius, leftRadius, + rightRadius, rightRadius), brush); +} + +void QHPainter::fillRoundRect ( const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius, + const QBrush& brush) +{ + fillPath(roundRectangle(rect, leftTopRadius, leftBottomRadius, + rightTopRadius, rightBottomRadius), brush); +} + diff --git a/Source/src/Util/cusdr_painter.h b/Source/src/Util/cusdr_painter.h new file mode 100644 index 0000000..8681894 --- /dev/null +++ b/Source/src/Util/cusdr_painter.h @@ -0,0 +1,105 @@ +/** +* @file cusdr_painter.h +* @brief painter header file for cuSDR +*/ + +/* + * This is an adaptation of Matteo Bertozzi's "Black Bar and Buttons" code. + * + * see: http://qt-apps.org/content/show.php/Black+Bar+and+Buttons?content=100399 + * + * Copyright 2009 Matteo Bertozzi + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_PAINTER_H +#define CUSDR_PAINTER_H + +#include + +class QHPainter : public QPainter { + +public: + QHPainter(); + QHPainter(QPaintDevice *device); + ~QHPainter(); + + // STATIC Methods + static QPainterPath roundRectangle (const QRectF& rect, qreal radius); + static QPainterPath roundRectangle (const QRectF& rect, + qreal leftRadius, + qreal rightRadius); + static QPainterPath roundRectangle (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius); + static QPainterPath topShadowRectangle (const QRectF& rect, qreal radius); + static QPainterPath topShadowRectangle (const QRectF& rect, + qreal leftRadius, + qreal rightRadius); + static QPainterPath topShadowRectangle (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius); + + // Methods + void drawShadowText ( qreal x, qreal y, + const QString& text, + const QColor& shadowColor, + const QPointF& offset, + qreal radius); + + void drawRoundRect (const QRectF& rect, + qreal radius); + void drawRoundRect (const QRectF& rect, + qreal leftRadius, + qreal rightRadius); + void drawRoundRect (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius); + + void drawTopShadow (const QRectF& rect, + qreal radius); + void drawTopShadow (const QRectF& rect, + qreal leftRadius, + qreal rightRadius); + void drawTopShadow (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius); + + void fillRoundRect (const QRectF& rect, + qreal radius, + const QBrush& brush); + void fillRoundRect (const QRectF& rect, + qreal leftRadius, + qreal rightRadius, + const QBrush& brush); + void fillRoundRect (const QRectF& rect, + qreal leftTopRadius, + qreal leftBottomRadius, + qreal rightTopRadius, + qreal rightBottomRadius, + const QBrush& brush); +}; + +#endif // CUSDR_PAINTER_H \ No newline at end of file diff --git a/Source/src/Util/cusdr_queue.h b/Source/src/Util/cusdr_queue.h new file mode 100644 index 0000000..f2ef13c --- /dev/null +++ b/Source/src/Util/cusdr_queue.h @@ -0,0 +1,135 @@ +/** +* @file cusdr_queue.h +* @brief queue header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-13 +*/ + +/* + * adaptation from a code example from QtCentre: http://www.qtcentre.org/threads/26250-Thread-Safe-Queue-container... + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_QUEUE_H +#define CUSDR_QUEUE_H + +#include +#include +#include + +template class QHQueue { + +public: + QHQueue(int maxSize = 2048) + : m_semFree(maxSize) + , m_semUsed(0) + { + } + + void enqueue(const T &value) { + + m_semFree.acquire(1); + m_mutex.lock(); + m_queue.enqueue(value); + m_mutex.unlock(); + m_semUsed.release(1); + } + + T dequeue() { + + m_semUsed.acquire(1); + m_mutex.lock(); + T val = m_queue.dequeue(); + m_mutex.unlock(); + m_semFree.release(1); + return val; + } + + T head() { + + m_semUsed.acquire(1); + m_mutex.lock(); + T val = m_queue.head(); + m_mutex.unlock(); + m_semUsed.release(1); + } + + bool isEmpty() const { + + return m_semUsed.available() == 0; + } + + bool isFull() const { + + return m_semFree.available() == 0; + } + + int count() const { + + return m_semUsed.available(); + } + + void release_queue() { + + m_semUsed.release(1); + } + + /*void setMaxSize(int maxSize) { + + m_mutex.lock(); + delete &m_semFree; + QSemaphore m_semFree(maxSize); + m_mutex.unlock(); + }*/ + + T tryHead() { + + bool t = m_semUsed.tryAcquire(1); + if (!t) + return T(); + + m_mutex.lock(); + T val = m_queue.head(); + m_mutex.unlock(); + m_semUsed.release(); + + return val; + } + + T tryDequeue() { + + bool t = m_semUsed.tryAcquire(1); + if (!t) + return T(); + + m_mutex.lock(); + T val = m_queue.dequeue(); + m_mutex.unlock(); + m_semUsed.release(); + + return val; + } + +private: + QQueue m_queue; + QSemaphore m_semFree; + QSemaphore m_semUsed; + QMutex m_mutex; +}; + +#endif // CUSDR_QUEUE_H \ No newline at end of file diff --git a/Source/src/Util/cusdr_splash.cpp b/Source/src/Util/cusdr_splash.cpp new file mode 100644 index 0000000..35defe7 --- /dev/null +++ b/Source/src/Util/cusdr_splash.cpp @@ -0,0 +1,62 @@ +/** +* @file cusdr_splash.cpp +* @brief splash screen class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-05-21 +*/ + +/* + * Taken from: Qt Developer Network; QSplashScreen replacement for semitransparent images + * + * http://developer.qt.nokia.com/wiki/QSplashScreen_replacement_for_semitransparent_images + * + * License: http://creativecommons.org/licenses/by-sa/2.5/legalcode + */ + +#include +#include "cusdr_splash.h" + +CSplashScreen::CSplashScreen(const QPixmap& thePixmap) + //: QFrame(0, Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint) + : QFrame(0, Qt::FramelessWindowHint) + , itsPixmap(thePixmap) +{ + setAttribute(Qt::WA_TranslucentBackground); + setAttribute(Qt::WA_TransparentForMouseEvents); + setFixedSize(itsPixmap.size()); +}; + +void CSplashScreen::clearMessage() { + + itsMessage.clear(); + repaint(); +} + +void CSplashScreen::showMessage(const QString& theMessage, int theAlignment/* = Qt::AlignLeft*/, const QColor& theColor/* = Qt::black*/) { + + itsMessage = theMessage; + itsAlignment = theAlignment; + itsColor = theColor; + repaint(); +} + +void CSplashScreen::paintEvent(QPaintEvent* pe) { + + Q_UNUSED(pe) + + QRect aTextRect(rect()); + //aTextRect.setRect(aTextRect.x() + 5, aTextRect.y() + 5, aTextRect.width() - 10, aTextRect.height() - 10); + aTextRect.setRect(aTextRect.x() - 5, aTextRect.y() - 5, aTextRect.width() - 10, aTextRect.height() - 10); + + QRect aCopyrightRect(rect()); + //aCopyrightRect.setRect(aCopyrightRect.x() + 5, aCopyrightRect.y() - 5, aCopyrightRect.width() - 10, aCopyrightRect.height() - 5); + aCopyrightRect.setRect(aCopyrightRect.right() - 125, aCopyrightRect.y() - 5, aCopyrightRect.width() - 10, aCopyrightRect.height() - 5); + + QPainter aPainter(this); + aPainter.drawPixmap(rect(), itsPixmap); + aPainter.setPen(itsColor); + aPainter.drawText(aTextRect, itsAlignment, itsMessage); + aPainter.setPen(Qt::black); + aPainter.drawText(aCopyrightRect, Qt::AlignBottom, "(C) 2011-2013 DL3HVH"); +} \ No newline at end of file diff --git a/Source/src/Util/cusdr_splash.h b/Source/src/Util/cusdr_splash.h new file mode 100644 index 0000000..689211e --- /dev/null +++ b/Source/src/Util/cusdr_splash.h @@ -0,0 +1,40 @@ +/** +* @file cusdr_splash.h +* @brief splash screen header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-05-21 +*/ + +/* + * Taken from: Qt Developer Network; QSplashScreen replacement for semitransparent images + * + * http://developer.qt.nokia.com/wiki/QSplashScreen_replacement_for_semitransparent_images + * + * License: http://creativecommons.org/licenses/by-sa/2.5/legalcode + */ + +#ifndef _CUSDR_SLASHSCREEN_H +#define _CUSDR_SLASHSCREEN_H + +#include + +class CSplashScreen : public QFrame { + +public: + CSplashScreen(const QPixmap& pixmap); + + void clearMessage(); + void showMessage(const QString& theMessage, int theAlignment = Qt::AlignLeft, const QColor& theColor = Qt::black); + +private: + virtual void paintEvent(QPaintEvent* pe); + + QPixmap itsPixmap; + QString itsMessage; + int itsAlignment; + QColor itsColor; +}; + + +#endif // _CUSDR_SLASHSCREEN_H \ No newline at end of file diff --git a/Source/src/Util/cusdr_styles.h b/Source/src/Util/cusdr_styles.h new file mode 100644 index 0000000..c7a8a1b --- /dev/null +++ b/Source/src/Util/cusdr_styles.h @@ -0,0 +1,439 @@ +/** +* @file cusdr_styles.h +* @brief style settings header file for cuSDR +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-30 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_STYLES_H +#define CUSDR_STYLES_H + +QString sdrStyle = QString::fromUtf8( + "background-color: rgba(0, 0, 0, 255);" + ); + +QString dialogStyle = QString::fromUtf8( + "background-color: rgba(60, 60, 60, 255);"); + +QString colorDialogStyle = QString::fromUtf8( + "background-color: rgba(30, 30, 30, 255); " + "color: rgb(166, 196, 208); "); + +QString mainWindowStyle = QString::fromUtf8( + "QMainWindow::separator {" + " background: rgba(166, 196, 208, 130);" + " width: 2px;" + " height: 2px;" + "}" + "QMainWindow::separator:hover {" + " background: rgba(166, 196, 208, 200);" + "}" + ); + +QString widgetStyle = QString::fromUtf8( + //"background-color: rgba(0, 0, 0, 255); " + "QGroupBox { " + " background-color: rgba(0, 0, 0, 255); " + //" border: 1px solid rgba(45, 122, 148, 150); " + " border: 1px solid rgba(255, 255, 255, 80); " + " border-radius: 2px; margin-top: 2ex; } " + "QGroupBox::title { " + " subcontrol-origin: margin; " + " padding: 0 0px; " + " color: rgba(170, 170, 170, 255); }" + ); + +QString itemStyle = QString::fromUtf8( + "color: rgba(200, 200, 200, 255); " + "border: 0px solid; "); + +QString labelStyle = QString::fromUtf8( + "color: rgba(166, 196, 208, 255);"); + +QString tableStyle = QString::fromUtf8( + "color: rgba(166, 196, 208, 255); " + "border: 0px solid; "); + +QString messageBoxStyle = QString::fromUtf8( + "border: 0px solid rgba(166, 196, 208, 255); " + "border-right-width: 0px; " + "color: rgb(166, 196, 208); " + "background-color: rgba(0, 0, 0, 255); "); + +QString lineEditStyle = QString::fromUtf8( + "border: 1px solid rgba(60, 60, 60, 255); " + //"border-right-width: 0px; " + "color: rgb(166, 196, 208); " + "background-color: rgba(0, 0, 0, 255); "); + +QString displayToolbarStyle = QString::fromUtf8( + "QToolBar {" + " border: 0px solid rgba(0, 0, 0, 255); " + " color: rgb(166, 196, 208); " + " background-color: rgba(0, 0, 0, 255); " + "}" + "QToolBar::handle {" + //" background-color: rgba(0, 0, 0, 255); " + "}" + ); + +QString mainBtnToolbarStyle = QString::fromUtf8( + "QToolBar {" + " border: 2px solid rgba(0, 0, 0, 255); " + //"border-right-width: 0px; " + " color: rgb(166, 196, 208); " + " background-color: rgba(0, 0, 0, 255); " + "}" + "QToolBar::handle {" + //" background-color: rgba(0, 0, 0, 255); " + "}" + ); + +QString statusbarStyle = QString::fromUtf8( + "QStatusBar {" + //"border: 0px solid rgba(60, 60, 60, 255); " + //"border-right-width: 0px; " + " color: rgb(166, 196, 208); " + " background-color: rgba(0, 0, 0, 255); " + "}" + "QStatusBar::item {" + " border: 1px rgba(60, 60, 60, 255);" + " border-radius: 0px;" + "}" + ); + +QString dockStyle = QString::fromUtf8( + "QDockWidget {" + " color: rgba(166, 196, 208, 255);" + " border: 1px solid rgba(60, 60, 60, 255);" + "}" + //"background-color: rgba(0, 0, 0, 255); " + "QDockWidget::title {" + " text-align: left;" + //" background: rgba(60, 60, 60, 255);" + " background: qlineargradient(y1:0, y2:1, stop: 0 #a0a0a0, stop: 0.5 #202020, stop: 1 #404040); " + //" border: 1px solid rgba(60, 60, 60, 255);" + //" border-radius: 2px;" + " padding-left: 5px;" + "}" + "QDockWidget::close-button, QDockWidget::float-button {" + " border: 1px solid transparent;" + " background: rgba(166, 196, 208, 255);" + " padding: 1px;" + "}"); + +QString comboBoxStyle = QString::fromUtf8( + "QComboBox { " + " color: rgba(166, 196, 208, 255); " + //" border: 1px solid rgba(45, 122, 148, 150); " + " border: 1px solid rgba(255, 255, 255, 50); " + " border-radius: 2px; } " + "QComboBox::drop-down:!editable { " + " color: rgba(166, 196, 208, 255); " + " background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, " + " stop: 0 #a1a1a1, stop: 0.4 #656565, " + " stop: 0.5 #383838, stop: 1.0 #232323); }" + "QComboBox:on { " + " color: rgba(166, 196, 208, 255); " + " padding-top: 3px; " + " padding-left: 4px; }" + "QComboBox:disabled { " + " color: rgba(166, 196, 208, 155); " + " padding-top: 3px; " + " padding-left: 4px; }" + "QComboBox::drop-down { " + " subcontrol-origin: padding; " + " subcontrol-position: top right; " + " width: 15px; " + " border-left-width: 0px; " + " border-left-color: darkgray; " + " border-left-style: solid; " + " border-top-right-radius: 2px; " + " border-bottom-right-radius: 2px; }" + "QComboBox::down-arrow { " + " image: url(:/img/down_arrow.png); " + " width: 10px; " + " height: 10px; }" + "QComboBox::down-arrow:on { " + " top: 1px; " + " left: 1px; }" + "QComboBox QAbstractItemView { " + " color: rgba(166, 196, 208, 255); " + //" border: 1px solid rgba(45, 122, 148, 150); " + " border: 1px solid rgba(255, 255, 255, 80); " + " selection-background-color: rgba(38, 38, 38, 255); }"); + +QString spinBoxStyle = QString::fromUtf8( + "QSpinBox::up-button { " + " subcontrol-origin: border; " + " subcontrol-position: top left; " + " width: 18px; " + " height: 10px; " + " border-width: 4px; } " + "QSpinBox::down-button { " + " subcontrol-origin: border; " + " subcontrol-position: bottom left; " + " width: 18px; " + " height: 10px; " + " border-width: 4px; } " + "QSpinBox::up-arrow { " + " image: url(:/img/up_arrow.png); " + " width: 8px; " + " height: 8px; } " + "QSpinBox::down-arrow { " + " image: url(:/img/down_arrow.png); " + " width: 8px; " + " height: 8px; } " + "QSpinBox::up-arrow:off { " + " image: url(:/img/up_arrow_off.png); }" + //" top: 1px; " + //" left: 1px; } " + "QSpinBox::down-arrow:off { " + " image: url(:/img/down_arrow_off.png); }" + "QSpinBox::up-arrow:disabled { " + " image: url(:/img/up_arrow_off.png); }" + //" top: 1px; " + //" left: 1px; } " + "QSpinBox::down-arrow:disabled { " + " image: url(:/img/down_arrow_off.png); }" + //" top: 1px; " + //" left: 1px; } " + "QSpinBox { " + " color: rgba(166, 196, 208, 255); " + " border: 1px solid rgba(255, 255, 255, 80); } " + + ); + +QString dSpinBoxStyle = QString::fromUtf8( + "QDoubleSpinBox::up-button { " + " subcontrol-origin: border; " + " subcontrol-position: top left; " + " width: 18px; " + " height: 10px; " + " border-width: 4px; } " + "QDoubleSpinBox::down-button { " + " subcontrol-origin: border; " + " subcontrol-position: bottom left; " + " width: 18px; " + " height: 10px; " + " border-width: 4px; } " + "QDoubleSpinBox::up-arrow { " + " image: url(:/img/up_arrow.png); " + " width: 8px; " + " height: 8px; } " + "QDoubleSpinBox::down-arrow { " + " image: url(:/img/down_arrow.png); " + " width: 8px; " + " height: 8px; } " + "QDoubleSpinBox::up-arrow:on { " + " top: 0px; " + " left: 0px; } " + "QDoubleSpinBox::down-arrow:on { " + " top: 0px; " + " left: 0px; } " + "QDoubleSpinBox { " + " color: rgba(166, 196, 208, 255); " + //" border: 1px solid rgba(45, 122, 148, 150); } " + " border: 1px solid rgba(255, 255, 255, 80); } " + ); + +QString menuStyle = QString::fromUtf8( + "QMenu { " + " background-color: rgba(0, 0, 0, 255); " + " border: 1px solid rgba(45, 122, 148, 150); " + " color: rgba(220, 220, 220, 255);} " + "QMenu::item { " + " background-color: transparent; } " + "QMenu::item:selected { " + " background: rgba(45, 122, 148, 200); } " + /*border: 1px inset rgba(45, 122, 148, 200); \ + position: absolute; \ + top: 1px; \ + right: 1px; \ + bottom: 1px; \ + left: 8px; }"*/ + ); + +QString miniButtonStyle = QString::fromUtf8( + "font-size: 7pt;" + ); + +QString sliderLabelStyle = QString::fromUtf8( + "QLabel { " + " color: rgba(126, 156, 168, 255); " + " background: qlineargradient(y1:0, y2:1, stop: 0 #808080, stop: 0.5 #202020, stop: 1 #404040); " + " border: qlineargradient(y1:0, y2:1, stop:0 #B1B1B1, stop:1 #000000); }" + ); + +QString volSliderStyle = QString::fromUtf8( + "QSlider::groove:horizontal {" + " border: qlineargradient(y1:0, y2:1, stop:0 #B1B1B1, stop:1 #000000);" + " background-color: transparent;" + "}" + "QSlider::handle:horizontal {" + " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, " + " stop: 0 #1592ba, stop: 0.5 #00527a, stop: 1 #0582aa);" + " border-radius: 2px;" + " width: 12px;" + "} " + "QSlider::handle:hover {" + " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, " + " stop: 0 #55c2ea, stop: 0.5 #4092ba, stop: 1 #55c2ea);" + //" margin: -4px 0;" + " border: 1px solid #91ebff;" + " border-radius: 2px;" + //" height: 16px;" + "}" + "QSlider::handle:pressed {" + " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, " + " stop: 0 #75e2fa, stop: 0.5 #60a2da, stop: 1 #75e2fa);" + " border: 1px solid #91ebff;" + " border-radius: 2px;" + "}" + "QSlider::add-page:horizontal {" + " background: qlineargradient(y1:0, y2:1, " + " stop: 0 #808080, stop: 0.5 #202020, stop: 1 #404040);" + //" background-color: transparent;" + "}" + "QSlider::sub-page:horizontal {" + " background: qlineargradient(y1:0, y2:1, " + " stop: 0 #1592ba, stop: 0.5 #00527a, stop: 1 #0582aa);" + //" background-color: transparent;" + "}"); + + +QString splitterStyle = QString::fromUtf8( + "QSplitter::handle:vertical { " + " height: 4px; " + " background: rgba(255, 255, 255, 0); } " + /*" background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, " + " stop:0 rgba(255, 255, 255, 0), " + " stop:0.3 rgba(85, 210, 250, 105), " + " stop:0.7 rgba(85, 210, 250, 105), " + " stop:1 rgba(255, 255, 255, 0)); } "*/ + + "QSplitter::handle:horizontal { " + " width: 4px; " + " background: rgba(255, 255, 255, 0); } " + /*" background: qlineargradient(x1:0, y1:0, x2:1, y2:1, " + " stop:0 rgba(255, 255, 255, 0), " + " stop:0.3 rgba(85, 210, 250, 105), " + " stop:0.7 rgba(85, 210, 250, 105), " + " stop:1 rgba(255, 255, 255, 0)); } "*/ + " border: 0px solid rgba(255, 0, 0, 255); " + //" width: 8px; " + //" margin-top: 1px; " + //" margin-bottom: 1px; " + //" border-radius: 1px; " + //" width: 3px; } " + + ////"QSplitter::handle { " + ////" image: url(:/img/left.png); } " + //"QSplitter { " + //" padding: 0px; " + ////" border: 1px solid rgba(60, 60, 60, 255); " + ////" border-radius: 2px; } " + //"QSplitter::handle:horizontal { " + //" width: 2px; } " + //"QSplitter::handle:vertical { " + //" height: 2px; } "); + ); + +QString frameStyle = QString::fromUtf8( + //"border: 1px solid rgba(45, 122, 148, 150); " + "border: 1px solid rgba(255, 255, 255, 80); " + "border-radius: 2px; margin-top: 2ex; " + ); + +QString tabWidgetStyle = QString::fromUtf8( + "QTabWidget::pane {" + " margin-top: 4px;" + " margin-left: 4px;" + //" margin-right: 4px;" + " margin-bottom: 2px;" + //" border: 0px" + //" border: 1px solid rgba(255, 255, 255, 80); " + " border: 1px solid #565656; " + " border-radius: 2px;" + "}" + "QTabWidget::tab-bar {" + " left: 4px;" + " top: 5px;" + " right: 4px;" + "}" + "QTabBar::tab {" + //" color: #000000;" + " color: rgba(166, 196, 208, 235);" + " background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 #868686, stop: 0.3 #565656," + " stop: 0.4 #000000, stop: 1.0 #000000);" + " border: 1px solid #565656;" + //" border-bottom-color: #91EBFF;" + " border-bottom-color: #565656;" + " border-left-color: #606060;" + " border-right-color: #000000;" + " border-top-left-radius: 1px;" + " border-top-right-radius: 1px;" + " min-width: 8ex;" + " max-height: 10px;" + " padding: 2px;" + "}" + "QTabBar::tab:disabled {" + " color: #000000;" + "}" + + "QTabBar::tab:selected {" + /*" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 #55D2FA, stop: 0.3 #505050," + " stop: 0.4 #101010, stop: 1.0 #000000);" + "}"*/ + " color: rgba(166, 196, 208, 255);" + " background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 #969696, stop: 0.3 #505050," + " stop: 0.4 #101010, stop: 1.0 #000000);" + "}" + "QTabBar::tab:hover {" + /*" background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 #91EBFF, stop: 0.4 #000000," + " stop: 0.8 #000000, stop: 1.0 #91EBFF);"*/ + " background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1," + " stop: 0 #C6C6C6, stop: 0.3 #505050," + " stop: 0.4 #202020, stop: 1.0 #000000);" + //" border-top-color: #91EBFF;" + //" border-left-color: #61CBDF;" + //" border-right-color: #91EBFF;" + //" border-color: #91EBFF;" + //" border-color: #969696;" + //" border-bottom-color: #000000;" + "}" + "QTabBar::tab:selected {" + //" border-color: #91EBFF;" + " border-color: #565656;" + " border-right-color: #000000;" + " border-bottom-color: #000000;" + "}" + "QTabBar::tab:!selected {" + " margin-top: 2px;" + "}" + ); + +#endif // CUSDR_STYLES_H diff --git a/Source/src/Util/qcircularbuffer.h b/Source/src/Util/qcircularbuffer.h new file mode 100644 index 0000000..1a1b87e --- /dev/null +++ b/Source/src/Util/qcircularbuffer.h @@ -0,0 +1,1294 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCIRCULARBUFFER_H +#define QCIRCULARBUFFER_H + +#include +#include +#include +#include + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +template +class CircularBufferData : public QSharedData +{ +public: + CircularBufferData() + : data(0), + capacity(0), + size(0), + first(-1), + last(-1) + {} + + ~CircularBufferData() + { + // Cleanup the data first + if (QTypeInfo::isComplex) { + // The type is complex so we manually call the destructor for each item + // since we used the placement new operator to instantiate them + T* b = data; + T* i = b + capacity; + while (i-- != b) + i->~T(); + } + + // Release the raw memory + deallocate(data); + } + + T* allocate(int capacity); + void deallocate(T* data); + + T* data; // Array of the actual data + int capacity; // Size of the m_data array + int size; // Number of elements of m_data actually used + int first; // Index in m_data of the first element of the circular buffer + int last; // Index in m_data of the last element of the circular buffer +}; + +template +T* CircularBufferData::allocate(int capacity) +{ + void* rawMemory = operator new[](capacity * sizeof(T)); + T* data = static_cast(rawMemory); + return data; +} + +template +void CircularBufferData::deallocate(T* data) +{ + operator delete[](data); +} + + +template +class QCircularBuffer +{ +public: + typedef QPair array_range; + typedef QPair const_array_range; + typedef array_range ArrayRange; + typedef const_array_range ConstArrayRange; + + QCircularBuffer() + : d(new CircularBufferData()) + {} + + explicit QCircularBuffer(int capacity); + explicit QCircularBuffer(int capacity, const T &value); + explicit QCircularBuffer(int capacity, int size, const T &value); + + QCircularBuffer(const QCircularBuffer& other) + : d(other.d) + {} + + QCircularBuffer& operator = (const QCircularBuffer& other) + { + d = other.d; + return *this; + } + + ~QCircularBuffer() {} + + class iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef T *pointer; + typedef T &reference; + + iterator() : buffer(0), index(-1) {} + iterator(QCircularBuffer* buffer, int index) + : buffer(buffer), index(index) + {} + iterator(const iterator& other) + : buffer(other.buffer), index(other.index) + {} + + T &operator*() const { return (*buffer)[ index ]; } + T* operator->() const + { + return buffer->d->data + ((buffer->d->first + index) % buffer->d->capacity); + } + T &operator[](int j) const { return (*buffer)[ index + j ]; } + + bool operator==(const iterator& other) const + { + return (buffer == other.buffer && index == other.index); + } + + bool operator!=(const iterator& other) const + { + return (buffer != other.buffer || index != other.index); + } + + bool operator<(const iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator<", "iterators use different buffers"); + return index < other.index; + } + + bool operator<=(const iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator<=", "iterators use different buffers"); + return index <= other.index; + } + + bool operator>(const iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator>", "iterators use different buffers"); + return index > other.index; + } + + bool operator>=(const iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator>=", "iterators use different buffers"); + return index >= other.index; + } + + iterator& operator++() { ++index; return *this; } + iterator operator++(int) + { + iterator ans = *this; + ++index; + return ans; + } + + iterator& operator--() { --index; return *this; } + iterator operator--(int) + { + iterator ans = *this; + --index; + return ans; + } + + iterator& operator+=(int j) { index += j; return *this; } + iterator& operator-=(int j) { index -= j; return *this; } + iterator operator+(int j) const { return iterator(buffer, index + j); } + iterator operator-(int j) const { return iterator(buffer, index - j); } + int operator-(iterator other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::iterator::operator-", "iterators use different buffers"); + return index - other.index; + } + + private: + QCircularBuffer* buffer; + int index; + friend class QCircularBuffer; + }; + friend class iterator; + + class const_iterator + { + public: + typedef std::random_access_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + typedef T value_type; + typedef const T* pointer; + typedef const T &reference; + + const_iterator() : buffer(0), index(-1) {} + const_iterator(const QCircularBuffer* buffer, int index) + : buffer(buffer), index(index) + {} + const_iterator(const const_iterator& other) + : buffer(other.buffer), index(other.index) + {} + explicit const_iterator(const iterator& other) + : buffer(other.buffer), index(other.index) + {} + + const T &operator*() const { return buffer->at(index); } + const T* operator->() const + { + return buffer->d->data + ((buffer->d->first + index) % buffer->d->capacity); + } + const T &operator[](int j) const { return buffer->at(index + j); } + + bool operator==(const const_iterator& other) const + { + return (buffer == other.buffer && index == other.index); + } + + bool operator!=(const const_iterator& other) const + { + return (buffer != other.buffer || index != other.index); + } + + bool operator<(const const_iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator<", "iterators use different buffers"); + return index < other.index; + } + + bool operator<=(const const_iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator<=", "iterators use different buffers"); + return index <= other.index; + } + + bool operator>(const const_iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator>", "iterators use different buffers"); + return index > other.index; + } + + bool operator>=(const const_iterator& other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator>=", "iterators use different buffers"); + return index >= other.index; + } + + const_iterator& operator++() { ++index; return *this; } + const_iterator operator++(int) + { + const_iterator ans = *this; + ++index; + return ans; + } + + const_iterator& operator--() { --index; return *this; } + const_iterator operator--(int) + { + const_iterator ans = *this; + --index; + return ans; + } + + const_iterator& operator+=(int j) { index += j; return *this; } + const_iterator& operator-=(int j) { index -= j; return *this; } + const_iterator operator+(int j) const { return const_iterator(buffer, index + j); } + const_iterator operator-(int j) const { return const_iterator(buffer, index - j); } + int operator-(const_iterator other) const + { + Q_ASSERT_X(buffer == other.buffer, "QCircularBuffer::const_iterator::operator-", "iterators use different buffers"); + return index - other.index; + } + + private: + const QCircularBuffer* buffer; + int index; + friend class QCircularBuffer; + }; + friend class const_iterator; + + iterator begin() { return iterator(this, 0); } + const_iterator begin() const { return const_iterator(this, 0); } + const_iterator constBegin() const { return const_iterator(this, 0); } + iterator end() { return iterator(this, d->size); } + const_iterator end() const { return const_iterator(this, d->size); } + const_iterator constEnd() const { return const_iterator(this, d->size); } + iterator insert(iterator before, int count, const T &value) + { + insert(before.index, count, value); + return iterator(this, before.index); + } + iterator insert(iterator before, const T &value) { return insert(before, 1, value); } + iterator erase(iterator begin, iterator end) + { + int count = end - begin; + remove(begin.index, count); + return iterator(this, end.index - count); + } + iterator erase(iterator pos) { return erase(pos, pos + 1); } + + // STL compatibility + typedef T value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef ptrdiff_t difference_type; + typedef iterator Iterator; + typedef const_iterator ConstIterator; + typedef int size_type; + + void push_back(const T &t) { append(t); } + void push_front(const T &t) { prepend(t); } + void pop_back() { Q_ASSERT(!isEmpty()); erase(end() - 1); } + void pop_front() { Q_ASSERT(!isEmpty()); erase(begin()); } + bool empty() const { return isEmpty(); } + T &front() { return first(); } + const T &front() const { return first(); } + T &back() { return last(); } + const T &back() const { return last(); } + + int refCount() const { return int(d->ref); } + + void append(const T &value); + + const T &at(int i) const + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::at", "index out of range"); + int index = (d->first + i) % d->capacity; + return d->data[ index ]; + } + + const T &operator[](int i) const + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::operator[]", "index out of range"); + int index = (d->first + i) % d->capacity; + return d->data[ index ]; + } + + T &operator[](int i) + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::operator[]", "index out of range"); + int index = (d->first + i) % d->capacity; + return d->data[ index ]; + } + + int capacity() const { return d->capacity; } + + void clear() { *this = QCircularBuffer(d->capacity); } + + bool contains(const T &value) const; + int count(const T &value) const; + int count() const { return size(); } + + array_range data() + { + if (d->size == 0) + return array_range(0, 0); + if (!isLinearised()) + linearise(); + return array_range(d->data + d->first, d->last - d->first + 1); + } + const_array_range data() const { return constData(); } + const_array_range constData() const + { + if (!isLinearised() || d->size == 0) + return const_array_range(0, 0); + return const_array_range(d->data + d->first, d->last - d->first + 1); + } + + array_range dataOne() + { + if (d->size == 0) + return array_range(0, 0); + if (isLinearised()) + return array_range(d->data + d->first, d->last - d->first + 1); + else + return array_range(d->data + d->first, d->capacity - d->first); + } + const_array_range dataOne() const { return constDataOne(); } + const_array_range constDataOne() const + { + if (d->size == 0) + return const_array_range(0, 0); + if (isLinearised()) + return const_array_range(d->data + d->first, d->last - d->first + 1); + else + return const_array_range(d->data + d->first, d->capacity - d->first); + } + + array_range dataTwo() + { + if (d->size == 0 || isLinearised()) + return array_range(0, 0); + return array_range(d->data, d->last + 1); + } + const_array_range dataTwo() const { return constDataTwo(); } + const_array_range constDataTwo() const + { + if (d->size == 0 || isLinearised()) + return const_array_range(0, 0); + return const_array_range(d->data, d->last + 1); + } + + bool endsWith(const T &value) const { return !isEmpty() && last() == value; } + QCircularBuffer& fill(const T &value, int size = -1); + T &first() { Q_ASSERT(!isEmpty()); return d->data[ d->first ]; } + const T &first() const { Q_ASSERT(!isEmpty()); return d->data[ d->first ]; } + int freeSize() const { return sizeAvailable(); } + + static QCircularBuffer fromList(const QList& list); + static QCircularBuffer fromVector(const QVector& vector); + + int indexOf(const T &value, int from = 0) const; + void insert(int i, const T &value) { insert(i, 1, value); }; + void insert(int i, int count, const T &value); + bool isEmpty() const { return d->size == 0; } + bool isFull() const { return d->size == d->capacity; } + bool isLinearised() const { return (d->last >= d->first); } + T &last() { Q_ASSERT(!isEmpty()); return d->data[ d->last ]; } + const T &last() const { Q_ASSERT(!isEmpty()); return d->data[ d->last ]; } + int lastIndexOf(const T &value, int from = -1) const; + void linearise(); + void prepend(const T &value); + void remove(int i) { remove(i, 1); } + void remove(int i, int count); + + void replace(int i, const T &value) + { + Q_ASSERT_X(i >= 0 && i < d->size, "QCircularBuffer::replace", "index out of range"); + const T copy(value); + (*this)[ i ] = copy; + } + + void reserve(int capacity) { setCapacity(capacity); } + void resize(int size); + void setCapacity(int capacity); + int size() const { return d->size; } + int sizeAvailable() const { return d->capacity - d->size; } + void squeeze() { setCapacity(size()); } + bool startsWith(const T &value) const { return !isEmpty() && first() == value; } + + QList toList() const; + QVector toVector() const; + + T value(int i) const + { + if (i < 0 || i >= d->size) + return T(); + return at(i); + } + + T value(int i, const T &defaultValue) const + { + if (i < 0 || i >= d->size) + return defaultValue; + return at(i); + } + + bool operator==(const QCircularBuffer other) const; + bool operator!=(const QCircularBuffer other) const { return !(*this == other); } + + QCircularBuffer& operator+=(const T &other) { append(other); return *this; } + QCircularBuffer& operator+=(const QCircularBuffer& other); + QCircularBuffer& operator+=(const QVector& other); + QCircularBuffer& operator+=(const QList& other); + + QCircularBuffer& operator<<(const T &other) { append(other); return *this; } + QCircularBuffer& operator<<(const QCircularBuffer& other) { *this += other; return *this; } + QCircularBuffer& operator<<(const QVector& other) { *this += other; return *this; } + QCircularBuffer& operator<<(const QList& other) { *this += other; return *this; } + +private: + QSharedDataPointer< CircularBufferData > d; +}; + +template +QCircularBuffer operator+(const QCircularBuffer& lhs, const QCircularBuffer& rhs); + + +template +QCircularBuffer::QCircularBuffer(int capacity) + : d(new CircularBufferData()) +{ + // Allocate some raw memory + d->data = d->allocate(capacity); + d->capacity = capacity; + + // Initialise the objects. If the type T is a complex type then we do this + // using the placement new operator. If the type T is not complex we simply + // use memset to initialise the memory to zero. + if (QTypeInfo::isComplex) { + T* b = d->data; + T* i = b + d->capacity; + while (i != b) + new (--i) T; + } else { + qMemSet(d->data, 0, capacity * sizeof(T)); + } +} + +template +QCircularBuffer::QCircularBuffer(int capacity, const T &value) + : d(new CircularBufferData()) +{ + // Allocate some raw memory + d->data = d->allocate(capacity); + d->capacity = capacity; + + // Initialise the objects. In this case we always use the placement new operator + T* b = d->data; + T* i = b + d->capacity; + while (i != b) + new (--i) T(value); + d->first = 0; + d->last = d->capacity - 1; + d->size = d->capacity; +} + +template +QCircularBuffer::QCircularBuffer(int capacity, int size, const T &value) + : d(new CircularBufferData()) +{ + Q_ASSERT_X(capacity >= size, "QCircularBuffer::QCircularBuffer(int capacity, int size, const T &value)", "size is greater than capacity"); + + // Allocate some raw memory + d->data = d->allocate(capacity); + d->capacity = capacity; + + // Initialise the objects that need to be set to the specified value. + // In this case we always use the placement new operator + T* b = d->data; + T* i = b + size; + while (i != b) + new (--i) T(value); + + // Initialise the remaining objects using the best method available + if (QTypeInfo::isComplex) { + T* b = d->data + size; + T* i = b + capacity - size; + while (i != b) + new (--i) T; + } else { + qMemSet(d->data + size, 0, (capacity - size) * sizeof(T)); + } + + d->first = 0; + d->last = size - 1; + d->size = size; +} + +template +void QCircularBuffer::append(const T &value) +{ + // If we have no capacity we do nothing + if (!d->capacity) + return; + + if (d->size == d->capacity) { + // Buffer is full. Overwrite earliest item and rotate + d->data[ d->first ] = value; + d->first = (++d->first % d->capacity); + d->last = (++d->last % d->capacity); + } else if (d->size != 0) { + // Buffer is partially full. Append data to end of array using appropriate method + int index = (d->first + d->size) % d->capacity; + if (QTypeInfo::isComplex) + new (d->data + index) T(value); + else + d->data[ index ] = value; + ++d->size; + ++d->last; + } else { + // Buffer is empty. Append data to end of array using appropriate method + d->size = 1; + d->first = d->last = 0; + if (QTypeInfo::isComplex) + new (d->data + d->first) T(value); + else + d->data[ d->first ] = value; + } +} + +template +bool QCircularBuffer::contains(const T &value) const +{ + if (isLinearised()) { + T* b = d->data + d->first; + T* i = b + d->size; + while (i != b) + if (*--i == value) + return true; + return false; + } else { + // Check the array from m_first to the end + T* b = d->data + d->first; + T* i = d->data + d->capacity; + while (i != b) + if (*--i == value) + return true; + + // Check array from 0 to m_end + b = d->data; + i = d->data + d->last + 1; + while (i != b) + if (*--i == value) + return true; + + return false; + } +} + +template +int QCircularBuffer::count(const T &value) const +{ + int c = 0; + if (isLinearised()) { + T* b = d->data + d->first; + T* i = b + d->size; + while (i != b) + if (*--i == value) + ++c; + } else { + // Check the array from m_first to the end + T* b = d->data + d->first; + T* i = d->data + d->capacity; + while (i != b) + if (*--i == value) + ++c; + + // Check array from 0 to m_end + b = d->data; + i = d->data + d->last + 1; + while (i != b) + if (*--i == value) + ++c; + } + return c; +} + +template +QCircularBuffer& QCircularBuffer::fill(const T &value, int size) +{ + Q_ASSERT_X(d->capacity >= size, "QCircularBuffer::fill", "size is greater than capacity"); + const T copy(value); + int oldSize = d->size; + d->size = (size < 0 ? d->size : size); + d->first = (size == 0 ? -1 : 0); + d->last = d->size - 1; + + // Copy item into array size times + if (d->size) { + T *b = d->data; + T *i = d->data + d->size; + while (i != b) + *--i = copy; + } + + if (d->size < oldSize) { + // Cleanup old items beyond end of new array + T *b = d->data + d->size; + T *i = d->data + oldSize; + while (i-- != b) { + i->~T(); + new (i) T(); + } + } + + return *this; +} + +template +QCircularBuffer QCircularBuffer::fromList(const QList& list) +{ + QCircularBuffer circ(list.size()); + for (int i = 0; i < list.size(); ++i) + circ.append(list.at(i)); + return circ; +} + +template +QCircularBuffer QCircularBuffer::fromVector(const QVector& vector) +{ + QCircularBuffer circ(vector.size()); + for (int i = 0; i < vector.size(); ++i) + circ.append(vector.at(i)); + return circ; +} + +template +int QCircularBuffer::indexOf(const T &value, int from) const +{ + Q_ASSERT_X(from < d->size, "QCircularBuffer::indexOf", "from is greater than last valid index"); + if (from < 0) + from = qMax(from + d->size, 0); + else if (from >= d->size) + from = d->size - 1; + for (int i = from; i < d->size; ++i) + if (at(i) == value) + return i; + return -1; +} + +template +void QCircularBuffer::insert(int i, int count, const T &value) +{ + Q_ASSERT_X(i >= 0 && i <= d->size, "QCircularBuffer::insert", "index out of range"); + + int freeCapacity = d->capacity - d->size; + + // Calculate number of elements that will actually be inserted. This + // depends upon where the insertion has been requested and any spare + // capacity left in the buffer. This is because elements at higher + // indices will be pushed to the right and will potentially wrap around + // to overwrite earlier elements. + int numToInsert = qMin(count, i + freeCapacity); + + // Calculate the number of elements at the beginning of the buffer that + // will be overwritten + int numToOverwrite = qMin(i, qMax(0, count - freeCapacity)); + + // Decide which way to shift to minimise the amount of copying required. + if (i < d->size / 2) { + // Inserting in lower half of buffer so we shift earlier items down + + // Shift data at the bottom end down. This may only be a subset if some + // of the early data is to be overwritten. + if (QTypeInfo::isStatic) { + int start = d->first + numToOverwrite; + int end = d->first + i - 1; + for (int j = start; j <= end; ++j) { + int srcIndex = j % d->capacity; + int dstIndex = (j - numToInsert + d->capacity) % d->capacity; + T* src = d->data + srcIndex; + T* dst = d->data + dstIndex; + + new (dst) T(*src); + } + } else { + // We have a movable type so a simple memcopy (or maybe two or + // three) will suffice to shift the data at the bottom end + int numToMove = i - numToOverwrite; + if (numToMove > 0) { + int srcBegin = (d->first + numToOverwrite) % d->capacity; + int srcEnd = (d->first + i - 1) % d->capacity; + int dstBegin = (srcBegin - numToInsert + d->capacity) % d->capacity; + int dstEnd = (srcEnd - numToInsert + d->capacity) % d->capacity; + + // Do we have any wrap-around problems to deal with? + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = abs(srcBegin - numToInsert); + memmove(d->data + d->capacity - wrapCount, d->data + srcBegin, wrapCount * sizeof(T)); + memmove(d->data, d->data + srcBegin + wrapCount, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = d->capacity - srcBegin; + memmove(d->data + dstBegin, d->data + d->capacity - wrapCount, wrapCount * sizeof(T)); + memmove(d->data + dstBegin + numToInsert, d->data, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = d->capacity - srcBegin; + memmove(d->data + dstBegin, d->data + d->capacity - srcWrapCount, srcWrapCount * sizeof(T)); + memmove(d->data + d->capacity - numToInsert, d->data, numToInsert * sizeof(T)); + memmove(d->data, d->data + numToInsert, (numToMove - srcWrapCount - numToInsert) * sizeof(T)); + } else { + // No wrap around - do a single memmove + memmove(d->data + dstBegin, d->data + srcBegin, numToMove * sizeof(T)); + } + } + } + + // Insert the new items + int end = d->first + i; + int start = end - numToInsert; + for (int j = start; j < end; ++j) { + T* p = d->data + ((j + d->capacity) % d->capacity); + new (p) T(value); + } + + // Adjust the first, last and size indices as needed. + // NB. The last index never changes in this regime. + d->size += qMin(count, freeCapacity); + d->first = (d->first - (numToInsert - numToOverwrite) + d->capacity) % d->capacity; + } else { + // Inserting in upper half of buffer so we shift later items up + + // Shift data at the top end up which may or may not overwrite some + // of the earliest data + if (QTypeInfo::isStatic) { + int start = d->first + d->size - 1; + int end = d->first + i; + for (int j = start; j >= end; j--) { + int srcIndex = j % d->capacity; + int dstIndex = (j + numToInsert) % d->capacity; + T* src = d->data + srcIndex; + T* dst = d->data + dstIndex; + + new (dst) T(*src); + } + } else { + // We have a movable type so a simple memcopy (or maybe two or + // three) will suffice to shift the data at the top end + int numToMove = d->size - i; + if (numToMove > 0) { + int srcBegin = (d->first + i) % d->capacity; + int srcEnd = d->last; + int dstBegin = (srcBegin + numToInsert) % d->capacity; + int dstEnd = (srcEnd + numToInsert) % d->capacity; + + // Do we have any wrap-around problems to deal with? + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = srcEnd + numToInsert - d->capacity + 1; + memmove(d->data, d->data + srcEnd - wrapCount + 1, wrapCount * sizeof(T)); + memmove(d->data + dstBegin, d->data + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = d->last + 1; + memmove(d->data + numToInsert, d->data, wrapCount * sizeof(T)); + memmove(d->data + dstBegin, d->data + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = d->last + 1; + memmove(d->data + numToInsert, d->data, srcWrapCount * sizeof(T)); + memmove(d->data, d->data + d->capacity - numToInsert, numToInsert * sizeof(T)); + memmove(d->data + dstBegin, d->data + srcBegin, (numToMove - srcWrapCount - numToInsert) * sizeof(T)); + } else { + // No wrap around - do a single memmove + memmove(d->data + dstBegin, d->data + srcBegin, numToMove * sizeof(T)); + } + } + } + + // Insert the new items + for (int j = d->first + i; j < d->first + i + numToInsert; ++j) { + T* p = d->data + (j % d->capacity); + new (p) T(value); + } + + // Adjust the first, last and size indices as needed + d->size += qMin(count, freeCapacity); + d->first = (d->first + numToOverwrite) % d->capacity; + d->last = (d->last + numToInsert) % d->capacity; + } +} + +template +int QCircularBuffer::lastIndexOf(const T &value, int from) const +{ + if (from < 0) + from = qMax(from + d->size, 0); + else if (from >= d->size) + from = d->size - 1; + for (int i = from; i >= 0; --i) + if (at(i) == value) + return i; + return -1; +} + +template +void QCircularBuffer::linearise() +{ + if (isLinearised()) + return; + + // Allocate some new raw memory + T* newData = d->allocate(d->capacity); + + // Copy across the elements from the original array... + // Copy items from m_first to the end of the array + T* b = d->data + d->first; + T* i = d->data + d->capacity; + T* j = newData + d->capacity - d->first; + while (i != b) + new (--j) T(*--i); + + // Copy items from the start of the array to m_last + b = d->data; + i = d->data + d->last + 1; + j = newData + d->size; + while (i != b) + new (--j) T(*--i); + + // Destroy the original items + if (QTypeInfo::isComplex) { + // The type is complex so we manually call the destructor for each item + // since we used the placement new operator to instantiate them + T* b = d->data; + T* i = b + d->capacity; + while (i-- != b) + i->~T(); + } + + // Release the raw memory + d->deallocate(d->data); + + // Assign the new memory to be our buffer data and fix indices + d->data = newData; + d->first = 0; + d->last = d->size - 1; +} + +template +void QCircularBuffer::prepend(const T &value) +{ + // If we have no capacity we do nothing + if (!d->capacity) + return; + + if (d->size == d->capacity) { + // Buffer is full. Overwrite last item and rotate + d->data[ d->last ] = value; + d->first = (--d->first + d->capacity) % d->capacity; + d->last = (--d->last + d->capacity) % d->capacity; + } else if (d->size != 0) { + // Buffer is partially full. Prepend data to start of array using appropriate method + d->first = (--d->first + d->capacity) % d->capacity; + ++d->size; + if (QTypeInfo::isComplex) + new (d->data + d->first) T(value); + else + d->data[ d->first ] = value; + } else { + // Buffer is empty. Prepend data to start of array using appropriate method + d->size = 1; + d->first = d->last = d->capacity - 1; + if (QTypeInfo::isComplex) + new (d->data + d->first) T(value); + else + d->data[ d->first ] = value; + } +} + +template +void QCircularBuffer::remove(int i, int count) +{ + Q_ASSERT_X(i >= 0 && count > 0 && i + count <= d->size, "QCircularBuffer::remove", "index out of range"); + + // Calculate the number of items that need to be moved downward + int numToMoveDown = d->size - count - i; + int numToMoveUp = i; + + if (numToMoveDown < numToMoveUp) { + // Move higher items down + int numToMove = numToMoveDown; + + if (QTypeInfo::isComplex) { + // Copy items down from higher positions + int start = d->first + i; + int end = start + numToMove; + for (int j = start; j < end ; ++j) { + T* src = d->data + ((j + count) % d->capacity); + T* dst = d->data + (j % d->capacity); + new (dst) T(*src); + } + + // Clean up items at end of buffer + for (int j = d->last; j > d->last - count; --j) { + T* p = d->data + ((j + d->capacity) % d->capacity); + p->~T(); + new (p) T(); + } + } else { + if (isLinearised()) { + // With a linearised buffer we can do a simple move and removal of items + memmove(d->data + d->last - numToMove - count + 1, d->data + d->last - numToMove + 1, numToMove * sizeof(T)); + qMemSet(d->data + d->last - count + 1, 0, count * sizeof(T)); + } else { + // With a non-linearised buffer we need to be careful of wrapping issues + int srcBegin = (d->last - numToMove + 1 + d->capacity) % d->capacity; + int srcEnd = d->last; + int dstBegin = (d->first + i) % d->capacity; + int dstEnd = (dstBegin + numToMove - 1) % d->capacity; + + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = d->capacity - srcBegin; + memmove(d->data + dstBegin, d->data + srcBegin, wrapCount * sizeof(T)); + memmove(d->data + dstBegin + wrapCount, d->data, (numToMove - wrapCount) * sizeof(T)); + } else if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = count - srcBegin; + memmove(d->data + d->capacity - wrapCount, d->data + srcBegin, wrapCount * sizeof(T)); + memmove(d->data, d->data + srcBegin + wrapCount, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = d->capacity - srcBegin; + memmove(d->data + dstBegin, d->data + srcBegin, srcWrapCount * sizeof(T)); + memmove(d->data + dstBegin + srcWrapCount, d->data, count * sizeof(T)); + memmove(d->data, d->data + count, (numToMove - srcWrapCount - count) * sizeof(T)); + } else { + // No wrap around, so we can do this in one hit + memmove(d->data + dstBegin, d->data + srcBegin, numToMove * sizeof(T)); + } + + // We potentially have a disjoint region that needs zeroing + int zeroStart = (d->last - count + d->capacity + 1) % d->capacity; + int zeroEnd = d->last; + if (zeroEnd < zeroStart) { + // Region to be zeroed wraps. Do it in two steps. + qMemSet(d->data, 0, (d->last + 1) * sizeof(T)); + qMemSet(d->data + zeroStart, 0, (count - d->last - 1) * sizeof(T)); + } else { + // Region to be zeroed is contiguous + qMemSet(d->data + zeroStart, 0, count * sizeof(T)); + } + } + } + + // Adjust the indices + d->size -= count; + d->last = (d->last - count + d->capacity) % d->capacity; + } else { + // Move lower items up + int numToMove = numToMoveUp; + + if (QTypeInfo::isComplex) { + // Copy items up from lower positions + int start = d->first + i - 1; + int end = start - numToMove; + for (int j = start; j > end ; --j) { + T* src = d->data + ((j + d->capacity) % d->capacity); + T* dst = d->data + ((j + d->capacity + count) % d->capacity); + new (dst) T(*src); + } + + // Clean up items at start of buffer + for (int j = d->first; j < d->first + count; ++j) { + T* p = d->data + (j % d->capacity); + p->~T(); + new (p) T(); + } + } else { + if (isLinearised()) { + // With a linearised buffer we can do a simple move and removal of items + memmove(d->data + d->first + count, d->data + d->first, numToMove * sizeof(T)); + qMemSet(d->data + d->first, 0, count * sizeof(T)); + } else { + // With a non-linearised buffer we need to be careful of wrapping issues + int srcBegin = d->first; + int srcEnd = (srcBegin + numToMove - 1) % d->capacity; + int dstBegin = (srcBegin + count) % d->capacity; + int dstEnd = (dstBegin + numToMove - 1) % d->capacity; + + bool srcRegionWraps = (srcEnd < srcBegin); + bool dstRegionWraps = (dstEnd < dstBegin); + if (srcRegionWraps && !dstRegionWraps) { + // Source region wraps so do the move in two steps + int wrapCount = srcEnd + 1; + memmove(d->data + dstEnd - wrapCount + 1, d->data, wrapCount * sizeof(T)); + memmove(d->data + dstBegin, d->data + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (!srcRegionWraps && dstRegionWraps) { + // Destination region wraps so do the move in two steps + int wrapCount = dstEnd + 1; + memmove(d->data, d->data + srcEnd - wrapCount + 1, wrapCount * sizeof(T)); + memmove(d->data + dstBegin, d->data + srcBegin, (numToMove - wrapCount) * sizeof(T)); + } else if (srcRegionWraps && dstRegionWraps) { + // Source and destination regions wrap so we have to do this in three steps + int srcWrapCount = srcEnd + 1; + memmove(d->data + dstEnd - srcWrapCount + 1, d->data, srcWrapCount * sizeof(T)); + memmove(d->data, d->data + d->capacity - count, count * sizeof(T)); + memmove(d->data + dstBegin, d->data + srcBegin, (numToMove - srcWrapCount - count) * sizeof(T)); + } else { + // No wrap around, so we can do this in one hit + memmove(d->data + dstBegin, d->data + srcBegin, numToMove * sizeof(T)); + } + + // We potentially have a disjoint region that needs zeroing + int zeroStart = d->first; + int zeroEnd = (zeroStart + count - 1) % d->capacity; + if (zeroEnd < zeroStart) { + // Region to be zeroed wraps. Do it in two steps. + qMemSet(d->data + zeroStart, 0, (d->capacity - d->first) * sizeof(T)); + qMemSet(d->data, 0, (count - d->capacity + d->first) * sizeof(T)); + } else { + // Region to be zeroed is contiguous + qMemSet(d->data + zeroStart, 0, count * sizeof(T)); + } + } + } + + // Adjust the indices + d->size -= count; + d->first = (d->first + count) % d->capacity; + } +} + +template +void QCircularBuffer::setCapacity(int capacity) +{ + if (capacity == d->capacity) + return; + + // Allocate some new raw memory + T* newData = d->allocate(capacity); + + // How many items can we copy across? + int newSize = qMin(d->size, capacity); + + if (QTypeInfo::isComplex) { + // Copy across the elements from the original array + for (int i = 0; i < newSize; ++i) { + T* src = d->data + ((d->first + i) % d->capacity); + T* dst = newData + i; + new (dst) T(*src); + } + + // Initialise any memory outside of the valid buffer (ie the unused items) + for (int i = newSize; i < capacity; ++i) + new (newData + i) T(); + + // Destroy the original items. + // The type is complex so we manually call the destructor for each item + // since we used the placement new operator to instantiate them + T* b = d->data; + T* i = b + d->capacity; + while (i-- != b) + i->~T(); + } else { + // Copy across the elements from the original array. The source region + // potentially wraps so we may have to do this in one or two steps + if (isLinearised()) { + memmove(newData, d->data + d->first, newSize * sizeof(T)); + } else { + int step1Size = qMin(newSize, d->capacity - d->first); + memmove(newData, d->data + d->first, step1Size * sizeof(T)); + int step2Size = qMax(0, qMin(newSize - d->capacity + d->first, d->last + 1)); + memmove(newData + step1Size, d->data, step2Size * sizeof(T)); + } + + // Initialise any memory outside of the valid buffer (ie the unused items) + qMemSet(newData + newSize, 0, (capacity - newSize) * sizeof(T)); + } + + // Release the raw memory for the old array + d->deallocate(d->data); + + // Assign the new memory to be our buffer data and fix indices + d->data = newData; + d->capacity = capacity; + d->first = 0; + d->size = newSize; + d->last = d->size - 1; +} + +template +void QCircularBuffer::resize(int size) +{ + Q_ASSERT_X(size >= 0 && size <= d->capacity, "QCircularBuffer::resize", "size out of range"); + + if (size < d->size) { + remove(size, d->size - size); + } else if (size > d->size) { + T t; + insert(d->size, size - d->size, t); + } +} + +template +bool QCircularBuffer::operator==(const QCircularBuffer other) const +{ + if (capacity() != other.capacity() || size() != other.size()) + return false; + if (d == other.d) + return true; + int count = size(); + for (int i = 0; i < count; ++i) + if (at(i) != other.at(i)) + return false; + return true; +} + +template +QCircularBuffer& QCircularBuffer::operator+=(const QCircularBuffer& other) +{ + // How many items do we need to copy? No point in ever copying across a number + // greater than capacity + int numToCopy = qMin(other.size(), d->capacity); + int offset = other.size() - numToCopy; + for (int i = 0; i < numToCopy; ++i) + append(other.at(offset + i)); + return *this; +} + +template +QCircularBuffer& QCircularBuffer::operator+=(const QVector& other) +{ + // How many items do we need to copy? No point in ever copying across a number + // greater than capacity + int numToCopy = qMin(other.size(), d->capacity); + int offset = other.size() - numToCopy; + for (int i = 0; i < numToCopy; ++i) + append(other.at(offset + i)); + return *this; +} + +template +QCircularBuffer& QCircularBuffer::operator+=(const QList& other) +{ + // How many items do we need to copy? No point in ever copying across a number + // greater than capacity + int numToCopy = qMin(other.size(), d->capacity); + int offset = other.size() - numToCopy; + for (int i = 0; i < numToCopy; ++i) + append(other.at(offset + i)); + return *this; +} + +template +QList QCircularBuffer::toList() const +{ + QList list; + for (int i = 0; i < size(); ++i) + list.append(at(i)); + return list; +} + +template +QVector QCircularBuffer::toVector() const +{ + QVector vector; + for (int i = 0; i < size(); ++i) + vector.append(at(i)); + return vector; +} + +template +QCircularBuffer operator+(const QCircularBuffer& lhs, const QCircularBuffer& rhs) +{ + QCircularBuffer circ(lhs.size() + rhs.size()); + for (int i = 0; i < lhs.size(); ++i) + circ.append(lhs.at(i)); + for (int i = 0; i < rhs.size(); ++i) + circ.append(rhs.at(i)); + return circ; +} + +Q_DECLARE_SEQUENTIAL_ITERATOR(CircularBuffer) +Q_DECLARE_MUTABLE_SEQUENTIAL_ITERATOR(CircularBuffer) + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QCIRCULARBUFFER_H diff --git a/Source/src/cusdr_agcWidget.cpp b/Source/src/cusdr_agcWidget.cpp new file mode 100644 index 0000000..3fc7dcb --- /dev/null +++ b/Source/src/cusdr_agcWidget.cpp @@ -0,0 +1,642 @@ +/** +* @file cusdr_agcWidget.h +* @brief AGC options widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-29 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#define LOG_GRAPHIC_OPTIONS_WIDGET + +//#include +//#include +//#include +//#include +//#include +#include + +#include "cusdr_agcWidget.h" + +#define btn_height 15 +#define btn_width 70 +#define btn_widths 32 +#define btn_width2 52 +#define btn_width3 60 + +AGCOptionsWidget::AGCOptionsWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(set->getDataEngineState()) + //, m_panadapterMode(set->getPanadapterMode()) + //, m_waterColorScheme(set->getWaterfallColorScheme()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) + , m_btnSpacing(5) + , m_currentReceiver(set->getCurrentReceiver()) + , m_sampleRate(set->getSampleRate()) + , m_mouseOver(false) +{ + //setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 0, 4, 0); + setMouseTracking(true); + + m_rxDataList = set->getReceiverDataList(); + + m_agcMode = m_rxDataList.at(0).agcMode; + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + createAgcModeBtnGroup(); + createAgcOptionsGroup(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setMargin(0); + hbox1->addStretch(); + hbox1->addWidget(agcModeGroupBox); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addStretch(); + hbox2->addWidget(agcOptionsGroupBox); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addStretch(); + setLayout(mainLayout); + + agcModeChanged(this, 0, m_agcMode, false); + + setupConnections(); +} + +AGCOptionsWidget::~AGCOptionsWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize AGCOptionsWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize AGCOptionsWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void AGCOptionsWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(graphicModeChanged( +// QObject *, +// QSDRGraphics::_Panadapter, +// QSDRGraphics::_WaterfallColorScheme)), +// this, +// SLOT(graphicModeChanged( +// QObject *, +// QSDRGraphics::_Panadapter, +// QSDRGraphics::_WaterfallColorScheme))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(agcModeChanged(QObject *, int, AGCMode, bool)), + this, + SLOT(agcModeChanged(QObject *, int, AGCMode, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(agcHangThresholdSliderChanged(QObject *, int, qreal)), + this, + SLOT(setAGCHangThresholdSlider(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcMaximumGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCMaximumGain_dB(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcFixedGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCFixedGain_dB(QObject *, int, qreal))); +} + +void AGCOptionsWidget::createAgcModeBtnGroup() { + + agcOFF = new AeroButton("Off", this); + agcOFF->setRoundness(0); + agcOFF->setFixedSize(btn_widths, btn_height); + agcOFF->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcOFF); + CHECKED_CONNECT(agcOFF, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcLONG = new AeroButton("Long", this); + agcLONG->setRoundness(0); + agcLONG->setFixedSize(btn_widths, btn_height); + agcLONG->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcLONG); + CHECKED_CONNECT(agcLONG, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcSLOW = new AeroButton("Slow", this); + agcSLOW->setRoundness(0); + agcSLOW->setFixedSize(btn_widths, btn_height); + agcSLOW->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcSLOW); + CHECKED_CONNECT(agcSLOW, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcMED = new AeroButton("Med", this); + agcMED->setRoundness(0); + agcMED->setFixedSize(btn_widths, btn_height); + agcMED->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcMED); + CHECKED_CONNECT(agcMED, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcFAST = new AeroButton("Fast", this); + agcFAST->setRoundness(0); + agcFAST->setFixedSize(btn_widths, btn_height); + agcFAST->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcFAST); + CHECKED_CONNECT(agcFAST, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcUSER = new AeroButton("User", this); + agcUSER->setRoundness(0); + agcUSER->setFixedSize(btn_widths, btn_height); + agcUSER->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcUSER); + CHECKED_CONNECT(agcUSER, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + QGridLayout *layout = new QGridLayout(); + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(agcOFF, 0, 0); + layout->addWidget(agcLONG, 0, 1); + layout->addWidget(agcSLOW, 0, 2); + layout->addWidget(agcMED, 0, 3); + layout->addWidget(agcFAST, 0, 4); + layout->addWidget(agcUSER, 0, 5); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + agcModeGroupBox = new QGroupBox(tr("AGC Mode"), this); + agcModeGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + agcModeGroupBox->setLayout(vbox); + agcModeGroupBox->setStyleSheet(set->getWidgetStyle()); + //agcModeGroupBox->setMinimumWidth(175); + agcModeGroupBox->setFont(QFont("Arial", 8)); +} + +void AGCOptionsWidget::createAgcOptionsGroup() { + + m_slopeSpinBox = new QSpinBox(this); + m_slopeSpinBox->setMinimum(0); + m_slopeSpinBox->setMaximum(20); + m_slopeSpinBox->setSingleStep(1); + m_slopeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_slopeSpinBox->setMinimumWidth(60); + m_slopeSpinBox->setValue((int) m_rxDataList.at(m_currentReceiver).agcVariableGain); + + CHECKED_CONNECT( + m_slopeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(slopeChanged(int))); + + m_slopeLabel = new QLabel("Slope (dB):", this); + m_slopeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_slopeLabel->setStyleSheet(set->getLabelStyle()); + + + m_maxGainSpinBox = new QSpinBox(this); + m_maxGainSpinBox->setMinimum(-60); + m_maxGainSpinBox->setMaximum(120); + m_maxGainSpinBox->setSingleStep(1); + m_maxGainSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_maxGainSpinBox->setMinimumWidth(60); + m_maxGainSpinBox->setValue((int) m_rxDataList.at(m_currentReceiver).agcMaximumGain_dB); + + CHECKED_CONNECT( + m_maxGainSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(maxGainChanged(int))); + + m_maxGainLabel = new QLabel("Max Gain (dB):", this); + m_maxGainLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_maxGainLabel->setStyleSheet(set->getLabelStyle()); + + + m_attackTimeSpinBox = new QSpinBox(this); + m_attackTimeSpinBox->setMinimum(1); + m_attackTimeSpinBox->setMaximum(10); + m_attackTimeSpinBox->setSingleStep(1); + m_attackTimeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_attackTimeSpinBox->setMinimumWidth(60); + m_attackTimeSpinBox->setValue((int) m_rxDataList.at(m_currentReceiver).agcAttackTime * 1000); + + CHECKED_CONNECT( + m_attackTimeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(attackTimeChanged(int))); + + m_attackTimeLabel = new QLabel("Attack Time (ms):", this); + m_attackTimeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_attackTimeLabel->setStyleSheet(set->getLabelStyle()); + + + m_decayTimeSpinBox = new QSpinBox(this); + m_decayTimeSpinBox->setMinimum(10); + m_decayTimeSpinBox->setMaximum(5000); + m_decayTimeSpinBox->setSingleStep(1); + m_decayTimeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_decayTimeSpinBox->setMinimumWidth(60); + m_decayTimeSpinBox->setValue((int) (m_rxDataList.at(m_currentReceiver).agcDecayTime * 1000)); + + CHECKED_CONNECT( + m_decayTimeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(decayTimeChanged(int))); + + m_decayTimeLabel = new QLabel("Decay Time (ms):", this); + m_decayTimeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_decayTimeLabel->setStyleSheet(set->getLabelStyle()); + + + m_hangTimeSpinBox = new QSpinBox(this); + m_hangTimeSpinBox->setMinimum(10); + m_hangTimeSpinBox->setMaximum(5000); + m_hangTimeSpinBox->setSingleStep(1); + m_hangTimeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_hangTimeSpinBox->setMinimumWidth(60); + m_hangTimeSpinBox->setValue((int) (m_rxDataList.at(m_currentReceiver).agcHangTime * 1000)); + + CHECKED_CONNECT( + m_hangTimeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(hangTimeChanged(int))); + + m_hangTimeLabel = new QLabel("Hang Time (ms):", this); + m_hangTimeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_hangTimeLabel->setStyleSheet(set->getLabelStyle()); + + m_hangThresholdSlider = new QSlider(Qt::Horizontal, this); + m_hangThresholdSlider->setTickPosition(QSlider::NoTicks); + m_hangThresholdSlider->setFixedSize(190, 12); + m_hangThresholdSlider->setSingleStep(1); + m_hangThresholdSlider->setRange(0, 100); + m_hangThresholdSlider->setValue(0); + m_hangThresholdSlider->setStyleSheet(set->getVolSliderStyle()); + + CHECKED_CONNECT( + m_hangThresholdSlider, + SIGNAL(valueChanged(int)), + this, + SLOT(hangThresholdValueChanged(int))); + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect(" 100 ").width(); + + QString str = "%1 "; + m_hangThresholdValueLabel = new QLabel(str.arg(0, 2, 10, QLatin1Char(' ')), this); + m_hangThresholdValueLabel->setFont(m_fonts.smallFont); + m_hangThresholdValueLabel->setFixedSize(fontMaxWidth, 12); + m_hangThresholdValueLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_hangThresholdValueLabel->setStyleSheet(set->getSliderLabelStyle()); + + m_hangThresholdLabel = new QLabel("Hang Threshold:", this); + m_hangThresholdLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_hangThresholdLabel->setStyleSheet(set->getLabelStyle()); + + + m_fixedGainSpinBox = new QSpinBox(this); + m_fixedGainSpinBox->setMinimum(-20); + m_fixedGainSpinBox->setMaximum(120); + m_fixedGainSpinBox->setSingleStep(1); + m_fixedGainSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_fixedGainSpinBox->setMinimumWidth(60); + m_fixedGainSpinBox->setValue((int) m_rxDataList.at(m_currentReceiver).agcFixedGain_dB); + + CHECKED_CONNECT( + m_fixedGainSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(fixedGainChanged(int))); + + m_fixedGainLabel = new QLabel("Fixed Gain (dB):", this); + m_fixedGainLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_fixedGainLabel->setStyleSheet(set->getLabelStyle()); + + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addWidget(m_slopeLabel); + hbox1->addStretch(); + hbox1->addWidget(m_slopeSpinBox); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(4); + hbox2->addWidget(m_maxGainLabel); + hbox2->addStretch(); + hbox2->addWidget(m_maxGainSpinBox); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(4); + hbox3->addWidget(m_attackTimeLabel); + hbox3->addStretch(); + hbox3->addWidget(m_attackTimeSpinBox); + + QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(4); + hbox4->addWidget(m_decayTimeLabel); + hbox4->addStretch(); + hbox4->addWidget(m_decayTimeSpinBox); + + QHBoxLayout *hbox5 = new QHBoxLayout(); + hbox5->setSpacing(4); + hbox5->addWidget(m_hangTimeLabel); + hbox5->addStretch(); + hbox5->addWidget(m_hangTimeSpinBox); + + QHBoxLayout *hbox6 = new QHBoxLayout(); + hbox6->setSpacing(4); + hbox6->addWidget(m_fixedGainLabel); + hbox6->addStretch(); + hbox6->addWidget(m_fixedGainSpinBox); + + QHBoxLayout *hbox7 = new QHBoxLayout(); + hbox7->setSpacing(4); + hbox7->addWidget(m_hangThresholdLabel); + hbox7->addStretch(); + //hbox7->addWidget(m_fixedGainSpinBox); + + QHBoxLayout *hbox8 = new QHBoxLayout; + hbox8->setSpacing(0); + hbox8->setMargin(0); + hbox8->addStretch(); + hbox8->addWidget(m_hangThresholdSlider); + hbox8->addWidget(m_hangThresholdValueLabel); + hbox8->addStretch(); + + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + vbox->addLayout(hbox3); + vbox->addLayout(hbox4); + vbox->addLayout(hbox5); + vbox->addLayout(hbox6); + vbox->addSpacing(20); + vbox->addLayout(hbox7); + vbox->addSpacing(4); + vbox->addLayout(hbox8); + + agcOptionsGroupBox = new QGroupBox(tr("AGC Options"), this); + agcOptionsGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + agcOptionsGroupBox->setLayout(vbox); + agcOptionsGroupBox->setStyleSheet(set->getWidgetStyle()); + //agcModeGroupBox->setMinimumWidth(175); + agcOptionsGroupBox->setFont(QFont("Arial", 8)); +} + +void AGCOptionsWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; + + update(); +} + +void AGCOptionsWidget::agcModeChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + int btn = agcModeBtnList.indexOf(button); + + foreach(AeroButton *btn, agcModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + set->setAGCMode(this, m_currentReceiver, (AGCMode) btn); + m_agcMode = (AGCMode) btn; + + button->setBtnState(AeroButton::ON); + button->update(); +} + +void AGCOptionsWidget::agcModeChanged(QObject *sender, int rx, AGCMode mode, bool hang) { + + Q_UNUSED(sender) + Q_UNUSED(hang) + + if (m_currentReceiver != rx) return; + m_agcMode = mode; + + foreach(AeroButton *btn, agcModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + agcModeBtnList.at(mode)->setBtnState(AeroButton::ON); + agcModeBtnList.at(mode)->update(); + + if (mode == (AGCMode) agcUser) { + + m_attackTimeSpinBox->setEnabled(true); + m_decayTimeSpinBox->setEnabled(true); + m_hangTimeSpinBox->setEnabled(true); + } + else { + + m_attackTimeSpinBox->setEnabled(false); + m_decayTimeSpinBox->setEnabled(false); + m_hangTimeSpinBox->setEnabled(false); + } +} + +void AGCOptionsWidget::slopeChanged(int value) { + + set->setAGCVariableGain_dB(this, set->getCurrentReceiver(), (qreal)value); +} + +void AGCOptionsWidget::maxGainChanged(int value) { + + int rx = set->getCurrentReceiver(); + set->setAGCMaximumGain_dB(this, rx, (qreal) value); +} + +void AGCOptionsWidget::setAGCMaximumGain_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + + m_maxGainSpinBox->blockSignals(true); + m_maxGainSpinBox->setValue((int) value); + m_maxGainSpinBox->blockSignals(false); +} + +void AGCOptionsWidget::fixedGainChanged(int value) { + + int rx = set->getCurrentReceiver(); + set->setAGCFixedGain_dB(this, rx, (qreal) value); +} + +void AGCOptionsWidget::setAGCFixedGain_dB(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + + m_fixedGainSpinBox->blockSignals(true); + m_fixedGainSpinBox->setValue((int) value); + m_fixedGainSpinBox->blockSignals(false); +} + +void AGCOptionsWidget::attackTimeChanged(int value) { + + set->setAGCAttackTime(this, set->getCurrentReceiver(), value/1000.0); +} + +void AGCOptionsWidget::decayTimeChanged(int value) { + + set->setAGCDecayTime(this, set->getCurrentReceiver(), value/1000.0); +} + +void AGCOptionsWidget::hangTimeChanged(int value) { + + set->setAGCHangTime(this, set->getCurrentReceiver(), value/1000.0); +} + +void AGCOptionsWidget::hangThresholdValueChanged(int value) { + + QString str = " %1 "; + m_hangThresholdValueLabel->setText(str.arg(value, 2, 10, QLatin1Char(' '))); + + set->setAGCHangThreshold(this, set->getCurrentReceiver(), value); +} + +void AGCOptionsWidget::setAGCHangThresholdSlider(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + + m_hangThresholdSlider->blockSignals(true); + m_hangThresholdSlider->setValue((int) value); + m_hangThresholdSlider->blockSignals(false); + + QString str = " %1 "; + m_hangThresholdValueLabel->setText(str.arg((int)value, 2, 10, QLatin1Char(' '))); +} + +void AGCOptionsWidget::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; + //int currentValue = m_framesPerSecondSpinBox->value(); + + //m_framesPerSecondSpinBox->setMaximum(m_sampleRate/1000); + + //if (currentValue > m_sampleRate/1000) { + + // m_framesPerSecondSpinBox->setValue(m_sampleRate/1000); + // set->setFramesPerSecond(value); + //} +} + +void AGCOptionsWidget::setCurrentReceiver(QObject *sender, int rx) { + + Q_UNUSED(sender) + + if (m_currentReceiver == rx) return; + m_currentReceiver = rx; + + if (m_agcMode != m_rxDataList.at(rx).agcMode) { + m_agcMode = m_rxDataList.at(rx).agcMode; + } +} diff --git a/Source/src/cusdr_agcWidget.h b/Source/src/cusdr_agcWidget.h new file mode 100644 index 0000000..a83805b --- /dev/null +++ b/Source/src/cusdr_agcWidget.h @@ -0,0 +1,165 @@ +/** +* @file cusdr_agcWidget.h +* @brief AGC options widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-29 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_AGC_OPTIONS_WIDGET_H +#define _CUSDR_AGC_OPTIONS_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" + + +class AGCOptionsWidget : public QWidget { + + Q_OBJECT + +public: + AGCOptionsWidget(QWidget *parent = 0); + ~AGCOptionsWidget(); + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + +private: + Settings *set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + //QSDRGraphics::_Panadapter m_panadapterMode; + //QSDRGraphics::_WfScheme m_waterColorScheme; + + AGCMode m_agcMode; + + QList m_rxDataList; + + CFonts *fonts; + TFonts m_fonts; + + QString m_menu_style; + QString m_callSingText; + + QGroupBox *agcModeGroupBox; + QGroupBox *agcOptionsGroupBox; + + AeroButton *agcOFF; + AeroButton *agcLONG; + AeroButton *agcSLOW; + AeroButton *agcMED; + AeroButton *agcFAST; + AeroButton *agcUSER; + + QList agcModeBtnList; + + QLineEdit *callSignLineEdit; + + QSlider *m_hangThresholdSlider; + + QSpinBox *m_slopeSpinBox; + QSpinBox *m_maxGainSpinBox; + QSpinBox *m_attackTimeSpinBox; + QSpinBox *m_decayTimeSpinBox; + QSpinBox *m_hangTimeSpinBox; + QSpinBox *m_fixedGainSpinBox; + + QLabel *m_slopeLabel; + QLabel *m_maxGainLabel; + QLabel *m_attackTimeLabel; + QLabel *m_decayTimeLabel; + QLabel *m_hangTimeLabel; + QLabel *m_fixedGainLabel; + QLabel *m_hangThresholdLabel; + QLabel *m_hangThresholdValueLabel; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_btnSpacing; + int m_fontHeight; + int m_maxFontWidth; + int m_currentReceiver; + int m_sampleRate; + int m_agcHangThreshold; + + bool m_mouseOver; + + //qreal m_agcSlope; + qreal m_agcMaxGain; + qreal m_agcAttackTime; + qreal m_agcDecayTime; + qreal m_agcHangTime; + qreal m_agcFixedGain; + + + + void setupConnections(); + void createAgcModeBtnGroup(); + void createAgcOptionsGroup(); +// void createFPSGroupBox(); +// void createPanSpectrumOptions(); +// void createWaterfallSpectrumOptions(); +// void createSMeterOptions(); +// void createColorChooserWidget(); +// void createCallSignEditor(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setCurrentReceiver(QObject *sender, int rx); + void sampleRateChanged(QObject *sender, int value); + void agcModeChanged(QObject *sender, int rx, AGCMode mode, bool value); + void agcModeChangedByBtn(); + void slopeChanged(int value); + void maxGainChanged(int value); + void attackTimeChanged(int value); + void decayTimeChanged(int value); + void hangTimeChanged(int value); + void fixedGainChanged(int value); + void hangThresholdValueChanged(int value); + void setAGCHangThresholdSlider(QObject *sender, int rx, qreal value); + void setAGCMaximumGain_dB(QObject *sender, int rx, qreal value); + void setAGCFixedGain_dB(QObject *sender, int rx, qreal value); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString ); +}; + +#endif // _CUSDR_AGC_OPTIONS_WIDGET_H diff --git a/Source/src/cusdr_alexAntennaWidget.cpp b/Source/src/cusdr_alexAntennaWidget.cpp new file mode 100644 index 0000000..29e9035 --- /dev/null +++ b/Source/src/cusdr_alexAntennaWidget.cpp @@ -0,0 +1,491 @@ +/** +* @file cusdr_alexAntennaWidget.cpp +* @brief Alexiares antenna settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-09 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_ALEX_WIDGET + +#include +#include +#include +#include +#include + +#include "cusdr_alexAntennaWidget.h" + +#define btn_height 15 +#define btn_width 16//20 +#define btn_width2 24//28 +#define btn_width3 45 + +AlexAntennaWidget::AlexAntennaWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(0) + , m_numberOfBands(MAX_BANDS) +{ + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(2, 2, 12, 0); + setMouseTracking(true); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + +// //QFont titleFont; +// m_normalFont.setStyleStrategy(QFont::PreferQuality); +// m_normalFont.setFixedPitch(true); +// #ifdef Q_OS_MAC +// m_titleFont.setPixelSize(11); +// m_titleFont.setFamily("Arial"); +// //m_smallFont.setBold(true); +// #endif +// #ifdef Q_OS_WIN +// m_normalFont.setPixelSize(11); +// m_normalFont.setFamily("Arial"); +// //m_smallFont.setBold(true); +// //m_smallFont.setItalic(true); +// #endif + +// m_smallFont.setStyleStrategy(QFont::PreferAntialias); +// m_smallFont.setFixedPitch(true); +// #ifdef Q_OS_MAC +// m_smallFont.setPixelSize(9); +// m_smallFont.setFamily("Arial"); +// //m_smallFont.setBold(true); +// #endif +// #ifdef Q_OS_WIN +// m_smallFont.setPixelSize(9); +// m_smallFont.setFamily("Arial"); +// //m_smallFont.setBold(true); +// //m_smallFont.setItalic(true); +// #endif + + createAntennasGroup(); + + // set main layout + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 4, 0); + hbox1->addWidget(antennaGroup); + + mainLayout->addLayout(hbox1); + mainLayout->addStretch(); + + setLayout(mainLayout); + + setAlexValues(); + setupConnections(); +} + +AlexAntennaWidget::~AlexAntennaWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void AlexAntennaWidget::setupConnections() { + + /* + CHECKED_CONNECT( + set, + SIGNAL(alexStateChanged(int, int)), + this, + SLOT(alexStateChanged(int, int))); +*/ +} + +void AlexAntennaWidget::createAntennasGroup() { + + QLabel *emptyLabel1 = new QLabel(" ", this); + emptyLabel1->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel1->setStyleSheet(set->getLabelStyle()); + + QLabel *emptyLabel2 = new QLabel(" ", this); + emptyLabel2->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel2->setStyleSheet(set->getLabelStyle()); + + QLabel *emptyLabel3 = new QLabel(" ", this); + emptyLabel3->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel3->setStyleSheet(set->getLabelStyle()); + + QLabel *antRxLabel = new QLabel("Rx Ant", this); + antRxLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + antRxLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *rxAuxLabel = new QLabel("Rx Aux", this); + rxAuxLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + rxAuxLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *antTxLabel = new QLabel("Tx Ant", this); + antTxLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + antTxLabel->setStyleSheet(set->getLabelStyle()); + + // band label + QStringList bandNames; + bandNames << "2200m" << "630m" << "160 m" << "80 m" << "60 m" << "40 m" << "30 m" << "20 m" << "17 m" << "15 m" << "12 m" << "10 m" << "6 m" << "gen"; + + QList bandLabelList; + + for (int i = 0; i < m_numberOfBands; i++) { + + QLabel *label = new QLabel(bandNames.at(i), this); + label->setFrameStyle(QFrame::Box | QFrame::Raised); + label->setStyleSheet(set->getLabelStyle()); + + bandLabelList << label; + } + + + // antennas 1,2, and 3 button lists + for (int i = 0; i < m_numberOfBands; i++) { + + AeroButton *btn = new AeroButton("1", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + antenna1BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(rxAntBtnClicked())); + + btn = new AeroButton("2", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + antenna2BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(rxAntBtnClicked())); + + btn = new AeroButton("3", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + antenna3BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(rxAntBtnClicked())); + } + + for (int i = 0; i < m_numberOfBands; i++) { + + QList btnList; + btnList << antenna1BtnList.at(i) << antenna2BtnList.at(i) << antenna3BtnList.at(i); + + bandBtnMatrix << btnList; + } + + // Rx Aux 1,2, and XV button lists + for (int i = 0; i < m_numberOfBands; i++) { + + AeroButton *btn = new AeroButton("1", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + rx1BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(rxAuxBtnClicked())); + + btn = new AeroButton("2", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + rx2BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(rxAuxBtnClicked())); + + btn = new AeroButton("XV", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + xvBtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(rxAuxBtnClicked())); + } + + for (int i = 0; i < m_numberOfBands; i++) { + + QList btnList; + btnList << rx1BtnList.at(i) << rx2BtnList.at(i) << xvBtnList.at(i); + + bandBtnRxMatrix << btnList; + } + + // Tx 1,2, and 3 button lists + for (int i = 0; i < m_numberOfBands; i++) { + + AeroButton *btn = new AeroButton("1", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + tx1BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(txAntBtnClicked())); + + btn = new AeroButton("2", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + tx2BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(txAntBtnClicked())); + + btn = new AeroButton("3", this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + + tx3BtnList << btn; + + CHECKED_CONNECT(btn, SIGNAL(clicked()), this, SLOT(txAntBtnClicked())); + } + + for (int i = 0; i < m_numberOfBands; i++) { + + QList btnList; + btnList << tx1BtnList.at(i) << tx2BtnList.at(i) << tx3BtnList.at(i); + + bandBtnTxMatrix << btnList; + } + + QGridLayout* grid = new QGridLayout(this); + grid->setVerticalSpacing(1); + grid->setHorizontalSpacing(1); + grid->setContentsMargins(3, 7, 5, 7); + + grid->addWidget(emptyLabel1, 0, 0, 1, 2, Qt::AlignLeft); + grid->addWidget(antRxLabel, 0, 2, 1, 3, Qt::AlignCenter); + grid->addWidget(emptyLabel2, 0, 5, 1, 1, Qt::AlignCenter); + grid->addWidget(rxAuxLabel, 0, 6, 1, 3, Qt::AlignCenter); + grid->addWidget(emptyLabel3, 0, 9, 1, 1, Qt::AlignCenter); + grid->addWidget(antTxLabel, 0, 10, 1, 3, Qt::AlignCenter); + + + for (int i = 0; i < m_numberOfBands; i++) { + + grid->addWidget(bandLabelList.at(i), i+1, 0, 1, 2, Qt::AlignLeft); + grid->addWidget(antenna1BtnList.at(i), i+1, 2, 1, 1, Qt::AlignCenter); + grid->addWidget(antenna2BtnList.at(i), i+1, 3, 1, 1, Qt::AlignCenter); + grid->addWidget(antenna3BtnList.at(i), i+1, 4, 1, 1, Qt::AlignCenter); + grid->addWidget(emptyLabel2, i+1, 5, 1, 1, Qt::AlignCenter); + grid->addWidget(rx1BtnList.at(i), i+1, 6, 1, 1, Qt::AlignCenter); + grid->addWidget(rx2BtnList.at(i), i+1, 7, 1, 1, Qt::AlignCenter); + grid->addWidget(xvBtnList.at(i), i+1, 8, 1, 1, Qt::AlignCenter); + grid->addWidget(emptyLabel3, i+1, 9, 1, 1, Qt::AlignCenter); + grid->addWidget(tx1BtnList.at(i), i+1, 10, 1, 1, Qt::AlignCenter); + grid->addWidget(tx2BtnList.at(i), i+1, 11, 1, 1, Qt::AlignCenter); + grid->addWidget(tx3BtnList.at(i), i+1, 12, 1, 1, Qt::AlignCenter); + } + + antennaGroup = new QGroupBox(tr(""), this); + antennaGroup->setMinimumWidth(m_minimumGroupBoxWidth); + antennaGroup->setLayout(grid); + antennaGroup->setStyleSheet(set->getWidgetStyle()); + antennaGroup->setFont(QFont("Arial", 8)); +} + +//***************** +void AlexAntennaWidget::rxAntBtnClicked() { + + AeroButton *button = qobject_cast(sender()); + + int btnHit; + int antenna; + int btnHit1 = antenna1BtnList.indexOf(button); + int btnHit2 = antenna2BtnList.indexOf(button); + int btnHit3 = antenna3BtnList.indexOf(button); + + if (btnHit1 >= 0) { + + btnHit = btnHit1; + antenna = 1; + } + else if (btnHit2 >= 0) { + + btnHit = btnHit2; + antenna = 2; + } + else if (btnHit3 >= 0) { + + btnHit = btnHit3; + antenna = 3; + } + else + return; + + if (btnHit >= 0) { + + foreach(AeroButton *btn, bandBtnMatrix.at(btnHit)) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + button->setBtnState(AeroButton::ON); + button->update(); + } + + m_alexStates[btnHit] &= 0x1FC; // 1 1 1 1 1 1 1 0 0 + m_alexStates[btnHit] |= antenna; + + set->setAlexState(this, btnHit, m_alexStates[btnHit]); +} + +void AlexAntennaWidget::rxAuxBtnClicked() { + + AeroButton *button = qobject_cast(sender()); + + int btnHit; + int aux; + int btnHit1 = rx1BtnList.indexOf(button); + int btnHit2 = rx2BtnList.indexOf(button); + int btnHit3 = xvBtnList.indexOf(button); + + if (btnHit1 >= 0) { + + btnHit = btnHit1; + aux = 1; + } + else if (btnHit2 >= 0) { + + btnHit = btnHit2; + aux = 2; + } + else if (btnHit3 >= 0) { + + btnHit = btnHit3; + aux = 3; + } + else + return; + + if (button->btnState() == AeroButton::ON) { + + button->setBtnState(AeroButton::OFF); + button->update(); + + m_alexStates[btnHit] &= 0x1E3; // 1 1 1 1 0 0 0 1 1 + } + else { + + if (btnHit >= 0) { + + foreach(AeroButton *btn, bandBtnRxMatrix.at(btnHit)) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + button->setBtnState(AeroButton::ON); + button->update(); + } + m_alexStates[btnHit] &= 0x1E3; // 1 1 1 1 0 0 0 1 1 + m_alexStates[btnHit] |= aux << 2; + } + set->setAlexState(this, btnHit, m_alexStates[btnHit]); +} + +void AlexAntennaWidget::txAntBtnClicked() { + + AeroButton *button = qobject_cast(sender()); + + int btnHit; + int antenna; + int btnHit1 = tx1BtnList.indexOf(button); + int btnHit2 = tx2BtnList.indexOf(button); + int btnHit3 = tx3BtnList.indexOf(button); + + if (btnHit1 >= 0) { + + btnHit = btnHit1; + antenna = 1; + } + else if (btnHit2 >= 0) { + + btnHit = btnHit2; + antenna = 2; + } + else if (btnHit3 >= 0) { + + btnHit = btnHit3; + antenna = 3; + } + else + return; + + if (btnHit >= 0) { + + foreach(AeroButton *btn, bandBtnTxMatrix.at(btnHit)) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + button->setBtnState(AeroButton::ON); + button->update(); + } + + m_alexStates[btnHit] &= 0x19F; // 1 1 0 0 1 1 1 1 1 + m_alexStates[btnHit] |= antenna << 5; + + set->setAlexState(this, btnHit, m_alexStates[btnHit]); +} + +void AlexAntennaWidget::setAlexValues() { + + //m_alexConfiguration = set->getAlexConfiguration(); + m_alexConfig = set->getAlexConfig(); + m_alexStates = set->getAlexStates();//m_alexParameters.state; + + for (int i = 0; i < m_numberOfBands; i++) { + + int rxAnt = m_alexStates.at(i) & 0x03; + if (rxAnt > 0) + bandBtnMatrix.at(i).at(rxAnt-1)->setBtnState(AeroButton::ON); + + int rxAux = (m_alexStates.at(i) >> 2) & 0x07; + if (rxAux > 0) + bandBtnRxMatrix.at(i).at(rxAux-1)->setBtnState(AeroButton::ON); + else { + + bandBtnRxMatrix.at(i).at(0)->setBtnState(AeroButton::OFF); + bandBtnRxMatrix.at(i).at(1)->setBtnState(AeroButton::OFF); + bandBtnRxMatrix.at(i).at(2)->setBtnState(AeroButton::OFF); + } + + int txAnt = (m_alexStates.at(i) >> 5) & 0x03; + if (txAnt > 0) + bandBtnTxMatrix.at(i).at(txAnt-1)->setBtnState(AeroButton::ON); + } +} diff --git a/Source/src/cusdr_alexAntennaWidget.h b/Source/src/cusdr_alexAntennaWidget.h new file mode 100644 index 0000000..4b3a896 --- /dev/null +++ b/Source/src/cusdr_alexAntennaWidget.h @@ -0,0 +1,116 @@ +/** +* @file cusdr_alexAntennaWidget.h +* @brief Alexiares antenna settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-09 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_ALEX_ANTENNA_WIDGET_H +#define _CUSDR_ALEX_ANTENNA_WIDGET_H + +//#include +//#include +#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" + +#ifdef LOG_ANTENNA_WIDGET +# define ANTENNA_WIDGET_DEBUG qDebug().nospace() << "AntennaWidget::\t" +#else +# define ALEX_WIDGET_DEBUG nullDebug() +#endif + + +class AlexAntennaWidget : public QWidget { + + Q_OBJECT + +public: + AlexAntennaWidget(QWidget *parent = 0); + ~AlexAntennaWidget(); + +protected: + //void resizeEvent(QResizeEvent *event); + +public slots: + +private: + void setupConnections(); + void createAntennasGroup(); + + void setAlexValues(); + +private: + Settings *set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QGroupBox *antennaGroup; + + QList antenna1BtnList; + QList antenna2BtnList; + QList antenna3BtnList; + + QList > bandBtnMatrix; + + QList rx1BtnList; + QList rx2BtnList; + QList xvBtnList; + + QList > bandBtnRxMatrix; + + QList tx1BtnList; + QList tx2BtnList; + QList tx3BtnList; + + QList > bandBtnTxMatrix; + + QList m_alexStates; + + CFonts *fonts; + TFonts m_fonts; + + quint16 m_alexConfig; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_numberOfBands; + +private slots: + void rxAntBtnClicked(); + void rxAuxBtnClicked(); + void txAntBtnClicked(); + +signals: + void showEvent(QObject* sender); + void closeEvent(QObject* sender); + void messageEvent(QString); +}; + +#endif // _CUSDR_ALEX_ANTENNA_WIDGET_H diff --git a/Source/src/cusdr_alexFilterWidget.cpp b/Source/src/cusdr_alexFilterWidget.cpp new file mode 100644 index 0000000..e2a0c1d --- /dev/null +++ b/Source/src/cusdr_alexFilterWidget.cpp @@ -0,0 +1,1045 @@ +/** +* @file cusdr_alexFilterWidget.cpp +* @brief Alexiares filter settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-23 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_ALEX_WIDGET + + +#include +#include +#include +#include + +#include "cusdr_alexFilterWidget.h" + +#define btn_height 15 +#define btn_width 22 +#define btn_width2 24//28 +#define btn_width3 45 + + +AlexFilterWidget::AlexFilterWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_frequency(set->getVfoFrequencies().at(0)) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(0) + , m_hpfFilters(6) + , m_lpfFilters(7) + , m_receiver(0) + , bypassAll(false) + , lowNoise6m(false) + , hpf13MHz(false) + , hpf20MHz(false) + , hpf9_5MHz(false) + , hpf6_5MHz(false) + , hpf1_5MHz(false) +{ + setObjectName("AlexFilterWidget"); + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 8, 4, 0); + setMouseTracking(true); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + btnOff = QColor(68, 68, 68, 255); + btnOn = QColor(56, 242, 115, 255); + + manualFilterBtn = new AeroButton("Auto", this); + manualFilterBtn->setRoundness(0); + manualFilterBtn->setFixedSize (btn_width3, btn_height); + manualFilterBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT(manualFilterBtn, SIGNAL(clicked()), this, SLOT(manualFilterBtnClicked())); + + defaultValuesBtn = new AeroButton("Default", this); + defaultValuesBtn->setRoundness(0); + defaultValuesBtn->setFixedSize (btn_width3, btn_height); + defaultValuesBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT(defaultValuesBtn, SIGNAL(clicked()), this, SLOT(defaultValuesBtnClicked())); + + //************************************************************** + // create groups + setFilterValues(); + + createHPFGroup(); + createLPFGroup(); + + // set main layout + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + mainLayout->setContentsMargins(1, 0, 4, 0); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 12, 0); + hbox1->addStretch(); + hbox1->addWidget(manualFilterBtn); + hbox1->addWidget(defaultValuesBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setContentsMargins(2, 0, 10, 0); + hbox2->addWidget(HPFGroup); + + QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(0); + hbox3->setContentsMargins(2, 0, 10, 0); + hbox3->addWidget(LPFGroup); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addStretch(); + + setLayout(mainLayout); + + initAlexValues(); + setupConnections(); + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + + setAlexConfiguration((double)(set->getVfoFrequencies().at(0)/1000.0)); +} + +AlexFilterWidget::~AlexFilterWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void AlexFilterWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(alexManualStateChanged(QObject *, bool)), + this, + SLOT(alexManualStateChanged(QObject *, bool))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(currentReceiverChanged(QObject *,int)), +// this, +// SLOT(setCurrentReceiver(QObject *, int))); + + /*CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, bool, int, long)), + this, + SLOT(setFrequency(QObject *, bool, int, long)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(setFrequency(QObject *, int, int, long))); +} + +void AlexFilterWidget::createHPFGroup() { + + QLabel *byPassLabel = new QLabel("byPass", this); + byPassLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + byPassLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *emptyLabel = new QLabel(" ", this); + emptyLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *hpfLabel = new QLabel("HPF (kHz)", this); + hpfLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + hpfLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *mHz1_5Label = new QLabel("1.5 MHz", this); + mHz1_5Label->setFrameStyle(QFrame::Box | QFrame::Raised); + mHz1_5Label->setStyleSheet(set->getLabelStyle()); + m_HPFLabelList.append(mHz1_5Label); + + QLabel *mHz6_5Label = new QLabel("6.5 MHz", this); + mHz6_5Label->setFrameStyle(QFrame::Box | QFrame::Raised); + mHz6_5Label->setStyleSheet(set->getLabelStyle()); + m_HPFLabelList.append(mHz6_5Label); + + QLabel *mHz9_5Label = new QLabel("9.5 MHz", this); + mHz9_5Label->setFrameStyle(QFrame::Box | QFrame::Raised); + mHz9_5Label->setStyleSheet(set->getLabelStyle()); + m_HPFLabelList.append(mHz9_5Label); + + QLabel *mHz13Label = new QLabel("13 MHz", this); + mHz13Label->setFrameStyle(QFrame::Box | QFrame::Raised); + mHz13Label->setStyleSheet(set->getLabelStyle()); + m_HPFLabelList.append(mHz13Label); + + QLabel *mHz20Label = new QLabel("20 MHz", this); + mHz20Label->setFrameStyle(QFrame::Box | QFrame::Raised); + mHz20Label->setStyleSheet(set->getLabelStyle()); + m_HPFLabelList.append(mHz20Label); + + QLabel *m6BPF_LNALabel = new QLabel("6m LNA", this); + m6BPF_LNALabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m6BPF_LNALabel->setStyleSheet(set->getLabelStyle()); + m_HPFLabelList.append(m6BPF_LNALabel); + + QLabel *byPassAllLabel = new QLabel("Bypass", this); + byPassAllLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + byPassAllLabel->setStyleSheet(set->getLabelStyle()); + + mhz55HPFLabel = new QLabel(" 55 MHz HPF ", this); + mhz55HPFLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + mhz55HPFLabel->setStyleSheet(set->getLabelStyle()); + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000000.0").width() + 30; + + QList values = set->getHPFLoFrequencies(); + + // HPF lo spin boxes + for (int i = 0; i < m_hpfFilters; i++) { + + QDoubleSpinBox *spinBox = new QDoubleSpinBox(); + spinBox->setStyleSheet(set->getDoubleSpinBoxStyle()); + spinBox->setDecimals(1); + spinBox->setWrapping(true); + spinBox->setMinimumWidth(fontMaxWidth); + spinBox->setRange(m_HPFFrequencyRangeLoList.at(i).first, m_HPFFrequencyRangeLoList.at(i).second); + spinBox->setSingleStep(0.5); + spinBox->setValue((double)(values.at(i)/1000.0)); + + CHECKED_CONNECT(spinBox, SIGNAL(valueChanged(double)), this, SLOT(hpfLoSpinBoxValueChanged(double))); + + m_HPFLoSpinBoxList << spinBox; + } + + values = set->getHPFHiFrequencies(); + + // HPF hi spin boxes + for (int i = 0; i < m_hpfFilters; i++) { + + QDoubleSpinBox *spinBox = new QDoubleSpinBox(); + spinBox->setStyleSheet(set->getDoubleSpinBoxStyle()); + spinBox->setDecimals(1); + spinBox->setWrapping(true); + spinBox->setMinimumWidth(fontMaxWidth); + spinBox->setRange(m_HPFFrequencyRangeHiList.at(i).first, m_HPFFrequencyRangeHiList.at(i).second); + spinBox->setSingleStep(0.5); + spinBox->setValue((double)(values.at(i)/1000.0)); + + CHECKED_CONNECT(spinBox, SIGNAL(valueChanged(double)), this, SLOT(hpfHiSpinBoxValueChanged(double))); + + m_HPFHiSpinBoxList << spinBox; + } + + // HPF active buttons + for (int i = 0; i < m_hpfFilters+1; i++) { + + QHLed *btn = new QHLed("", this); + btn->setFixedSize(4, btn_height); + btn->setColors(btnOff, btnOff); + + m_HPFActiveBtnList << btn; + } + + + hpf1_5MHzBtn = new AeroButton("Off", this); + hpf1_5MHzBtn->setRoundness(0); + hpf1_5MHzBtn->setFixedSize(btn_width, btn_height); + hpf1_5MHzBtn->setStyleSheet(set->getMiniButtonStyle()); + hpf1_5MHzBtn->setBtnState(AeroButton::OFF); + m_HPFBtnList.append(hpf1_5MHzBtn); + + CHECKED_CONNECT(hpf1_5MHzBtn, SIGNAL(clicked()), this, SLOT(hpf1_5MHzBtnClicked())); + + hpf6_5MHzBtn = new AeroButton("Off", this); + hpf6_5MHzBtn->setRoundness(0); + hpf6_5MHzBtn->setFixedSize(btn_width, btn_height); + hpf6_5MHzBtn->setStyleSheet(set->getMiniButtonStyle()); + hpf6_5MHzBtn->setBtnState(AeroButton::OFF); + m_HPFBtnList.append(hpf6_5MHzBtn); + + CHECKED_CONNECT(hpf6_5MHzBtn, SIGNAL(clicked()), this, SLOT(hpf6_5MHzBtnClicked())); + + hpf9_5MHzBtn = new AeroButton("Off", this); + hpf9_5MHzBtn->setRoundness(0); + hpf9_5MHzBtn->setFixedSize(btn_width, btn_height); + hpf9_5MHzBtn->setStyleSheet(set->getMiniButtonStyle()); + hpf9_5MHzBtn->setBtnState(AeroButton::OFF); + m_HPFBtnList.append(hpf9_5MHzBtn); + + CHECKED_CONNECT(hpf9_5MHzBtn, SIGNAL(clicked()), this, SLOT(hpf9_5MHzBtnClicked())); + + hpf13MHzBtn = new AeroButton("Off", this); + hpf13MHzBtn->setRoundness(0); + hpf13MHzBtn->setFixedSize(btn_width, btn_height); + hpf13MHzBtn->setStyleSheet(set->getMiniButtonStyle()); + hpf13MHzBtn->setBtnState(AeroButton::OFF); + m_HPFBtnList.append(hpf13MHzBtn); + + CHECKED_CONNECT(hpf13MHzBtn, SIGNAL(clicked()), this, SLOT(hpf13MHzBtnClicked())); + + hpf20MHzBtn = new AeroButton("Off", this); + hpf20MHzBtn->setRoundness(0); + hpf20MHzBtn->setFixedSize(btn_width, btn_height); + hpf20MHzBtn->setStyleSheet(set->getMiniButtonStyle()); + hpf20MHzBtn->setBtnState(AeroButton::OFF); + m_HPFBtnList.append(hpf20MHzBtn); + + CHECKED_CONNECT(hpf20MHzBtn, SIGNAL(clicked()), this, SLOT(hpf20MHzBtnClicked())); + + lowNoise6mAmpBtn = new AeroButton("Off", this); + lowNoise6mAmpBtn->setRoundness(0); + lowNoise6mAmpBtn->setFixedSize(btn_width, btn_height); + lowNoise6mAmpBtn->setStyleSheet(set->getMiniButtonStyle()); + lowNoise6mAmpBtn->setBtnState(AeroButton::OFF); + m_HPFBtnList.append(lowNoise6mAmpBtn); + + CHECKED_CONNECT(lowNoise6mAmpBtn, SIGNAL(clicked()), this, SLOT(lowNoise6mAmpBtnClicked())); + + bypassAllHPFBtn = new AeroButton("Off", this); + bypassAllHPFBtn->setRoundness(0); + bypassAllHPFBtn->setFixedSize (btn_width, btn_height); + bypassAllHPFBtn->setStyleSheet(set->getMiniButtonStyle()); + bypassAllHPFBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT(bypassAllHPFBtn, SIGNAL(clicked()), this, SLOT(bypassAllHPFBtnClicked())); + + + QGridLayout* grid = new QGridLayout(this); + grid->setVerticalSpacing(1); + grid->setHorizontalSpacing(1); + grid->setContentsMargins(2, 12, 2, 7); + + grid->addWidget(byPassLabel, 0, 0, 1, 2, Qt::AlignLeft); + grid->addWidget(hpfLabel, 0, 2, 1, 3, Qt::AlignCenter); + + for (int i = 0; i < m_hpfFilters; i++) { + + grid->addWidget(m_HPFBtnList.at(i), i+1, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(m_HPFLabelList.at(i), i+1, 1, 1, 1, Qt::AlignLeft); + grid->addWidget(m_HPFLoSpinBoxList.at(i), i+1, 2, 1, 1, Qt::AlignCenter); + grid->addWidget(m_HPFHiSpinBoxList.at(i), i+1, 3, 1, 1, Qt::AlignCenter); + grid->addWidget(m_HPFActiveBtnList.at(i), i+1, 4, 1, 1, Qt::AlignCenter); + } + + grid->addWidget(bypassAllHPFBtn, 8, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(byPassAllLabel, 8, 1, 1, 1, Qt::AlignCenter); + grid->addWidget(mhz55HPFLabel, 8, 2, 1, 2, Qt::AlignCenter); + grid->addWidget(m_HPFActiveBtnList.at(m_hpfFilters), 8, 4, 1, 1, Qt::AlignCenter); + + HPFGroup = new QGroupBox(tr("HP Filters"), this); + HPFGroup->setMinimumWidth(m_minimumGroupBoxWidth); + HPFGroup->setLayout(grid); + HPFGroup->setStyleSheet(set->getWidgetStyle()); + HPFGroup->setFont(QFont("Arial", 8)); +} + +void AlexFilterWidget::createLPFGroup() { + + QLabel *lpfLabel = new QLabel("LPF (kHz)", this); + lpfLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + lpfLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *emptyLabel = new QLabel(" ", this); + emptyLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *m160Label = new QLabel("160m", this); + m160Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m160Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m160Label); + + QLabel *m80Label = new QLabel("80m", this); + m80Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m80Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m80Label); + + QLabel *m60_40Label = new QLabel("60/40m", this); + m60_40Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m60_40Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m60_40Label); + + QLabel *m30_20Label = new QLabel("30/20m", this); + m30_20Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m30_20Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m30_20Label); + + QLabel *m17_15Label = new QLabel("17/15m", this); + m17_15Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m17_15Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m17_15Label); + + QLabel *m12_10Label = new QLabel("12/10m", this); + m12_10Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m12_10Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m12_10Label); + + QLabel *m6Label = new QLabel("6m", this); + m6Label->setFrameStyle(QFrame::Box | QFrame::Raised); + m6Label->setStyleSheet(set->getLabelStyle()); + m_LPFLabelList.append(m6Label); + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("000000.0").width() + 30; + + QList values = set->getLPFLoFrequencies(); + + // LPF lo spin boxes + for (int i = 0; i < m_lpfFilters; i++) { + + QDoubleSpinBox *spinBox = new QDoubleSpinBox(); + spinBox->setStyleSheet(set->getDoubleSpinBoxStyle()); + spinBox->setDecimals(1); + spinBox->setWrapping(true); + spinBox->setMinimumWidth(fontMaxWidth); + spinBox->setRange(m_LPFFrequencyRangeLoList.at(i).first, m_LPFFrequencyRangeLoList.at(i).second); + spinBox->setSingleStep(0.5); + spinBox->setValue((double)(values.at(i)/1000.0)); + + CHECKED_CONNECT(spinBox, SIGNAL(valueChanged(double)), this, SLOT(lpfLoSpinBoxValueChanged(double))); + + m_LPFLoSpinBoxList << spinBox; + } + + values = set->getLPFHiFrequencies(); + + // LPF hi spin boxes + for (int i = 0; i < m_lpfFilters; i++) { + + QDoubleSpinBox *spinBox = new QDoubleSpinBox(); + spinBox->setStyleSheet(set->getDoubleSpinBoxStyle()); + spinBox->setDecimals(1); + spinBox->setWrapping(true); + spinBox->setMinimumWidth(fontMaxWidth); + spinBox->setRange(m_LPFFrequencyRangeHiList.at(i).first, m_LPFFrequencyRangeHiList.at(i).second); + spinBox->setSingleStep(0.5); + spinBox->setValue((double)(values.at(i)/1000.0)); + + CHECKED_CONNECT(spinBox, SIGNAL(valueChanged(double)), this, SLOT(lpfHiSpinBoxValueChanged(double))); + + m_LPFHiSpinBoxList << spinBox; + } + + // LPF active buttons + for (int i = 0; i < m_lpfFilters; i++) { + + QHLed *btn = new QHLed("", this); + btn->setFixedSize(4, btn_height); + btn->setColors(btnOff, btnOff); + + m_LPFActiveBtnList << btn; + + //CHECKED_CONNECT(spinBox, SIGNAL(valueChanged(double)), this, SLOT(hpfHiSpinBoxValueChanged(double))); + } + + QGridLayout* grid = new QGridLayout(this); + grid->setVerticalSpacing(1); + grid->setHorizontalSpacing(1); + grid->setContentsMargins(28, 12, 2, 7); + + grid->addWidget(emptyLabel, 0, 0, 1, 1, Qt::AlignCenter); + grid->addWidget(lpfLabel, 0, 1, 1, 3, Qt::AlignCenter); + + for (int i = 0; i < m_lpfFilters; i++) { + + grid->addWidget(m_LPFLabelList.at(i), i+1, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(m_LPFLoSpinBoxList.at(i), i+1, 1, 1, 1, Qt::AlignCenter); + grid->addWidget(m_LPFHiSpinBoxList.at(i), i+1, 2, 1, 1, Qt::AlignCenter); + grid->addWidget(m_LPFActiveBtnList.at(i), i+1, 3, 1, 1, Qt::AlignCenter); + } + + LPFGroup = new QGroupBox(tr("LP Filters"), this); + LPFGroup->setMinimumWidth(m_minimumGroupBoxWidth); + LPFGroup->setLayout(grid); + LPFGroup->setStyleSheet(set->getWidgetStyle()); + LPFGroup->setFont(QFont("Arial", 8)); +} + +//***************** + +void AlexFilterWidget::setFilterValues() { + + m_HPFFrequencyRangeLoList << qMakePair(0.0, 2000.0); + m_HPFFrequencyRangeLoList << qMakePair(6000.0, 8000.0); + m_HPFFrequencyRangeLoList << qMakePair(9000.0, 11000.0); + m_HPFFrequencyRangeLoList << qMakePair(12000.0, 15000.0); + m_HPFFrequencyRangeLoList << qMakePair(18000.0, 25000.0); + m_HPFFrequencyRangeLoList << qMakePair(49000.0, 52500.0); + + m_HPFFrequencyRangeHiList << qMakePair(1600.0, 6000.0); + m_HPFFrequencyRangeHiList << qMakePair(7000.0, 9500.0); + m_HPFFrequencyRangeHiList << qMakePair(10000.0, 13000.0); + m_HPFFrequencyRangeHiList << qMakePair(13700.0, 19000.0); + m_HPFFrequencyRangeHiList << qMakePair(25000.0, 32000.0); + m_HPFFrequencyRangeHiList << qMakePair(52500.0, 55000.0); + + m_LPFFrequencyRangeLoList << qMakePair(0.0, 1900.0); + m_LPFFrequencyRangeLoList << qMakePair(2000.0, 4000.0); + m_LPFFrequencyRangeLoList << qMakePair(5000.0, 11000.0); + m_LPFFrequencyRangeLoList << qMakePair(9000.0, 15000.0); + m_LPFFrequencyRangeLoList << qMakePair(17000.0, 22000.0); + m_LPFFrequencyRangeLoList << qMakePair(23000.0, 30000.0); + m_LPFFrequencyRangeLoList << qMakePair(30000.0, 52000.0); + + m_LPFFrequencyRangeHiList << qMakePair(1000.0, 3000.0); + m_LPFFrequencyRangeHiList << qMakePair(2000.0, 5000.0); + m_LPFFrequencyRangeHiList << qMakePair(5000.0, 8000.0); + m_LPFFrequencyRangeHiList << qMakePair(9000.0, 15000.0); + m_LPFFrequencyRangeHiList << qMakePair(17000.0, 22000.0); + m_LPFFrequencyRangeHiList << qMakePair(23000.0, 30000.0); + m_LPFFrequencyRangeHiList << qMakePair(52000.0, 66000.0); + + + m_HPFLoDefaultFrequencyList << 1500.0; + m_HPFLoDefaultFrequencyList << 7000.0; + m_HPFLoDefaultFrequencyList << 10100.0; + m_HPFLoDefaultFrequencyList << 14000.0; + m_HPFLoDefaultFrequencyList << 21000.0; + m_HPFLoDefaultFrequencyList << 50000.0; + + m_HPFHiDefaultFrequencyList << 5500.0; + m_HPFHiDefaultFrequencyList << 7300.0; + m_HPFHiDefaultFrequencyList << 10150.0; + m_HPFHiDefaultFrequencyList << 18168.0; + m_HPFHiDefaultFrequencyList << 29700.0; + m_HPFHiDefaultFrequencyList << 54000.0; + + m_LPFLoDefaultFrequencyList << 1800.0; + m_LPFLoDefaultFrequencyList << 3500.0; + m_LPFLoDefaultFrequencyList << 5330.0; + m_LPFLoDefaultFrequencyList << 10100.0; + m_LPFLoDefaultFrequencyList << 18068.0; + m_LPFLoDefaultFrequencyList << 24890.0; + m_LPFLoDefaultFrequencyList << 50000.0; + + m_LPFHiDefaultFrequencyList << 2000.0; + m_LPFHiDefaultFrequencyList << 4000.0; + m_LPFHiDefaultFrequencyList << 7300.0; + m_LPFHiDefaultFrequencyList << 14350.0; + m_LPFHiDefaultFrequencyList << 21450.0; + m_LPFHiDefaultFrequencyList << 29700.0; + m_LPFHiDefaultFrequencyList << 54000.0; +} + +void AlexFilterWidget::hpfLoSpinBoxValueChanged(double value) { + + QDoubleSpinBox *spinBox = qobject_cast(sender()); + + int filter = m_HPFLoSpinBoxList.indexOf(spinBox); + + set->setAlexHPFLoFrequencies(filter, (long)(value * 1000)); +} + +void AlexFilterWidget::hpfHiSpinBoxValueChanged(double value) { + + QDoubleSpinBox *spinBox = qobject_cast(sender()); + + int filter = m_HPFHiSpinBoxList.indexOf(spinBox); + + set->setAlexHPFHiFrequencies(filter, (long)(value * 1000)); +} + +void AlexFilterWidget::lpfLoSpinBoxValueChanged(double value) { + + QDoubleSpinBox *spinBox = qobject_cast(sender()); + + int filter = m_LPFLoSpinBoxList.indexOf(spinBox); + + set->setAlexLPFLoFrequencies(filter, (long)(value * 1000)); +} + +void AlexFilterWidget::lpfHiSpinBoxValueChanged(double value) { + + QDoubleSpinBox *spinBox = qobject_cast(sender()); + + int filter = m_LPFHiSpinBoxList.indexOf(spinBox); + + set->setAlexLPFHiFrequencies(filter, (long)(value * 1000)); +} + +void AlexFilterWidget::manualFilterBtnClicked() { + + if (manualFilterBtn->btnState() == AeroButton::OFF) { + + manualFilterBtn->setText("Manual"); + manualFilterBtn->setBtnState(AeroButton::ON); + +// bypassAllHPFBtn->setEnabled(true); +// lowNoise6mAmpBtn->setEnabled(true); +// hpf13MHzBtn->setEnabled(true); +// hpf20MHzBtn->setEnabled(true); +// hpf9_5MHzBtn->setEnabled(true); +// hpf6_5MHzBtn->setEnabled(true); +// hpf1_5MHzBtn->setEnabled(true); +// lpf30_20mBtn->setEnabled(true); +// lpf60_40mBtn->setEnabled(true); +// lpf80mBtn->setEnabled(true); +// lpf160mBtn->setEnabled(true); +// lpf6mBtn->setEnabled(true); +// lpf12_10mBtn->setEnabled(true); +// lpf17_15mBtn->setEnabled(true); + + m_alexConfig |= 0x01; + } + else { + + manualFilterBtn->setText("Auto"); + manualFilterBtn->setBtnState(AeroButton::OFF); + +// bypassAllHPFBtn->setEnabled(false); +// lowNoise6mAmpBtn->setEnabled(false); +// hpf13MHzBtn->setEnabled(false); +// hpf20MHzBtn->setEnabled(false); +// hpf9_5MHzBtn->setEnabled(false); +// hpf6_5MHzBtn->setEnabled(false); +// hpf1_5MHzBtn->setEnabled(false); +// lpf30_20mBtn->setEnabled(false); +// lpf60_40mBtn->setEnabled(false); +// lpf80mBtn->setEnabled(false); +// lpf160mBtn->setEnabled(false); +// lpf6mBtn->setEnabled(false); +// lpf12_10mBtn->setEnabled(false); +// lpf17_15mBtn->setEnabled(false); + + m_alexConfig |= 0xFFFE; + } + manualFilterBtn->update(); + + set->setAlexConfiguration(this, m_alexConfig); +} + +void AlexFilterWidget::defaultValuesBtnClicked() { + + for (int i = 0; i < m_hpfFilters; i++) { + + m_HPFLoSpinBoxList[i]->setValue(m_HPFLoDefaultFrequencyList.at(i)); + m_HPFHiSpinBoxList[i]->setValue(m_HPFHiDefaultFrequencyList.at(i)); + } + + for (int i = 0; i < m_lpfFilters; i++) { + + m_LPFLoSpinBoxList[i]->setValue(m_LPFLoDefaultFrequencyList.at(i)); + m_LPFHiSpinBoxList[i]->setValue(m_LPFHiDefaultFrequencyList.at(i)); + } +} + +void AlexFilterWidget::bypassAllHPFBtnClicked() { + + if (bypassAllHPFBtn->btnState() == AeroButton::OFF) { + + bypassAllHPFBtn->setText("On"); + bypassAllHPFBtn->setBtnState(AeroButton::ON); + bypassAll = true; + } + else { + + bypassAllHPFBtn->setText("Off"); + bypassAllHPFBtn->setBtnState(AeroButton::OFF); + bypassAll = false; + } + bypassAllHPFBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::lowNoise6mAmpBtnClicked() { + + if (lowNoise6mAmpBtn->btnState() == AeroButton::OFF) { + + lowNoise6mAmpBtn->setText("On"); + lowNoise6mAmpBtn->setBtnState(AeroButton::ON); + lowNoise6m = true; + } + else { + + lowNoise6mAmpBtn->setText("Off"); + lowNoise6mAmpBtn->setBtnState(AeroButton::OFF); + lowNoise6m = false; + } + lowNoise6mAmpBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::hpf1_5MHzBtnClicked() { + + if (hpf1_5MHzBtn->btnState() == AeroButton::OFF) { + + hpf1_5MHzBtn->setBtnState(AeroButton::ON); + hpf1_5MHzBtn->setText("On"); + hpf1_5MHz = true; + } + else { + + hpf1_5MHzBtn->setBtnState(AeroButton::OFF); + hpf1_5MHzBtn->setText("Off"); + hpf1_5MHz= false; + } + hpf1_5MHzBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::hpf6_5MHzBtnClicked() { + + if (hpf6_5MHzBtn->btnState() == AeroButton::OFF) { + + hpf6_5MHzBtn->setBtnState(AeroButton::ON); + hpf6_5MHzBtn->setText("On"); + hpf6_5MHz = true; + } + else { + + hpf6_5MHzBtn->setBtnState(AeroButton::OFF); + hpf6_5MHzBtn->setText("Off"); + hpf6_5MHz = false; + } + hpf6_5MHzBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::hpf9_5MHzBtnClicked() { + + if (hpf9_5MHzBtn->btnState() == AeroButton::OFF) { + + hpf9_5MHzBtn->setBtnState(AeroButton::ON); + hpf9_5MHzBtn->setText("On"); + hpf9_5MHz = true; + } + else { + + hpf9_5MHzBtn->setBtnState(AeroButton::OFF); + hpf9_5MHzBtn->setText("Off"); + hpf9_5MHz = false; + } + hpf9_5MHzBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::hpf13MHzBtnClicked() { + + if (hpf13MHzBtn->btnState() == AeroButton::OFF) { + + hpf13MHzBtn->setBtnState(AeroButton::ON); + hpf13MHzBtn->setText("On"); + hpf13MHz = true; + } + else { + + hpf13MHzBtn->setBtnState(AeroButton::OFF); + hpf13MHzBtn->setText("Off"); + hpf13MHz = false; + } + hpf13MHzBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::hpf20MHzBtnClicked() { + + if (hpf20MHzBtn->btnState() == AeroButton::OFF) { + + hpf20MHzBtn->setBtnState(AeroButton::ON); + hpf20MHzBtn->setText("On"); + hpf20MHz = true; + } + else { + + hpf20MHzBtn->setBtnState(AeroButton::OFF); + hpf20MHzBtn->setText("Off"); + hpf20MHz = false; + } + hpf20MHzBtn->update(); + + setFrequency(this, 0, m_receiver, set->getVfoFrequencies().at(m_receiver)); +} + +void AlexFilterWidget::setFrequency(QObject * sender, int mode, int rx, long frequency) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + m_receiver = rx; + m_frequency = frequency; + + if ((m_alexConfig & 0x01) == 0) return; + + setAlexConfiguration((double)(frequency/1000.0)); + + set->setAlexConfiguration(this, m_alexConfig); +} + +void AlexFilterWidget::setAlexConfiguration(double freq) { + + foreach(QHLed *led, m_HPFActiveBtnList) + led->setColors(btnOff, btnOff); + + // Alex configuration + // m_alexConfig (quint16): + // + // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + // | | | | | | | | | | | | | | | + // | | | | | | | | | | | | | | +-----Alex - manual HPF/LPF filter select (0 = disable, 1 = enable) + // | | | | | | | | | | | | | +------ Alex - Bypass all HPFs (0 = disable, 1 = enable)* + // | | | | | | | | | | | | +-------- Alex - 6M low noise amplifier (0 = disable, 1 = enable)* + // | | | | | | | | | | | +---------- Alex - select 1.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | | +------------ Alex - select 6.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | +-------------- Alex - select 9.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | +---------------- Alex - select 13MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | +------------------ Alex - select 20MHz HPF (0 = disable, 1 = enable)* + // | | | | | | +-------------------- Alex - select 160m LPF (0 = disable, 1 = enable)* + // | | | | | +---------------------- Alex - select 80m LPF (0 = disable, 1 = enable)* + // | | | | +------------------------ Alex - select 60/40m LPF (0 = disable, 1 = enable)* + // | | | +-------------------------- Alex - select 30/20m LPF (0 = disable, 1 = enable)* + // | | +---------------------------- Alex - select 17/15m LPF (0 = disable, 1 = enable)* + // | +------------------------------ Alex - select 12/10m LPF (0 = disable, 1 = enable)* + // +-------------------------------- Alex - select 6m LPF (0 = disable, 1 = enable)* + + // reset + m_alexConfig &= 1; + + // HPF switching + if (!bypassAll) { + + // HPF 1.5 MHz + if (freq >= m_HPFLoSpinBoxList.at(0)->value() && freq <= m_HPFHiSpinBoxList.at(0)->value()) { + + if (!hpf1_5MHz) { + + m_HPFActiveBtnList.at(0)->setColors(btnOn, btnOn); + m_alexConfig |= 0x08; + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + // HPF 6.5 MHz + else if (freq >= m_HPFLoSpinBoxList.at(1)->value() && freq <= m_HPFHiSpinBoxList.at(1)->value()) { + + if (!hpf6_5MHz) { + + m_HPFActiveBtnList.at(1)->setColors(btnOn, btnOn); + m_alexConfig |= 0x10; + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + // HPF 9.5 MHz + else if (freq >= m_HPFLoSpinBoxList.at(2)->value() && freq <= m_HPFHiSpinBoxList.at(2)->value()) { + + if (!hpf9_5MHz) { + + m_HPFActiveBtnList.at(2)->setColors(btnOn, btnOn); + m_alexConfig |= 0x20; + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + // HPF 13 MHz + else if (freq >= m_HPFLoSpinBoxList.at(3)->value() && freq <= m_HPFHiSpinBoxList.at(3)->value()) { + + if (!hpf13MHz) { + + m_HPFActiveBtnList.at(3)->setColors(btnOn, btnOn); + m_alexConfig |= 0x40; + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + // HPF 20 MHz + else if (freq >= m_HPFLoSpinBoxList.at(4)->value() && freq <= m_HPFHiSpinBoxList.at(4)->value()) { + + if (!hpf20MHz) { + + m_HPFActiveBtnList.at(4)->setColors(btnOn, btnOn); + m_alexConfig |= 0x80; + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + // 6m BPF/LNA + else if (freq >= m_HPFLoSpinBoxList.at(5)->value() && freq <= m_HPFHiSpinBoxList.at(5)->value()) { + + if (!lowNoise6m) { + + m_HPFActiveBtnList.at(5)->setColors(btnOn, btnOn); + m_alexConfig |= 0x04; + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + } + // by pass all + else { + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x02; + } + + + // LPF switching + foreach(QHLed *led, m_LPFActiveBtnList) + led->setColors(btnOff, btnOff); + + if (freq >= m_LPFLoSpinBoxList.at(0)->value() && freq <= m_LPFHiSpinBoxList.at(0)->value()) { + + m_LPFActiveBtnList.at(0)->setColors(btnOn, btnOn); + m_alexConfig |= 0x100; + } + else if (freq >= m_LPFLoSpinBoxList.at(1)->value() && freq <= m_LPFHiSpinBoxList.at(1)->value()) { + + m_LPFActiveBtnList.at(1)->setColors(btnOn, btnOn); + m_alexConfig |= 0x200; + } + else if (freq >= m_LPFLoSpinBoxList.at(2)->value() && freq <= m_LPFHiSpinBoxList.at(2)->value()) { + + m_LPFActiveBtnList.at(2)->setColors(btnOn, btnOn); + m_alexConfig |= 0x400; + } + else if (freq >= m_LPFLoSpinBoxList.at(3)->value() && freq <= m_LPFHiSpinBoxList.at(3)->value()) { + + m_LPFActiveBtnList.at(3)->setColors(btnOn, btnOn); + m_alexConfig |= 0x800; + } + else if (freq >= m_LPFLoSpinBoxList.at(4)->value() && freq <= m_LPFHiSpinBoxList.at(4)->value()) { + + m_LPFActiveBtnList.at(4)->setColors(btnOn, btnOn); + m_alexConfig |= 0x1000; + } + else if (freq >= m_LPFLoSpinBoxList.at(5)->value() && freq <= m_LPFHiSpinBoxList.at(5)->value()) { + + m_LPFActiveBtnList.at(5)->setColors(btnOn, btnOn); + m_alexConfig |= 0x2000; + } + else { + + m_LPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + m_alexConfig |= 0x4000; + } +} + +void AlexFilterWidget::setCurrentReceiver(QObject *sender, int rx) { + + Q_UNUSED(sender) + + m_receiver = rx; +} + +void AlexFilterWidget::initAlexValues() { + + // Alex configuration: + // + // m_alexConfig (quint16) + // + // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + // | | | | | | | | | | | | | | | + // | | | | | | | | | | | | | | +-----Alex - manual HPF/LPF filter select (0 = disable, 1 = enable) + // | | | | | | | | | | | | | +------ Alex - Bypass all HPFs (0 = disable, 1 = enable)* + // | | | | | | | | | | | | +-------- Alex - 6M low noise amplifier (0 = disable, 1 = enable)* + // | | | | | | | | | | | +---------- Alex - select 1.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | | +------------ Alex - select 6.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | +-------------- Alex - select 9.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | +---------------- Alex - select 13MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | +------------------ Alex - select 20MHz HPF (0 = disable, 1 = enable)* + // | | | | | | +-------------------- Alex - select 160m LPF (0 = disable, 1 = enable)* + // | | | | | +---------------------- Alex - select 80m LPF (0 = disable, 1 = enable)* + // | | | | +------------------------ Alex - select 60/40m LPF (0 = disable, 1 = enable)* + // | | | +-------------------------- Alex - select 30/20m LPF (0 = disable, 1 = enable)* + // | | +---------------------------- Alex - select 17/15m LPF (0 = disable, 1 = enable)* + // | +------------------------------ Alex - select 12/10m LPF (0 = disable, 1 = enable)* + // +-------------------------------- Alex - select 6m LPF (0 = disable, 1 = enable)* + + m_alexConfig = set->getAlexConfig(); + m_alexStates = set->getAlexStates(); + + + if (m_alexConfig & 0x01) { + + manualFilterBtn->setText("Manual"); + manualFilterBtn->setBtnState(AeroButton::ON); + } + else { + + manualFilterBtn->setText("Auto"); + manualFilterBtn->setBtnState(AeroButton::OFF); + } + manualFilterBtn->update(); +} + +void AlexFilterWidget::alexManualStateChanged(QObject *sender, bool value) { + + Q_UNUSED(sender) + + if (value) { + + m_alexConfig |= 0x01; + m_receiver = set->getCurrentReceiver(); + setFrequency(this, true, m_receiver, set->getVfoFrequencies().at(m_receiver)); + + manualFilterBtn->setText("Manual"); + manualFilterBtn->setBtnState(AeroButton::ON); + } + else { + + m_alexConfig &= 0xFFFE; + + foreach(QHLed *led, m_HPFActiveBtnList) + led->setColors(btnOff, btnOff); + + m_HPFActiveBtnList.at(6)->setColors(btnOn, btnOn); + + manualFilterBtn->setText("Auto"); + manualFilterBtn->setBtnState(AeroButton::OFF); + + set->setAlexConfiguration(this, m_alexConfig); + } + manualFilterBtn->update(); +} + diff --git a/Source/src/cusdr_alexFilterWidget.h b/Source/src/cusdr_alexFilterWidget.h new file mode 100644 index 0000000..c536e58 --- /dev/null +++ b/Source/src/cusdr_alexFilterWidget.h @@ -0,0 +1,160 @@ +/** +* @file cusdr_alexFilterWidget.h +* @brief Alexiares filter settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-23 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_ALEX_FILTER_WIDGET_H +#define _CUSDR_ALEX_FILTER_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "Util/cusdr_led.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" + + +class AlexFilterWidget : public QWidget { + + Q_OBJECT + +public: + AlexFilterWidget(QWidget *parent = 0); + ~AlexFilterWidget(); + +public slots: + +private: + void setupConnections(); + void createHPFGroup(); + void createLPFGroup(); + + void initAlexValues(); + void setFilterValues(); + +private: + Settings *set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QGroupBox* HPFGroup; + QGroupBox* LPFGroup; + + QList m_HPFLoSpinBoxList; + QList m_HPFHiSpinBoxList; + QList m_LPFLoSpinBoxList; + QList m_LPFHiSpinBoxList; + + QList m_HPFActiveBtnList; + QList m_LPFActiveBtnList; + + QList m_HPFLabelList; + QList m_LPFLabelList; + QList m_HPFBtnList; + + QList m_alexStates; + + QList > m_HPFFrequencyRangeLoList; + QList > m_HPFFrequencyRangeHiList; + QList > m_LPFFrequencyRangeLoList; + QList > m_LPFFrequencyRangeHiList; + + QList m_HPFLoDefaultFrequencyList; + QList m_HPFHiDefaultFrequencyList; + QList m_LPFLoDefaultFrequencyList; + QList m_LPFHiDefaultFrequencyList; + + CFonts *fonts; + TFonts m_fonts; + + QLabel *mhz55HPFLabel; + + AeroButton *manualFilterBtn; + AeroButton *defaultValuesBtn; + AeroButton *bypassAllHPFBtn; + AeroButton *lowNoise6mAmpBtn; + AeroButton *hpf13MHzBtn; + AeroButton *hpf20MHzBtn; + AeroButton *hpf9_5MHzBtn; + AeroButton *hpf6_5MHzBtn; + AeroButton *hpf1_5MHzBtn; + + QColor btnOff; + QColor btnOn; + + quint16 m_alexConfig; + + long m_frequency; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_hpfFilters; + int m_lpfFilters; + int m_receiver; + + bool bypassAll; + bool lowNoise6m; + bool hpf13MHz; + bool hpf20MHz; + bool hpf9_5MHz; + bool hpf6_5MHz; + bool hpf1_5MHz; + +private slots: + void alexManualStateChanged(QObject *sender, bool value); + + void hpfLoSpinBoxValueChanged(double value); + void hpfHiSpinBoxValueChanged(double value); + void lpfLoSpinBoxValueChanged(double value); + void lpfHiSpinBoxValueChanged(double value); + + //void setFrequency(QObject * sender, bool value, int rx, long frequency); + void setFrequency(QObject * sender, int mode, int rx, long frequency); + void setCurrentReceiver(QObject *sender, int rx); + void setAlexConfiguration(double frequency); + void manualFilterBtnClicked(); + void defaultValuesBtnClicked(); + void bypassAllHPFBtnClicked(); + void lowNoise6mAmpBtnClicked(); + void hpf13MHzBtnClicked(); + void hpf20MHzBtnClicked(); + void hpf9_5MHzBtnClicked(); + void hpf6_5MHzBtnClicked(); + void hpf1_5MHzBtnClicked(); + +signals: + void showEvent(QObject* sender); + void closeEvent(QObject* sender); + void messageEvent(QString); +}; + +#endif // _CUSDR_ALEX_FILTER_WIDGET_H diff --git a/Source/src/cusdr_alexTabWidget.cpp b/Source/src/cusdr_alexTabWidget.cpp new file mode 100644 index 0000000..f718976 --- /dev/null +++ b/Source/src/cusdr_alexTabWidget.cpp @@ -0,0 +1,86 @@ +/** +* @file cusdr_alexTabWidget.cpp +* @brief Alex settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-23 +*/ + +/* + * + * Copyright 2010-2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "cusdr_alexTabWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +AlexTabWidget::AlexTabWidget(QWidget *parent) + : QTabWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + setStyleSheet(set->getTabWidgetStyle()); + //setMinimumWidth(m_minimumWidgetWidth); + //setMaximumWidth (247); + setContentsMargins(4, 4, 4, 0); + setMouseTracking(true); + + m_alexAntennaWidget = new AlexAntennaWidget(this); + m_alexFilterWidget = new AlexFilterWidget(this); + + this->addTab(m_alexAntennaWidget, "Antenna"); + this->addTab(m_alexFilterWidget, "Filter"); + + setupConnections(); +} + +AlexTabWidget::~AlexTabWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize AlexTabWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize AlexTabWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void AlexTabWidget::setupConnections() { + +} + +void AlexTabWidget::addNICChangedConnection() { + + //m_hpsdrWidget->addNICChangedConnection(); +} diff --git a/Source/src/cusdr_alexTabWidget.h b/Source/src/cusdr_alexTabWidget.h new file mode 100644 index 0000000..40198dd --- /dev/null +++ b/Source/src/cusdr_alexTabWidget.h @@ -0,0 +1,69 @@ +/** +* @file cusdr_alexTabWidget.h +* @brief Alex settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-23 +*/ + +/* + * + * Copyright 2010-2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_ALEX_TABWIDGET_H +#define _CUSDR_ALEX_TABWIDGET_H + +//#include +//#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_alexAntennaWidget.h" +#include "cusdr_alexFilterWidget.h" + + +class AlexTabWidget : public QTabWidget { + + Q_OBJECT + +public: + AlexTabWidget(QWidget *parent = 0); + ~AlexTabWidget(); + + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + void addNICChangedConnection(); + +private: + Settings *set; + + AlexAntennaWidget *m_alexAntennaWidget; + AlexFilterWidget *m_alexFilterWidget; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + +}; + +#endif // _CUSDR_ALEX_TABWIDGET_H diff --git a/Source/src/cusdr_chirpWidget.cpp b/Source/src/cusdr_chirpWidget.cpp new file mode 100644 index 0000000..bc7bb5a --- /dev/null +++ b/Source/src/cusdr_chirpWidget.cpp @@ -0,0 +1,1103 @@ +/** +* @file cusdr_chirpWidget.cpp +* @brief Chirp signal settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-05-21 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_CHIRP_WIDGET + +//#include +//#include +//#include +//#include +#include +#include +#include +#include + +#include "cusdr_chirpWidget.h" + +#define btn_height 15 +#define btn_width 80 +#define btn_width2 52 + +ChirpWidget::ChirpWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(set->getDataEngineState()) + , m_timeScaleMax(2) + , m_graphWidth(200) + , m_graphHeight(100) + , m_antialiased(true) + , m_mouseOver(false) + , m_showChirpFFT(false) + , m_chirpUSB(false) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) + , m_btnSpacing(5) + , m_cnt(0) +{ + //setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 0, 4, 0); + setMouseTracking(true); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_stripes.resize(100); + m_timeScale = m_graphWidth / m_timeScaleMax; + stripeFreqRange(); + + // **************** + + createChirpModeGroup(); + createPlayFileGroup(); + createChirpSignalGroup(); + createMatchedFilterControlGroup(); + + set->setChirpReceiver(false); + + spectrumLabel = new QLabel(this); + createChirpSpectrumGroup(); + + //************************************************************** + // set main layout + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setMargin(0); + hbox1->addStretch(); + hbox1->addWidget(chirpModeGroupBox); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addStretch(); + hbox2->addWidget(playFileGroupBox); + + QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(0); + hbox3->setMargin(0); + hbox3->addStretch(); + hbox3->addWidget(chirpSignalGroupBox); + + QHBoxLayout *hbox4 = new QHBoxLayout; + hbox4->setSpacing(0); + hbox4->setMargin(0); + hbox4->addStretch(); + hbox4->addWidget(matchedFilterControlGroupBox); + + + QHBoxLayout *hbox5 = new QHBoxLayout; + hbox5->setSpacing(0); + hbox5->setMargin(0); + hbox5->addStretch(); + hbox5->addWidget(chirpSpectrumGroupBox); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addLayout(hbox4); + mainLayout->addLayout(hbox5); + mainLayout->addStretch(); + + setLayout(mainLayout); + + setupConnections(); + initChirpDecoder(); + + //createSpectrum(); +} + +ChirpWidget::~ChirpWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize ChirpWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize ChirpWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void ChirpWidget::setupConnections() { + + /*CHECKED_CONNECT( + set, + SIGNAL(audioBufferChanged(QObject *, qint64, qint64, const QByteArray)), + this, + SLOT(chirpBufferChanged(QObject *, qint64, qint64, const QByteArray)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(lowerChirpFreqChanged(QObject *, int)), + this, + SLOT(setChirpLowerFrequency(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(upperChirpFreqChanged(QObject *, int)), + this, + SLOT(setChirpUpperFrequency(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(chirpBufferDurationUsChanged(QObject *, qint64)), + this, + SLOT(setChirpBufferDurationUs(QObject *, qint64))); + + CHECKED_CONNECT( + set, + SIGNAL(chirpRepetitionTimesChanged(QObject *, int)), + this, + SLOT(setChirpRepetitionTimes(QObject *, int))); + + /*CHECKED_CONNECT( + set, + SIGNAL(chirpSpectrumChanged(qint64, qint64, const FrequencySpectrum &)), + this, + SLOT(chirpSpectrumChanged(qint64, qint64, const FrequencySpectrum &)));*/ + + CHECKED_CONNECT( + set, + SIGNAL(chirpSpectrumListChanged(const QList &)), + this, + SLOT(chirpSpectrumListChanged(const QList &))); + +} + +void ChirpWidget::createChirpModeGroup() { + + chirpModeBtn = new AeroButton("Decoding", this); + chirpModeBtn->setRoundness(10); + chirpModeBtn->setFixedSize(btn_width, btn_height); + chirpModeBtn->setBtnState(AeroButton::ON); + + CHECKED_CONNECT( + chirpModeBtn, + SIGNAL(clicked()), + this, + SLOT(initChirpDecoder())); + + loadFileBtn = new AeroButton("Load File", this); + loadFileBtn->setRoundness(10); + loadFileBtn->setFixedSize(btn_width, btn_height); + loadFileBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + loadFileBtn, + SIGNAL(clicked()), + this, + SLOT(showFileDialog())); + + /*rcveBtn = new AeroButton("Receiver", this); + rcveBtn->setRoundness(10); + rcveBtn->setFixedSize(btn_width, btn_height); + rcveBtn->setBtnState(AeroButton::OFF);*/ + + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(chirpModeBtn); + hbox1->addWidget(loadFileBtn); + //hbox1->addStretch(); + + /*QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(4); + hbox2->addStretch(); + hbox2->addWidget(rcveBtn);*/ + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + //vbox->addLayout(hbox2); + + chirpModeGroupBox = new QGroupBox(tr("Chirp WSPR"), this); + chirpModeGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + chirpModeGroupBox->setLayout(vbox); + chirpModeGroupBox->setStyleSheet(set->getWidgetStyle()); + chirpModeGroupBox->setFont(QFont("Arial", 8)); +} + +void ChirpWidget::createPlayFileGroup() { + + pauseBtn = new AeroButton("Pause", this); + pauseBtn->setRoundness(10); + pauseBtn->setFixedSize(btn_width2, btn_height); + pauseBtn->setBtnState(AeroButton::OFF); + pauseBtn->setEnabled(false); + CHECKED_CONNECT( + pauseBtn, + SIGNAL(clicked()), + this, + SLOT(suspend())); + + playBtn = new AeroButton("Play", this); + playBtn->setRoundness(10); + playBtn->setFixedSize(btn_width2, btn_height); + playBtn->setBtnState(AeroButton::OFF); + playBtn->setEnabled(false); + CHECKED_CONNECT( + playBtn, + SIGNAL(clicked()), + this, + SLOT(startPlayback())); + + settingsBtn = new AeroButton("Settings", this); + settingsBtn->setRoundness(10); + settingsBtn->setFixedSize(btn_width2, btn_height); + settingsBtn->setBtnState(AeroButton::OFF); + settingsBtn->setEnabled(true); + CHECKED_CONNECT( + settingsBtn, + SIGNAL(clicked()), + this, + SLOT(showSettingsDialog())); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(m_btnSpacing); + hbox1->addStretch(); + hbox1->addWidget(pauseBtn); + hbox1->addWidget(playBtn); + hbox1->addWidget(settingsBtn); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(m_btnSpacing); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + + playFileGroupBox = new QGroupBox(tr("Sound File"), this); + playFileGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + playFileGroupBox->setLayout(vbox); + playFileGroupBox->setStyleSheet(set->getWidgetStyle()); + playFileGroupBox->setFont(QFont("Arial", 8)); +} + +void ChirpWidget::createChirpSignalGroup() { + + //QFontMetrics d_fm(m_titleFont); + int fontMaxWidth = m_fonts.normalFontMetrics->boundingRect("00000").width(); + + QLabel *minFLabel = new QLabel(tr("lo :"), this); + minFLabel->setFont(m_fonts.normalFont); + minFLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *maxFLabel = new QLabel(tr("hi :"), this); + maxFLabel->setFont(m_fonts.normalFont); + maxFLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *freqLabel = new QLabel(tr(" Hz"), this); + freqLabel->setFont(m_fonts.normalFont); + freqLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *timeLabel = new QLabel(tr("chirp length :"), this); + timeLabel->setFont(m_fonts.normalFont); + timeLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *msecLabel = new QLabel(tr(" ms"), this); + msecLabel->setFont(m_fonts.normalFont); + msecLabel->setStyleSheet(set->getLabelStyle()); + + /*QLabel *repetitionLabel = new QLabel(tr("repetitions :"), this); + repetitionLabel->setFont(m_titleFont); + repetitionLabel->setStyleSheet(set->getLabelStyle());*/ + + lowerFreqSpinBox = new QSpinBox(this); + lowerFreqSpinBox->setStyleSheet(set->getSpinBoxStyle()); + lowerFreqSpinBox->setFixedWidth(fontMaxWidth + 30); + lowerFreqSpinBox->setRange(0, 10000); + lowerFreqSpinBox->setSingleStep(10); + lowerFreqSpinBox->setValue(set->getLowerChirpFreq()); + + CHECKED_CONNECT( + lowerFreqSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setLowerChirpFreq(int))); + + upperFreqSpinBox = new QSpinBox(this); + upperFreqSpinBox->setStyleSheet(set->getSpinBoxStyle()); + upperFreqSpinBox->setFixedWidth(fontMaxWidth + 30); + upperFreqSpinBox->setRange(50, 10000); + upperFreqSpinBox->setSingleStep(10); + upperFreqSpinBox->setValue(set->getUpperChirpFreq()); + + CHECKED_CONNECT( + upperFreqSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setUpperChirpFreq(int))); + + timeSpinBox = new QSpinBox(this); + timeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + timeSpinBox->setFixedWidth(fontMaxWidth + 30); + timeSpinBox->setRange(100, 10000); + timeSpinBox->setSingleStep(1); + timeSpinBox->setValue(set->getChirpBufferDurationUs()/1000); + + CHECKED_CONNECT( + timeSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setChirpBufferDurationUs(int))); + + CHECKED_CONNECT( + timeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(stripeResize(int))); + + /*repetitionSpinBox = new QSpinBox(this); + repetitionSpinBox->setStyleSheet(set->getSpinBoxStyle()); + repetitionSpinBox->setFixedWidth(fontMaxWidth + 30); + repetitionSpinBox->setRange(1, 10); + repetitionSpinBox->setSingleStep(1); + repetitionSpinBox->setValue(set->getChirpRepetitionTimes()); + CHECKED_CONNECT( + repetitionSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setChirpRepetitionTimes(int)));*/ + + playChirpBtn = new AeroButton("Play", this); + playChirpBtn->setRoundness(10); + playChirpBtn->setFixedSize(btn_width2, btn_height); + playChirpBtn->setBtnState(AeroButton::OFF); + CHECKED_CONNECT( + playChirpBtn, + SIGNAL(clicked()), + this, + SLOT(startPlayback())); + + /*chirpForwardBtn = new AeroButton("Forward", this); + chirpForwardBtn->setRoundness(10); + chirpForwardBtn->setFixedSize(btn_width2, btn_height); + + chirpBackwardBtn = new AeroButton("Backward", this); + chirpBackwardBtn->setRoundness(10); + chirpBackwardBtn->setFixedSize(btn_width2, btn_height);*/ + + /*chirpLSBBtn = new AeroButton("LSB", this); + chirpLSBBtn->setRoundness(10); + chirpLSBBtn->setFixedSize(btn_width2, btn_height); + chirpLSBBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + chirpLSBBtn, + SIGNAL(clicked()), + this, + SLOT(switchSideband())); + + chirpUSBBtn = new AeroButton("USB", this); + chirpUSBBtn->setRoundness(10); + chirpUSBBtn->setFixedSize(btn_width2, btn_height); + chirpUSBBtn->setBtnState(AeroButton::ON); + + CHECKED_CONNECT( + chirpUSBBtn, + SIGNAL(clicked()), + this, + SLOT(switchSideband()));*/ + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(m_btnSpacing); + hbox1->addStretch(); + hbox1->addWidget(minFLabel); + hbox1->addWidget(lowerFreqSpinBox); + hbox1->addSpacing(6); + hbox1->addWidget(maxFLabel); + hbox1->addWidget(upperFreqSpinBox); + hbox1->addSpacing(1); + hbox1->addWidget(freqLabel); + //hbox1->addWidget(playChirpBtn); + //hbox1->addStretch(); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(m_btnSpacing); + hbox2->addStretch(); + hbox2->addWidget(timeLabel); + hbox2->addWidget(timeSpinBox); + hbox2->addWidget(msecLabel); + //hbox2->addStretch(); + + /*QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(m_btnSpacing); + hbox3->addStretch(); + hbox3->addWidget(repetitionLabel); + hbox3->addWidget(repetitionSpinBox); + hbox3->addSpacing(d_fm.boundingRect(" ms").width());*/ + + /*QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(m_btnSpacing); + hbox3->addStretch(); + hbox3->addWidget(chirpForwardBtn); + hbox3->addWidget(chirpBackwardBtn);*/ + + /*QHBoxLayout *hbox4 = new QHBoxLayout; + hbox4->setSpacing(m_btnSpacing); + hbox4->addStretch(); + hbox4->addWidget(chirpLSBBtn); + hbox4->addWidget(chirpUSBBtn);*/ + + QHBoxLayout *hbox5 = new QHBoxLayout; + hbox5->setSpacing(m_btnSpacing); + hbox5->addStretch(); + hbox5->addWidget(playChirpBtn); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(m_btnSpacing); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + vbox->addSpacing(6); + //vbox->addLayout(hbox3); + //vbox->addLayout(hbox4); + vbox->addLayout(hbox5); + + chirpSignalGroupBox = new QGroupBox(tr("Chirp Signal"), this); + chirpSignalGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + chirpSignalGroupBox->setLayout(vbox); + chirpSignalGroupBox->setStyleSheet(set->getWidgetStyle()); + chirpSignalGroupBox->setFont(QFont("Arial", 8)); +} + +void ChirpWidget::createChirpSpectrumGroup() { + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(m_btnSpacing); + hbox1->addStretch(); + hbox1->addWidget(spectrumLabel); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(m_btnSpacing); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + + chirpSpectrumGroupBox = new QGroupBox(tr("Chirp Signal Spectrum"), this); + chirpSpectrumGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + chirpSpectrumGroupBox->setLayout(vbox); + chirpSpectrumGroupBox->setStyleSheet(set->getWidgetStyle()); + chirpSpectrumGroupBox->setFont(QFont("Arial", 8)); +} + +void ChirpWidget::createMatchedFilterControlGroup() { + + //QFontMetrics d_fm(m_titleFont); + int fontMaxWidth = m_fonts.normalFontMetrics->boundingRect("00000").width(); + + /*avgBtn = new AeroButton("AVG", this); + avgBtn->setRoundness(10); + avgBtn->setFixedSize(btn_width2, btn_height); + avgBtn->setBtnState(AeroButton::OFF);*/ + + QLabel *avgLabel = new QLabel(tr("Avg:"), this); + avgLabel->setFont(m_fonts.normalFont); + avgLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *secLabel = new QLabel(tr(" s"), this); + secLabel->setFont(m_fonts.normalFont); + secLabel->setStyleSheet(set->getLabelStyle()); + + avgSpinBox = new QSpinBox(this); + avgSpinBox->setStyleSheet(set->getSpinBoxStyle()); + avgSpinBox->setFixedWidth(fontMaxWidth + 30); + avgSpinBox->setRange(1, 120); + avgSpinBox->setSingleStep(1); + avgSpinBox->setValue(1); + + CHECKED_CONNECT( + avgSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setChirpAvgLength(int))); + + /*QLabel *filterLabel = new QLabel(tr("FIR Bandpass:"), this); + filterLabel->setFont(m_titleFont); + filterLabel->setStyleSheet(set->getLabelStyle());*/ + + QLabel *loFilterLabel = new QLabel(tr("BPF lo :"), this); + loFilterLabel->setFont(m_fonts.normalFont); + loFilterLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *upFilterLabel = new QLabel(tr("hi :"), this); + upFilterLabel->setFont(m_fonts.normalFont); + upFilterLabel->setStyleSheet(set->getLabelStyle()); + + QLabel *freqFilterLabel = new QLabel(tr(" Hz"), this); + freqFilterLabel->setFont(m_fonts.normalFont); + freqFilterLabel->setStyleSheet(set->getLabelStyle()); + + filterLowerFreqSpinBox = new QSpinBox(this); + filterLowerFreqSpinBox->setStyleSheet(set->getSpinBoxStyle()); + filterLowerFreqSpinBox->setFixedWidth(fontMaxWidth + 30); + filterLowerFreqSpinBox->setRange(0, 5000); + filterLowerFreqSpinBox->setSingleStep(10); + filterLowerFreqSpinBox->setValue(set->getChirpFilterLowerFrequency()); + + CHECKED_CONNECT( + filterLowerFreqSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setChirpFilterLowerFrequency(int))); + + filterUpperFreqSpinBox = new QSpinBox(this); + filterUpperFreqSpinBox->setStyleSheet(set->getSpinBoxStyle()); + filterUpperFreqSpinBox->setFixedWidth(fontMaxWidth + 30); + filterUpperFreqSpinBox->setRange(50, 10000); + filterUpperFreqSpinBox->setSingleStep(10); + filterUpperFreqSpinBox->setValue(set->getChirpFilterUpperFrequency()); + + CHECKED_CONNECT( + filterUpperFreqSpinBox, + SIGNAL(valueChanged(int)), + set, + SLOT(setChirpFilterUpperFrequency(int))); + + + showChirpFFTBtn = new AeroButton("Show Rx spectrum", this); + showChirpFFTBtn->setRoundness(10); + showChirpFFTBtn->setFixedSize(100, btn_height); + showChirpFFTBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + showChirpFFTBtn, + SIGNAL(clicked()), + this, + SLOT(showChirpFFT())); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(m_btnSpacing); + hbox1->addStretch(); + hbox1->addWidget(avgLabel); + hbox1->addWidget(avgSpinBox); + hbox1->addSpacing(1); + hbox1->addWidget(secLabel); + + /*QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(m_btnSpacing); + hbox2->addSpacing(6); + hbox2->addWidget(filterLabel);*/ + //hbox2->addStretch(); + + QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(m_btnSpacing); + hbox3->addStretch(); + hbox3->addWidget(loFilterLabel); + hbox3->addWidget(filterLowerFreqSpinBox); + hbox3->addSpacing(6); + hbox3->addWidget(upFilterLabel); + hbox3->addWidget(filterUpperFreqSpinBox); + hbox3->addSpacing(1); + hbox3->addWidget(freqFilterLabel); + + QHBoxLayout *hbox4 = new QHBoxLayout; + hbox4->setSpacing(m_btnSpacing); + hbox4->addStretch(); + hbox4->addWidget(showChirpFFTBtn); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(m_btnSpacing); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + //vbox->addLayout(hbox2); + vbox->addLayout(hbox3); + vbox->addSpacing(6); + vbox->addLayout(hbox4); + + matchedFilterControlGroupBox = new QGroupBox(tr("Matched Filter Control"), this); + matchedFilterControlGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + matchedFilterControlGroupBox->setLayout(vbox); + matchedFilterControlGroupBox->setStyleSheet(set->getWidgetStyle()); + matchedFilterControlGroupBox->setFont(QFont("Arial", 8)); +} + +void ChirpWidget::showFileDialog() { + + if (chirpModeBtn->btnState() == AeroButton::ON) { + + chirpModeBtn->setBtnState(AeroButton::OFF); + loadFileBtn->setBtnState(AeroButton::ON); + chirpModeBtn->update(); + } + + const QString dir; + const QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open WAV file"), dir, "*.wav"); + + if (fileNames.count()) { + + set->setSystemState( + this, + QSDR::NoError, + //m_hwInterface, + QSDR::NoInterfaceMode, + QSDR::ChirpWSPRFile, + QSDR::DataEngineDown); + emit messageEvent("[server]: switched to chirp decode file mode."); + emit loadFileEvent(this, fileNames.front()); + //updateButtonStates(); + playBtn->setEnabled(true); + pauseBtn->setEnabled(true); + } + else { + + playBtn->setEnabled(false); + pauseBtn->setEnabled(false); + } +} + +void ChirpWidget::initChirpDecoder() { + + if (loadFileBtn->btnState() == AeroButton::ON) { + + chirpModeBtn->setBtnState(AeroButton::ON); + loadFileBtn->setBtnState(AeroButton::OFF); + + playBtn->setEnabled(false); + pauseBtn->setEnabled(false); + loadFileBtn->update(); + + set->setSystemState( + this, + QSDR::NoError, + m_hwInterface, + QSDR::ChirpWSPR, + QSDR::DataEngineDown); + emit messageEvent("[server]: switched to chirp decode mode."); + } + + set->switchToChirpSignalMode(this); +} + +void ChirpWidget::setReceiver() { + + if (rcveBtn->btnState() == AeroButton::OFF) { + + rcveBtn->setBtnState(AeroButton::ON); + set->setChirpReceiver(true); + + } + else + if (rcveBtn->btnState() == AeroButton::ON) { + + rcveBtn->setBtnState(AeroButton::OFF); + set->setChirpReceiver(false); + } +} + +void ChirpWidget::showChirpFFT() { + + if (m_showChirpFFT) { + + showChirpFFTBtn->setBtnState(AeroButton::OFF); + set->setChirpFFTShow(false); + m_showChirpFFT = false; + } + else { + + showChirpFFTBtn->setBtnState(AeroButton::ON); + set->setChirpFFTShow(true); + m_showChirpFFT = true; + } + +} + +void ChirpWidget::switchSideband() { + + if (m_chirpUSB) { + + chirpLSBBtn->setBtnState(AeroButton::OFF); + chirpUSBBtn->setBtnState(AeroButton::ON); + chirpLSBBtn->update(); + chirpUSBBtn->update(); + set->setChirpUSB(true); + m_chirpUSB = false; + } + else { + + chirpLSBBtn->setBtnState(AeroButton::ON); + chirpUSBBtn->setBtnState(AeroButton::OFF); + chirpLSBBtn->update(); + chirpUSBBtn->update(); + set->setChirpUSB(false); + m_chirpUSB = true; + } +} + +//void ChirpWidget::chirpBufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer) { +// +// Q_UNUSED (sender) +// +// CHIRP_WIDGET_DEBUG << "audioBufferChanged" +// << "bufferPosition" << position +// << "bufferLength" << length; +// +// m_chirpBufferPosition = position; +// m_chirpBufferLength = length; +// m_chirpBuffer = buffer; +// +// +//} + +void ChirpWidget::chirpSpectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum) { + + CHIRP_WIDGET_DEBUG << "chirp spectrum changed!"; + + m_chirpPosition = position; + m_chirpLength = length; + m_spectrum = spectrum; + + CHIRP_WIDGET_DEBUG << "pos =" << m_chirpPosition; + + //updateStripes(); +} + +void ChirpWidget::chirpSpectrumListChanged(const QList &spectrumList) { + + //CHIRP_WIDGET_DEBUG << "chirp spectrumList changed!"; + + m_spectrumList = spectrumList; + updateStripes(); +} + +void ChirpWidget::resetSpectrum() { + + m_spectrum.reset(); + chirpSpectrumChanged(m_chirpPosition, m_chirpLength, m_spectrum); +} + +void ChirpWidget::suspend() { + + emit suspendSignal(this); +} + +void ChirpWidget::startPlayback() { + + emit startPlaybackSignal(this); +} + +void ChirpWidget::showSettingsDialog() { + + emit showSettingsDialogSignal(this); +} + +void ChirpWidget::setChirpLowerFrequency(QObject* sender, int lo) { + + Q_UNUSED(sender) + + if (lo >= upperFreqSpinBox->value()) + lowerFreqSpinBox->setValue(upperFreqSpinBox->value()); +} + +void ChirpWidget::setChirpUpperFrequency(QObject* sender, int hi) { + + Q_UNUSED(sender) + + if (hi <= lowerFreqSpinBox->value()) + upperFreqSpinBox->setValue(lowerFreqSpinBox->value()); +} + +void ChirpWidget::setChirpAmplitude(QObject* sender, qreal amp) { + + Q_UNUSED(sender) + Q_UNUSED(amp) + +} + +void ChirpWidget::setChirpBufferDurationUs(QObject* sender, qint64 value) { + + Q_UNUSED(sender) + Q_UNUSED(value) +} + +void ChirpWidget::setChirpRepetitionTimes(QObject* sender, int value) { + + Q_UNUSED(sender) + Q_UNUSED(value) +} + +void ChirpWidget::setFilterLowerFrequency(QObject* sender, int value) { + + Q_UNUSED(sender) + Q_UNUSED(value) +} + +void ChirpWidget::setFilterUpperFrequency(QObject* sender, int value) { + + Q_UNUSED(sender) + Q_UNUSED(value) +} + +int ChirpWidget::stripeIndex(qreal frequency) const { + + Q_ASSERT(frequency >= m_lowFreq && frequency < m_highFreq); + + const qreal bandWidth = (m_highFreq - m_lowFreq) / m_stripes.count(); + const int index = (frequency - m_lowFreq) / bandWidth; + + if(index < 0 || index >= m_stripes.count()) Q_ASSERT(false); + + return index; +} + +QPair ChirpWidget::stripeRange(int index) const { + + Q_ASSERT(index >= 0 && index < m_stripes.count()); + + const qreal bandWidth = (m_highFreq - m_lowFreq) / m_stripes.count(); + + return QPair(index * bandWidth, (index+1) * bandWidth); +} + +void ChirpWidget::stripeFreqRange() { + + //int lo = set->getLowerChirpFreq(); + int hi = set->getUpperChirpFreq(); + + //int unit = qRound((hi - lo) / 8); + //m_lowFreq = 100; + //m_highFreq = hi + unit; + m_lowFreq = 0; + + if (hi < 5000) + m_highFreq = 5000; + else + m_highFreq = 10000; +} + +void ChirpWidget::updateStripes() { + + if (m_stripeList.count() > 0) + m_stripeList.clear(); + + stripeFreqRange(); + foreach(FrequencySpectrum spectrum, m_spectrumList) { + + m_stripes.fill(Stripe()); + FrequencySpectrum::const_iterator i = spectrum.begin(); + const FrequencySpectrum::const_iterator end = spectrum.end(); + + for ( ; i != end; ++i) { + + const FrequencySpectrum::Element e = *i; + if (e.frequency >= m_lowFreq && e.frequency < m_highFreq) { + + Stripe &stripe = m_stripes[stripeIndex(e.frequency)]; + stripe.value = qMax(stripe.value, e.amplitude); + stripe.clipped |= e.clipped; + } + } + m_stripeList.append(m_stripes); + } + + createSpectrum(); +} + +void ChirpWidget::stripeResize(int scale) { + + qreal s = scale/1000.0; + if (s <= 2.0) + m_timeScaleMax = 2; + else + if (s <= 5.0) + m_timeScaleMax = 5; + else + m_timeScaleMax = 10; + + m_timeScale = s * m_graphWidth / m_timeScaleMax; + + updateStripes(); +} + +//void ChirpWidget::selectStripe(int index) { +// const QPair frequencyRange = stripeRange(index); +// const QString message = QString("%1 - %2 Hz") +// .arg(frequencyRange.first) +// .arg(frequencyRange.second); +// emit infoMessage(message, StripeSelectionInterval); +// +// if (NullTimerId != m_timerId) +// killTimer(m_timerId); +// m_timerId = startTimer(StripeSelectionInterval); +// +// m_stripeSelected = index; +// update(); +//} + +void ChirpWidget::createSpectrum() { + + m_resultImage = QImage(220, 150, QImage::Format_ARGB32_Premultiplied); + + QPainter painter(&m_resultImage); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(m_resultImage.rect(), Qt::transparent); + painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing, true); + + QRect rect(0, 0, m_graphWidth + 20, m_graphHeight + 20); + QImage* stripeImage; + stripeImage = createSpectrumImage(rect); + + if (stripeImage) { + + painter.drawImage(0, 0, *stripeImage); + delete stripeImage; + } + + painter.end(); + + spectrumLabel->setPixmap(QPixmap::fromImage(m_resultImage)); +} + +QImage* ChirpWidget::createSpectrumImage(const QRect& rect) { + + QImage *image = new QImage(rect.size(), QImage::Format_ARGB32_Premultiplied); + if (!image) return NULL; + + QPainter painter(image); + painter.setFont(m_fonts.smallFont); + //painter.fillRect(image->rect(), Qt::transparent); + painter.fillRect(image->rect(), Qt::black); + + QFontMetrics sfm(m_fonts.smallFont); + m_fontHeight = sfm.height(); + m_maxFontWidth = sfm.width("00000 Hz"); + + int s = 0; + int length = m_stripeList.count(); + + if (length > 0) + //m_scale = (qreal)(1.0f * m_graphWidth / length); + m_scale = m_timeScale / length; + else + m_scale = 0; + + //CHIRP_WIDGET_DEBUG << "m_timeScale = " << m_timeScale; + + foreach(QVector stripe, m_stripeList) { + + int slength = stripe.count(); + for (int i = 0; i < slength; i++) { + + qreal v = stripe[i].value;// + 0.2f; + + //QColor color = QColor((int)(v * 55), (int)(v * 225), (int)(v * 255)); + //QColor color = QColor((int)(v * 255), (int)(v * 55), (int)(v * 255)); + QColor color = QColor((int)(v * 255), (int)(v * 55), (int)(v * 255)); + painter.setPen(QPen(color, 1)); + + int x1 = s * m_scale + 15; + int x2 = (s+1) * m_scale + 15; + int y = m_graphWidth/2 - (i+1); + + //if (x2 < m_graphWidth + 5) + painter.drawLine(x1, y, x2, y); + } + s++; + } + + QPen pen(QColor(45, 122, 148, 150), 1); + painter.setPen(pen); + + painter.drawRect(15, 0, m_graphWidth-1, m_graphHeight-1); + //painter.drawRect(0, 0, 10, m_graphHeight+9); + + pen.setColor(QColor(85, 162, 188, 255)); + painter.setPen(pen); + painter.rotate(-90); + + int scaleTextWidth = sfm.width("Frequency (kHz)"); + painter.drawText(- (scaleTextWidth + m_graphHeight) / 2, m_fontHeight - 5, "Frequency (kHz)"); + + painter.rotate(90); + scaleTextWidth = sfm.width("Time (sec)"); + painter.drawText(15 + (m_graphWidth - scaleTextWidth) / 2, 10 + m_graphHeight, "Time (sec)"); + painter.drawText(10, 10 + m_graphHeight, "0.0"); + + qreal t = 1.0f * m_timeScaleMax; + QString str = QString::number(t, 'f', 1); + painter.drawText(5 + m_graphWidth, 10 + m_graphHeight, str); + + //pen.setColor(QColor(225, 225, 225, 255)); + painter.setPen(pen); + + painter.drawText( + 18, 32 - m_fontHeight, + m_maxFontWidth, m_fontHeight, + Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, + "3.75"); + + painter.drawText( + 18, 57 - m_fontHeight, + m_maxFontWidth, m_fontHeight, + Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, + "2.50"); + + painter.drawText( + 18, 82 - m_fontHeight, + m_maxFontWidth, m_fontHeight, + Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, + "1.25"); + + pen.setStyle(Qt::DashLine); + pen.setColor(QColor(45, 122, 148, 110)); + painter.setPen(pen); + + painter.drawLine(42, 25, m_graphWidth + 15, 25); + painter.drawLine(42, 50, m_graphWidth + 15, 50); + painter.drawLine(42, 75, m_graphWidth + 15, 75); + + painter.drawLine(65, 0, 65, m_graphHeight); + painter.drawLine(115, 0, 115, m_graphHeight); + painter.drawLine(165, 0, 165, m_graphHeight); + //painter.drawLine(0, m_graphHeight, m_graphWidth, m_graphHeight); // bottom + + + painter.end(); + + return image; +} + +void ChirpWidget::resizeEvent(QResizeEvent *event) { + + //Q_UNUSED(event); + //QResizeEvent::oldSize() + + //QTimer::singleShot(10, this, SLOT(getRegion())); + //m_resizeFrame = true; + + QWidget::resizeEvent(event); +} diff --git a/Source/src/cusdr_chirpWidget.h b/Source/src/cusdr_chirpWidget.h new file mode 100644 index 0000000..efd0b6a --- /dev/null +++ b/Source/src/cusdr_chirpWidget.h @@ -0,0 +1,231 @@ +/** +* @file cusdr_chirpWidget.h +* @brief Chirp signal settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-05-21 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_CHIRP_WIDGET_H +#define _CUSDR_CHIRP_WIDGET_H + +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" + + +#ifdef LOG_CHIRP_WIDGET +# define CHIRP_WIDGET_DEBUG qDebug().nospace() << "ChirpWidget::\t" +#else +# define CHIRP_WIDGET_DEBUG nullDebug() +#endif + + +class ChirpWidget : public QWidget { + + Q_OBJECT + +public: + ChirpWidget(QWidget *parent = 0); + ~ChirpWidget(); + +protected: + void resizeEvent(QResizeEvent *event); + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + +private: + void setupConnections(); + void createChirpModeGroup(); + void createPlayFileGroup(); + void createChirpSignalGroup(); + void createChirpSpectrumGroup(); + void createMatchedFilterControlGroup(); + void createSpectrum(); + +private: + Settings *set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + CFonts *fonts; + TFonts m_fonts; + + QString m_menu_style; + QString lineedit_style; + + QLabel *labelAudioPortLabel; + QLabel *labelAudioPortText; + QLabel *spectrumLabel; + QLabel *controlLabel; + + QGroupBox *chirpModeGroupBox; + QGroupBox *playFileGroupBox; + QGroupBox *chirpSignalGroupBox; + QGroupBox *chirpSpectrumGroupBox; + QGroupBox *matchedFilterControlGroupBox; + + QComboBox *m_inputDeviceComboBox; + QComboBox *m_outputDeviceComboBox; + + QSpinBox *lowerFreqSpinBox; + QSpinBox *upperFreqSpinBox; + QSpinBox *timeSpinBox; + //QSpinBox *repetitionSpinBox; + QSpinBox *avgSpinBox; + QSpinBox *filterLowerFreqSpinBox; + QSpinBox *filterUpperFreqSpinBox; + + AeroButton *chirpModeBtn; + AeroButton *loadFileBtn; + AeroButton *rcveBtn; + AeroButton *pauseBtn; + AeroButton *playBtn; + AeroButton *settingsBtn; + AeroButton *playChirpBtn; + AeroButton *avgBtn; + AeroButton *chirpLSBBtn; + AeroButton *chirpUSBBtn; + AeroButton *chirpForwardBtn; + AeroButton *chirpBackwardBtn; + AeroButton *showChirpFFTBtn; + + QIcon pauseIcon; + QIcon playIcon; + QIcon settingsIcon; + + QRect m_spectrumRect; + QImage m_sourceImage; + QImage m_destinationImage; + QImage m_resultImage; + + QImage* createSpectrumImage(const QRect& rect); + + //QList m_specImages; + + struct Stripe { + Stripe() : value(0.0), clipped(false) { } + qreal value; + bool clipped; + }; + + QVector m_stripes; + int m_stripeSelected; + int m_timerId; + qreal m_lowFreq; + qreal m_highFreq; + FrequencySpectrum m_spectrum; + + QList m_spectrumList; + QList > m_stripeList; + + int stripeIndex(qreal frequency) const; + QPair stripeRange(int stripeIndex) const; + void stripeFreqRange(); + + + qreal m_scale; + qreal m_timeScale; + int m_timeScaleMax; + int m_fontHeight; + int m_maxFontWidth; + int m_graphWidth; + int m_graphHeight; + int m_graphScaleX; + + qint64 m_chirpPosition; + qint64 m_chirpLength; + + QVector m_freq; + + qint64 m_chirpBufferPosition; + qint64 m_chirpBufferLength; + QByteArray m_chirpBuffer; + + bool m_antialiased; + bool m_mouseOver; + bool m_showChirpFFT; + bool m_chirpUSB; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_btnSpacing; + int m_cnt; + +private slots: + /*void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state);*/ + + void initChirpDecoder(); + void showFileDialog(); + void setReceiver(); + void suspend(); + void startPlayback(); + void showSettingsDialog(); + void showChirpFFT(); + void switchSideband(); + + void setChirpLowerFrequency(QObject* sender, int lo); + void setChirpUpperFrequency(QObject* sender, int lo); + void setChirpAmplitude(QObject* sender, qreal amp); + void setChirpBufferDurationUs(QObject* sender, qint64 value); + void setChirpRepetitionTimes(QObject* sender, int value); + void setFilterLowerFrequency(QObject* sender, int lo); + void setFilterUpperFrequency(QObject* sender, int lo); + + //void chirpBufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + void chirpSpectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + void chirpSpectrumListChanged(const QList &spectrumList); + void resetSpectrum(); + void updateStripes(); + void stripeResize(int scale); + //void updateChirpSpectrum(); + //void selectBar(int index); + + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString ); + void initChirpDecoderEvent(QObject *sender, bool value); + void loadFileEvent(QObject *sender, const QString &fileName); + void suspendSignal(QObject *sender); + void startPlaybackSignal(QObject *sender); + void showSettingsDialogSignal(QObject *sender); +}; + +#endif // _CUSDR_CHIRP_WIDGET_H diff --git a/Source/src/cusdr_colorsWidget.cpp b/Source/src/cusdr_colorsWidget.cpp new file mode 100644 index 0000000..348a145 --- /dev/null +++ b/Source/src/cusdr_colorsWidget.cpp @@ -0,0 +1,711 @@ +/** +* @file cusdr_colorsWidget.cpp +* @brief OpenGL color options widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-08-19 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_COLOROPTIONS_WIDGET + +// use: COLOROPTIONS_DEBUG + +#include +#include +#include +#include +#include +#include +#include + +#include "cusdr_colorsWidget.h" + +#define btn_height 15 +#define btn_width 70 +#define btn_widths 38 +#define btn_width2 52 +#define btn_width3 60 + +ColorOptionsWidget::ColorOptionsWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(set->getDataEngineState()) + //, m_panadapterMode(set->getPanadapterMode()) + //, m_waterColorScheme(set->getWaterfallColorScheme()) + , m_colorTriangle(new QtColorTriangle(this)) + , m_antialiased(true) + , m_mouseOver(false) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) + , m_btnSpacing(5) + , m_currentReceiver(set->getCurrentReceiver()) + , m_btnChooserHit(0) + , m_sampleRate(set->getSampleRate()) +{ + //setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 0, 4, 0); + setMouseTracking(true); + + m_rxDataList = set->getReceiverDataList(); + + createColorChooserWidget(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setMargin(0); + hbox1->addStretch(); + hbox1->addWidget(m_colorChooserWidget); + hbox1->addStretch(); + + mainLayout->addLayout(hbox1); + mainLayout->addStretch(); + setLayout(mainLayout); + + m_panadapterColors = set->getPanadapterColors(); + m_oldPanadapterColors = m_panadapterColors; + + setupConnections(); +} + +ColorOptionsWidget::~ColorOptionsWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize ColorOptionsWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize ColorOptionsWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void ColorOptionsWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + m_colorTriangle, + SIGNAL(colorChanged(QColor)), + this, + SLOT(triangleColorChanged(QColor))); +} + +void ColorOptionsWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + bool change = false; + + if (m_hwInterface != hwmode) { + + m_hwInterface = hwmode; + //hwInterfaceChanged(); + change = true; + } + + if (m_serverMode != mode) { + + m_serverMode = mode; + change = true; + } + + if (m_dataEngineState != state) { + + m_dataEngineState = state; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + + } + else { + + + } + change = true; + } + if (!change) return; + + update(); +} + +void ColorOptionsWidget::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode) +{ + Q_UNUSED (sender) + Q_UNUSED (rx) + Q_UNUSED (panMode) + Q_UNUSED (waterfallColorMode) + + bool change = false; + + /*if (m_panadapterMode != panMode) { + + m_panadapterMode = panMode; + change = true; + } + + if (m_waterColorScheme != waterColorScheme) { + + m_waterColorScheme = waterColorScheme; + change = true; + }*/ + + if (!change) return; + + update(); +} + +void ColorOptionsWidget::createColorChooserWidget() { + + QColor col = set->getPanadapterColors().panCenterLineColor; + + m_setPanBackground = new AeroButton("Background", this); + m_setPanBackground->setRoundness(0); + m_setPanBackground->setFixedSize (btn_width3, btn_height); + m_setPanBackground->setStyleSheet(set->getMiniButtonStyle()); + m_setPanBackground->setColorOn(col); + m_changeColorBtnList.append(m_setPanBackground); + + CHECKED_CONNECT( + m_setPanBackground, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().waterfallColor; + + m_setWaterfall = new AeroButton("Waterfall", this); + m_setWaterfall->setRoundness(0); + m_setWaterfall->setFixedSize (btn_width3, btn_height); + m_setWaterfall->setStyleSheet(set->getMiniButtonStyle()); + m_setWaterfall->setColorOn(col); + m_changeColorBtnList.append(m_setWaterfall); + + CHECKED_CONNECT( + m_setWaterfall, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().panLineColor; + + m_setPanLine = new AeroButton("Pan Line", this); + m_setPanLine->setRoundness(0); + m_setPanLine->setFixedSize (btn_width3, btn_height); + m_setPanLine->setStyleSheet(set->getMiniButtonStyle()); + m_setPanLine->setColorOn(col); + m_changeColorBtnList.append(m_setPanLine); + + CHECKED_CONNECT( + m_setPanLine, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().panLineFilledColor; + + m_setPanLineFilling = new AeroButton("Pan Filling", this); + m_setPanLineFilling->setRoundness(0); + m_setPanLineFilling->setFixedSize (btn_width3, btn_height); + m_setPanLineFilling->setStyleSheet(set->getMiniButtonStyle()); + m_setPanLineFilling->setColorOn(col); + m_changeColorBtnList.append(m_setPanLineFilling); + + CHECKED_CONNECT( + m_setPanLineFilling, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().panSolidTopColor; + + m_setPanSolidTop = new AeroButton("Solid T", this); + m_setPanSolidTop->setRoundness(0); + m_setPanSolidTop->setFixedSize (btn_width3, btn_height); + m_setPanSolidTop->setStyleSheet(set->getMiniButtonStyle()); + m_setPanSolidTop->setColorOn(col); + m_changeColorBtnList.append(m_setPanSolidTop); + + CHECKED_CONNECT( + m_setPanSolidTop, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().panSolidBottomColor; + + m_setPanSolidBottom = new AeroButton("Solid B", this); + m_setPanSolidBottom->setRoundness(0); + m_setPanSolidBottom->setFixedSize (btn_width3, btn_height); + m_setPanSolidBottom->setStyleSheet(set->getMiniButtonStyle()); + m_setPanSolidBottom->setColorOn(col); + m_changeColorBtnList.append(m_setPanSolidBottom); + + CHECKED_CONNECT( + m_setPanSolidBottom, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().wideBandLineColor; + + m_setWideBandLine = new AeroButton("Wideband", this); + m_setWideBandLine->setRoundness(0); + m_setWideBandLine->setFixedSize (btn_width3, btn_height); + m_setWideBandLine->setStyleSheet(set->getMiniButtonStyle()); + m_setWideBandLine->setColorOn(col); + m_changeColorBtnList.append(m_setWideBandLine); + + CHECKED_CONNECT( + m_setWideBandLine, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().wideBandFilledColor; + + m_setWideBandFilling = new AeroButton("WB Filling", this); + m_setWideBandFilling->setRoundness(0); + m_setWideBandFilling->setFixedSize (btn_width3, btn_height); + m_setWideBandFilling->setStyleSheet(set->getMiniButtonStyle()); + m_setWideBandFilling->setColorOn(col); + m_changeColorBtnList.append(m_setWideBandFilling); + + CHECKED_CONNECT( + m_setWideBandFilling, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().wideBandSolidTopColor; + + m_setWideBandSolidTop = new AeroButton("WB Solid T", this); + m_setWideBandSolidTop->setRoundness(0); + m_setWideBandSolidTop->setFixedSize (btn_width3, btn_height); + m_setWideBandSolidTop->setStyleSheet(set->getMiniButtonStyle()); + m_setWideBandSolidTop->setColorOn(col); + m_changeColorBtnList.append(m_setWideBandSolidTop); + + CHECKED_CONNECT( + m_setWideBandSolidTop, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().wideBandSolidBottomColor; + + m_setWideBandSolidBottom = new AeroButton("WB Solid B", this); + m_setWideBandSolidBottom->setRoundness(0); + m_setWideBandSolidBottom->setFixedSize (btn_width3, btn_height); + m_setWideBandSolidBottom->setStyleSheet(set->getMiniButtonStyle()); + m_setWideBandSolidBottom->setColorOn(col); + m_changeColorBtnList.append(m_setWideBandSolidBottom); + + CHECKED_CONNECT( + m_setWideBandSolidBottom, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().wideBandSolidBottomColor; + + m_setDistanceLine = new AeroButton("Dist. Line", this); + m_setDistanceLine->setRoundness(0); + m_setDistanceLine->setFixedSize (btn_width3, btn_height); + m_setDistanceLine->setStyleSheet(set->getMiniButtonStyle()); + m_setDistanceLine->setColorOn(col); + m_changeColorBtnList.append(m_setDistanceLine); + + CHECKED_CONNECT( + m_setDistanceLine, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().wideBandSolidBottomColor; + + m_setDistanceLineFilling = new AeroButton("Dist. Filling", this); + m_setDistanceLineFilling->setRoundness(0); + m_setDistanceLineFilling->setFixedSize (btn_width3, btn_height); + m_setDistanceLineFilling->setStyleSheet(set->getMiniButtonStyle()); + m_setDistanceLineFilling->setColorOn(col); + m_changeColorBtnList.append(m_setDistanceLineFilling); + + CHECKED_CONNECT( + m_setDistanceLineFilling, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().panCenterLineColor; + + m_setPanCenterLine = new AeroButton("Center", this); + m_setPanCenterLine->setRoundness(0); + m_setPanCenterLine->setFixedSize (btn_width3, btn_height); + m_setPanCenterLine->setStyleSheet(set->getMiniButtonStyle()); + m_setPanCenterLine->setColorOn(col); + m_changeColorBtnList.append(m_setPanCenterLine); + + CHECKED_CONNECT( + m_setPanCenterLine, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + col = set->getPanadapterColors().gridLineColor; + + m_setGridLine = new AeroButton("Grid", this); + m_setGridLine->setRoundness(0); + m_setGridLine->setFixedSize (btn_width3, btn_height); + m_setGridLine->setStyleSheet(set->getMiniButtonStyle()); + m_setGridLine->setColorOn(col); + m_changeColorBtnList.append(m_setGridLine); + + CHECKED_CONNECT( + m_setGridLine, + SIGNAL(clicked()), + this, + SLOT(colorChooserChanged())); + + + m_setPanBackground->setBtnState(AeroButton::OFF); + m_setWaterfall->setBtnState(AeroButton::OFF); + m_setPanLine->setBtnState(AeroButton::OFF); + m_setPanLineFilling->setBtnState(AeroButton::OFF); + m_setPanSolidTop->setBtnState(AeroButton::OFF); + m_setPanSolidBottom->setBtnState(AeroButton::OFF); + m_setWideBandLine->setBtnState(AeroButton::OFF); + m_setWideBandFilling->setBtnState(AeroButton::OFF); + m_setWideBandSolidTop->setBtnState(AeroButton::OFF); + m_setWideBandSolidBottom->setBtnState(AeroButton::OFF); + m_setDistanceLine->setBtnState(AeroButton::OFF); + m_setDistanceLineFilling->setBtnState(AeroButton::OFF); + m_setPanCenterLine->setBtnState(AeroButton::OFF); + m_setGridLine->setBtnState(AeroButton::OFF); + + m_resetBtn = new AeroButton("Reset", this); + m_resetBtn->setRoundness(0); + //m_resetBtn->setFixedSize (btn_widths, btn_height); + m_resetBtn->setFixedSize (btn_width3, btn_height); + + CHECKED_CONNECT( + m_resetBtn, + SIGNAL(clicked()), + this, + SLOT(resetColors())); + + m_okBtn = new AeroButton("OK", this); + m_okBtn->setRoundness(0); + //m_okBtn->setFixedSize (btn_widths, btn_height); + m_okBtn->setFixedSize (btn_width3, btn_height); + + CHECKED_CONNECT( + m_okBtn, + SIGNAL(clicked()), + this, + SLOT(acceptColors())); + + + QGridLayout *grid1 = new QGridLayout; + grid1->setSpacing(1); + grid1->setHorizontalSpacing(1); + grid1->setContentsMargins(0, 0, 0, 0); + grid1->addWidget(m_colorTriangle, 0, 3, 5, 3); + grid1->addWidget(m_setPanBackground, 0, 0); + grid1->addWidget(m_setWaterfall, 0, 1); + grid1->addWidget(m_setPanLine, 1, 0); + grid1->addWidget(m_setPanLineFilling, 1, 1); + grid1->addWidget(m_setPanSolidTop, 2, 0); + grid1->addWidget(m_setPanSolidBottom, 2, 1); + grid1->addWidget(m_setWideBandLine, 3, 0); + grid1->addWidget(m_setWideBandFilling, 3, 1); + grid1->addWidget(m_setWideBandSolidTop, 4, 0); + grid1->addWidget(m_setWideBandSolidBottom, 4, 1); + grid1->addWidget(m_setDistanceLine, 5, 0); + grid1->addWidget(m_setDistanceLineFilling, 5, 1); + grid1->addWidget(m_setPanCenterLine, 6, 0); + grid1->addWidget(m_setGridLine, 6, 1); + grid1->addWidget(m_resetBtn, 8, 0); + grid1->addWidget(m_okBtn, 8, 1); + //grid1->addWidget(m_resetBtn, 7, 3); + //grid1->addWidget(m_okBtn, 7, 4); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(m_resetBtn); + hbox1->addWidget(m_okBtn); + + QVBoxLayout *vbox1 = new QVBoxLayout; + vbox1->setSpacing(4); + //vbox1->addStretch(); + vbox1->addWidget(m_colorTriangle); + vbox1->addLayout(hbox1); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setSpacing(4); + hbox->addSpacing(6); + hbox->addLayout(grid1); + //hbox->addLayout(vbox1); + + m_colorChooserWidget = new QGroupBox(tr("Color Chooser"), this); + m_colorChooserWidget->setMinimumWidth(m_minimumGroupBoxWidth); + m_colorChooserWidget->setLayout(hbox); + m_colorChooserWidget->setStyleSheet(set->getWidgetStyle()); + m_colorChooserWidget->setFont(QFont("Arial", 8)); +} + +void ColorOptionsWidget::colorChooserChanged() { + + AeroButton *button = qobject_cast(sender()); + m_btnChooserHit = m_changeColorBtnList.indexOf(button); + + foreach(AeroButton *btn, m_changeColorBtnList) { + + btn->setBtnState(AeroButton::OFF); + //btn->setColor(QColor(90, 90, 90)); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (m_btnChooserHit) { + + case 0: + m_colorTriangle->setColor(set->getPanadapterColors().panBackgroundColor); + break; + + case 1: + m_colorTriangle->setColor(set->getPanadapterColors().waterfallColor); + break; + + case 2: + m_colorTriangle->setColor(set->getPanadapterColors().panLineColor); + break; + + case 3: + m_colorTriangle->setColor(set->getPanadapterColors().panLineFilledColor); + break; + + case 4: + m_colorTriangle->setColor(set->getPanadapterColors().panSolidTopColor); + break; + + case 5: + m_colorTriangle->setColor(set->getPanadapterColors().panSolidBottomColor); + break; + + case 6: + m_colorTriangle->setColor(set->getPanadapterColors().wideBandLineColor); + break; + + case 7: + m_colorTriangle->setColor(set->getPanadapterColors().wideBandFilledColor); + break; + + case 8: + m_colorTriangle->setColor(set->getPanadapterColors().wideBandSolidTopColor); + break; + + case 9: + m_colorTriangle->setColor(set->getPanadapterColors().wideBandSolidBottomColor); + break; + + case 10: + m_colorTriangle->setColor(set->getPanadapterColors().distanceLineColor); + break; + + case 11: + m_colorTriangle->setColor(set->getPanadapterColors().distanceLineFilledColor); + break; + + case 12: + m_colorTriangle->setColor(set->getPanadapterColors().panCenterLineColor); + break; + + case 13: + m_colorTriangle->setColor(set->getPanadapterColors().gridLineColor); + break; + } +} + +void ColorOptionsWidget::resetColors() { + + m_panadapterColors = m_oldPanadapterColors; + + foreach(AeroButton *btn, m_changeColorBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + set->setPanadapterColors(m_panadapterColors); +} + +void ColorOptionsWidget::acceptColors() { + + m_oldPanadapterColors = m_panadapterColors; + set->setPanadapterColors(m_panadapterColors); +} + +void ColorOptionsWidget::triangleColorChanged(QColor color) { + + m_currentColor = color; + m_changeColorBtnList.at(m_btnChooserHit)->setColorOn(color); + m_changeColorBtnList.at(m_btnChooserHit)->update(); + + switch (m_btnChooserHit) { + + case 0: + m_panadapterColors.panBackgroundColor = color; + break; + + case 1: + m_panadapterColors.waterfallColor = color; + break; + + case 2: + m_panadapterColors.panLineColor = color; + break; + + case 3: + m_panadapterColors.panLineFilledColor = color; + break; + + case 4: + m_panadapterColors.panSolidTopColor = color; + break; + + case 5: + m_panadapterColors.panSolidBottomColor = color; + break; + + case 6: + m_panadapterColors.wideBandLineColor = color; + break; + + case 7: + m_panadapterColors.wideBandFilledColor = color; + break; + + case 8: + m_panadapterColors.wideBandSolidTopColor = color; + break; + + case 9: + m_panadapterColors.wideBandSolidBottomColor = color; + break; + + case 10: + m_panadapterColors.distanceLineColor = color; + break; + + case 11: + m_panadapterColors.distanceLineFilledColor = color; + break; + + case 12: + m_panadapterColors.panCenterLineColor = color; + break; + + case 13: + m_panadapterColors.gridLineColor = color; + break; + } + set->setPanadapterColors(m_panadapterColors); +} + +void ColorOptionsWidget::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; +} + +void ColorOptionsWidget::setCurrentReceiver(QObject *sender, int rx) { + + Q_UNUSED(sender) + + if (m_currentReceiver == rx) return; + m_currentReceiver = rx; +} diff --git a/Source/src/cusdr_colorsWidget.h b/Source/src/cusdr_colorsWidget.h new file mode 100644 index 0000000..331a3c7 --- /dev/null +++ b/Source/src/cusdr_colorsWidget.h @@ -0,0 +1,141 @@ +/** +* @file cusdr_colorsWidget.h +* @brief OpenGL color options widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-08-19 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_COLOR_OPTIONS_WIDGET_H +#define _CUSDR_COLOR_OPTIONS_WIDGET_H + +//#include +//#include +//#include +#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "Util/cusdr_colorTriangle.h" +#include "cusdr_settings.h" + +#ifdef LOG_COLOROPTIONS_WIDGET +# define COLOROPTIONS_DEBUG qDebug().nospace() << "ColorWidget::\t" +#else +# define COLOROPTIONS_DEBUG nullDebug() +#endif + + +class ColorOptionsWidget : public QWidget { + + Q_OBJECT + +public: + ColorOptionsWidget(QWidget *parent = 0); + ~ColorOptionsWidget(); + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + +private: + Settings *set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QtColorTriangle *m_colorTriangle; + QList m_rxDataList; + + QString m_menu_style; + + QColor m_currentColor; + QColor m_newColor; + + QGroupBox *m_colorChooserWidget; + + AeroButton *m_resetBtn; + AeroButton *m_okBtn; + AeroButton *m_setPanBackground; + AeroButton *m_setPanCenterLine; + AeroButton *m_setPanLine; + AeroButton *m_setPanLineFilling; + AeroButton *m_setPanSolidTop; + AeroButton *m_setPanSolidBottom; + AeroButton *m_setWaterfall; + AeroButton *m_setWideBandLine; + AeroButton *m_setWideBandFilling; + AeroButton *m_setWideBandSolidTop; + AeroButton *m_setWideBandSolidBottom; + AeroButton *m_setDistanceLine; + AeroButton *m_setDistanceLineFilling; + AeroButton *m_setGridLine; + + QList m_changeColorBtnList; + + TPanadapterColors m_panadapterColors; + TPanadapterColors m_oldPanadapterColors; + + int m_fontHeight; + int m_maxFontWidth; + + bool m_antialiased; + bool m_mouseOver; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_btnSpacing; + + int m_currentReceiver; + int m_btnChooserHit; + int m_sampleRate; + + void setupConnections(); + void createColorChooserWidget(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setCurrentReceiver(QObject *sender, int rx); + void colorChooserChanged(); + void resetColors(); + void acceptColors(); + void triangleColorChanged(QColor color); + void sampleRateChanged(QObject *sender, int value); + +signals: + void colorChanged(const QColor &color); +}; + +#endif // _CUSDR_COLOR_OPTIONS_WIDGET_H diff --git a/Source/src/cusdr_displayTabWidget.cpp b/Source/src/cusdr_displayTabWidget.cpp new file mode 100644 index 0000000..c60d033 --- /dev/null +++ b/Source/src/cusdr_displayTabWidget.cpp @@ -0,0 +1,198 @@ +/** +* @file cusdr_displayTabWidget.cpp +* @brief Display settings tab widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-10-30 +*/ + +/* + * + * Copyright 2010 - 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "cusdr_displayTabWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +DisplayTabWidget::DisplayTabWidget(QWidget *parent) + : QTabWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + setStyleSheet(set->getTabWidgetStyle()); + setContentsMargins(4, 4, 4, 0); + setMouseTracking(true); + + m_displayWidget = new DisplayOptionsWidget(this); + m_colorWidget = new ColorOptionsWidget(this); + + this->addTab(m_displayWidget, " Display "); + this->addTab(m_colorWidget, " Colors "); + + setTabEnabled(1, true); + setTabEnabled(2, true); + + setupConnections(); +} + +DisplayTabWidget::~DisplayTabWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize DisplayTabWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize DisplayTabWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void DisplayTabWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(alexPresenceChanged(bool)), + this, + SLOT(setAlexPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(penelopePresenceChanged(bool)), + this, + SLOT(setPennyPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(pennyLanePresenceChanged(bool)), + this, + SLOT(setPennyPresence(bool))); +} + +void DisplayTabWidget::systemStateChanged( + QObject *sender, /*!<[in] the sender of the signal. */ + QSDR::_Error err, /*!<[in] error state. */ + QSDR::_HWInterfaceMode hwmode, /*!<[in] HPSDR interface (Metis, Hermes, none). */ + QSDR::_ServerMode mode, /*!<[in] server mode. */ + QSDR::_DataEngineState state /*!<[in] data engine state. */ +) { + Q_UNUSED (sender) + Q_UNUSED (err) + + //if (sender == this) return; + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_hwInterface == QSDR::Hermes) + setTabEnabled(2, true); + else + setTabEnabled(2, false); + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; +} + +void DisplayTabWidget::setPennyPresence(bool value) { + + //setTabEnabled(1, value); + setTabEnabled(2, value); + //setTabEnabled(3, value); +} + +void DisplayTabWidget::setAlexPresence(bool value) { + + setTabEnabled(3, value); +} + +void DisplayTabWidget::addNICChangedConnection() { + + //m_networkWidget->addNICChangedConnection(); +} + +void DisplayTabWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void DisplayTabWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +void DisplayTabWidget::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void DisplayTabWidget::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void DisplayTabWidget::mouseMoveEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void DisplayTabWidget::mousePressEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void DisplayTabWidget::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + + diff --git a/Source/src/cusdr_displayTabWidget.h b/Source/src/cusdr_displayTabWidget.h new file mode 100644 index 0000000..6573a87 --- /dev/null +++ b/Source/src/cusdr_displayTabWidget.h @@ -0,0 +1,106 @@ +/** +* @file cusdr_displayTabWidget.h +* @brief Display settings tab widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-10-30 +*/ + +/* + * + * Copyright 2010 - 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_DISPLAY_TABWIDGET_H +#define _CUSDR_DISPLAY_TABWIDGET_H + +//#include +//#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_displayWidget.h" +#include "cusdr_colorsWidget.h" + +//#include "cusdr_networkWidget.h" +//#include "cusdr_transmitTabWidget.h" +//#include "cusdr_alexTabWidget.h" +//#include "cusdr_extCtrlWidget.h" + + +class DisplayTabWidget : public QTabWidget { + + Q_OBJECT + +public: + DisplayTabWidget(QWidget *parent = 0); + ~DisplayTabWidget(); + + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + void addNICChangedConnection(); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + Settings *set; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + DisplayOptionsWidget *m_displayWidget; + ColorOptionsWidget *m_colorWidget; + + QString m_message; + + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setAlexPresence(bool value); + void setPennyPresence(bool value); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString message); +}; + +#endif // _CUSDR_DISPLAY_TABWIDGET_H diff --git a/Source/src/cusdr_displayWidget.cpp b/Source/src/cusdr_displayWidget.cpp new file mode 100644 index 0000000..901ae69 --- /dev/null +++ b/Source/src/cusdr_displayWidget.cpp @@ -0,0 +1,1056 @@ +/** +* @file cusdr_displayWidget.cpp +* @brief OpenGL display options widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-08-19 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_DISPLAYOPTIONS_WIDGET + +// use: DISPLAYOPTIONS_DEBUG + +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_displayWidget.h" + +#define btn_height 15 +#define btn_width 70 +#define btn_widths 38 +#define btn_width2 52 +#define btn_width3 60 + +DisplayOptionsWidget::DisplayOptionsWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(set->getDataEngineState()) + , m_antialiased(true) + , m_mouseOver(false) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) + , m_btnSpacing(5) + , m_currentReceiver(set->getCurrentReceiver()) + , m_btnChooserHit(0) + , m_framesPerSecond(set->getFramesPerSecond(m_currentReceiver)) + , m_sampleRate(set->getSampleRate()) + , m_sMeterHoldTime(set->getSMeterHoldTime()) +{ + //setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 0, 4, 0); + setMouseTracking(true); + + m_rxDataList = set->getReceiverDataList(); + m_widebandOptions = set->getWidebandOptions(); + m_panadapterMode = set->getPanadapterMode(m_currentReceiver); + m_waterColorMode = set->getWaterfallColorMode(m_currentReceiver); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + createFPSGroupBox(); + createPanSpectrumOptions(); + createWidebandPanOptions(); + createWaterfallSpectrumOptions(); + createSMeterOptions(); + createCallSignEditor(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setMargin(0); + hbox1->addStretch(); + hbox1->addWidget(m_fpsGroupBox); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addStretch(); + hbox2->addWidget(m_panSpectrumOptions); + + QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(0); + hbox3->setMargin(0); + hbox3->addStretch(); + hbox3->addWidget(m_widebandPanOptions); + + QHBoxLayout *hbox4 = new QHBoxLayout; + hbox4->setSpacing(0); + hbox4->setMargin(0); + hbox4->addStretch(); + hbox4->addWidget(m_waterfallSpectrumOptions); + + QHBoxLayout *hbox5 = new QHBoxLayout; + hbox5->setSpacing(0); + hbox5->setMargin(0); + hbox5->addStretch(); + hbox5->addWidget(m_sMeterOptions); + + QHBoxLayout *hbox6 = new QHBoxLayout; + hbox6->setSpacing(0); + hbox6->setMargin(0); + hbox6->addStretch(); + hbox6->addWidget(m_callSignEditor); + hbox6->addStretch(); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addLayout(hbox4); + mainLayout->addLayout(hbox5); + mainLayout->addLayout(hbox6); + mainLayout->addStretch(); + setLayout(mainLayout); + + setupConnections(); +} + +DisplayOptionsWidget::~DisplayOptionsWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize DisplayOptionsWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize DisplayOptionsWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void DisplayOptionsWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(sampleRateChanged(QObject *, int)), + this, + SLOT(sampleRateChanged(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(framesPerSecondChanged(QObject*, int, int)), + this, + SLOT(setFramesPerSecond(QObject*, int, int))); +} + +void DisplayOptionsWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + bool change = false; + + if (m_hwInterface != hwmode) { + + m_hwInterface = hwmode; + //hwInterfaceChanged(); + change = true; + } + + if (m_serverMode != mode) { + + m_serverMode = mode; + change = true; + } + + if (m_dataEngineState != state) { + + m_dataEngineState = state; + + if (m_dataEngineState == QSDR::DataEngineUp) { + + + } + else { + + + } + change = true; + } + if (!change) return; + + update(); +} + +void DisplayOptionsWidget::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterMode) +{ + Q_UNUSED (sender) + + bool change = false; + + if (m_panadapterMode != panMode) { + + //m_panadapterMode = panMode; + if (m_currentReceiver == rx) + setPanadapterMode(m_currentReceiver); + + change = true; + } + + if (m_waterColorMode != waterMode) { + + //m_waterColorMode = waterMode; + if (m_currentReceiver == rx) + setWaterfallColorMode(m_currentReceiver); + change = true; + } + + if (!change) return; + + update(); +} + +void DisplayOptionsWidget::createFPSGroupBox() { + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect(" 200 ").width(); + + m_fpsSlider = new QSlider(Qt::Horizontal, this); + m_fpsSlider->setTickPosition(QSlider::NoTicks); + m_fpsSlider->setFixedSize(190, 12); + m_fpsSlider->setSingleStep(1); + m_fpsSlider->setRange(1, 80); + m_fpsSlider->setValue(m_framesPerSecond); + m_fpsSlider->setStyleSheet(set->getVolSliderStyle()); + + CHECKED_CONNECT(m_fpsSlider, SIGNAL(valueChanged(int)), this, SLOT(fpsValueChanged(int))); + + QString str = "%1 "; + m_fpsLevelLabel = new QLabel(str.arg(m_framesPerSecond, 2, 10, QLatin1Char(' ')), this); + m_fpsLevelLabel->setFont(m_fonts.smallFont); + m_fpsLevelLabel->setFixedSize(fontMaxWidth, 12); + m_fpsLevelLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_fpsLevelLabel->setStyleSheet(set->getSliderLabelStyle()); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setSpacing(0); + hbox->setMargin(0); + hbox->addStretch(); + hbox->addWidget(m_fpsSlider); + hbox->addWidget(m_fpsLevelLabel); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(6); + vbox->addSpacing(6); + vbox->addLayout(hbox); + + m_fpsGroupBox = new QGroupBox(tr("Frames per Second"), this); + m_fpsGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + m_fpsGroupBox->setLayout(vbox); + m_fpsGroupBox->setStyleSheet(set->getWidgetStyle()); + m_fpsGroupBox->setFont(QFont("Arial", 8)); +} + +void DisplayOptionsWidget::createPanSpectrumOptions() { + + m_PanLineBtn = new AeroButton("Line", this); + m_PanLineBtn->setRoundness(0); + m_PanLineBtn->setFixedSize(btn_width, btn_height); + m_panadapterBtnList.append(m_PanLineBtn); + + CHECKED_CONNECT( + m_PanLineBtn, + SIGNAL(clicked()), + this, + SLOT(panModeChanged())); + + m_PanFilledLineBtn = new AeroButton("Filled Line", this); + m_PanFilledLineBtn->setRoundness(0); + m_PanFilledLineBtn->setFixedSize(btn_width, btn_height); + m_panadapterBtnList.append(m_PanFilledLineBtn); + + CHECKED_CONNECT( + m_PanFilledLineBtn, + SIGNAL(clicked()), + this, + SLOT(panModeChanged())); + + m_PanSolidBtn = new AeroButton("Solid", this); + m_PanSolidBtn->setRoundness(0); + m_PanSolidBtn->setFixedSize (btn_width, btn_height); + m_panadapterBtnList.append(m_PanSolidBtn); + + CHECKED_CONNECT( + m_PanSolidBtn, + SIGNAL(clicked()), + this, + SLOT(panModeChanged())); + + switch (m_panadapterMode) { + + case (PanGraphicsMode) Line: + + m_PanLineBtn->setBtnState(AeroButton::ON); + m_PanFilledLineBtn->setBtnState(AeroButton::OFF); + m_PanSolidBtn->setBtnState(AeroButton::OFF); + break; + + case (PanGraphicsMode) FilledLine: + + m_PanFilledLineBtn->setBtnState(AeroButton::ON); + m_PanLineBtn->setBtnState(AeroButton::OFF); + m_PanSolidBtn->setBtnState(AeroButton::OFF); + break; + + case (PanGraphicsMode) Solid: + + m_PanSolidBtn->setBtnState(AeroButton::ON); + m_PanLineBtn->setBtnState(AeroButton::OFF); + m_PanFilledLineBtn->setBtnState(AeroButton::OFF); + break; + } + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect(" 200 ").width(); + + m_avgValue = set->getSpectrumAveragingCnt(m_currentReceiver); + + m_avgSlider = new QSlider(Qt::Horizontal, this); + m_avgSlider->setTickPosition(QSlider::NoTicks); + m_avgSlider->setFixedSize(130, 12); + m_avgSlider->setSingleStep(1); + m_avgSlider->setRange(1, 100); + m_avgSlider->setValue(m_avgValue); + m_avgSlider->setStyleSheet(set->getVolSliderStyle()); + + CHECKED_CONNECT(m_avgSlider, SIGNAL(valueChanged(int)), this, SLOT(averagingFilterCntChanged(int))); + + QString str = "%1 "; + m_avgLevelLabel = new QLabel(str.arg(m_avgValue, 2, 10, QLatin1Char(' ')), this); + m_avgLevelLabel->setFont(m_fonts.smallFont); + m_avgLevelLabel->setFixedSize(fontMaxWidth, 12); + m_avgLevelLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_avgLevelLabel->setStyleSheet(set->getSliderLabelStyle()); + + m_avgLabel = new QLabel("Avg Filter:", this); + m_avgLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_avgLabel->setStyleSheet(set->getLabelStyle()); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(m_PanLineBtn); + hbox1->addWidget(m_PanFilledLineBtn); + hbox1->addWidget(m_PanSolidBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addWidget(m_avgLabel); + hbox2->addStretch(); + hbox2->addWidget(m_avgSlider); + hbox2->addWidget(m_avgLevelLabel); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(6); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + m_panSpectrumOptions = new QGroupBox(tr("Panadapter Spectrum"), this); + m_panSpectrumOptions->setMinimumWidth(m_minimumGroupBoxWidth); + m_panSpectrumOptions->setLayout(vbox); + m_panSpectrumOptions->setStyleSheet(set->getWidgetStyle()); + m_panSpectrumOptions->setFont(QFont("Arial", 8)); +} + +void DisplayOptionsWidget::createWidebandPanOptions() { + + m_wbPanLineBtn = new AeroButton("Line", this); + m_wbPanLineBtn->setRoundness(0); + m_wbPanLineBtn->setFixedSize(btn_width, btn_height); + m_wbpanadapterBtnList.append(m_wbPanLineBtn); + + CHECKED_CONNECT( + m_wbPanLineBtn, + SIGNAL(clicked()), + this, + SLOT(wbPanModeChanged())); + + m_wbPanFilledLineBtn = new AeroButton("Filled Line", this); + m_wbPanFilledLineBtn->setRoundness(0); + m_wbPanFilledLineBtn->setFixedSize(btn_width, btn_height); + m_wbpanadapterBtnList.append(m_wbPanFilledLineBtn); + + CHECKED_CONNECT( + m_wbPanFilledLineBtn, + SIGNAL(clicked()), + this, + SLOT(wbPanModeChanged())); + + m_wbPanSolidBtn = new AeroButton("Solid", this); + m_wbPanSolidBtn->setRoundness(0); + m_wbPanSolidBtn->setFixedSize (btn_width, btn_height); + m_wbpanadapterBtnList.append(m_wbPanSolidBtn); + + CHECKED_CONNECT( + m_wbPanSolidBtn, + SIGNAL(clicked()), + this, + SLOT(wbPanModeChanged())); + + switch (m_widebandOptions.panMode) { + + case (PanGraphicsMode) Line: + + m_wbPanLineBtn->setBtnState(AeroButton::ON); + m_wbPanFilledLineBtn->setBtnState(AeroButton::OFF); + m_wbPanSolidBtn->setBtnState(AeroButton::OFF); + break; + + case (PanGraphicsMode) FilledLine: + + m_wbPanFilledLineBtn->setBtnState(AeroButton::ON); + m_wbPanLineBtn->setBtnState(AeroButton::OFF); + m_wbPanSolidBtn->setBtnState(AeroButton::OFF); + break; + + case (PanGraphicsMode) Solid: + + m_wbPanSolidBtn->setBtnState(AeroButton::ON); + m_wbPanLineBtn->setBtnState(AeroButton::OFF); + m_wbPanFilledLineBtn->setBtnState(AeroButton::OFF); + break; + } + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect(" 200 ").width(); + + m_wbAvgValue = m_widebandOptions.averagingCnt; + + m_wbAvgSlider = new QSlider(Qt::Horizontal, this); + m_wbAvgSlider->setTickPosition(QSlider::NoTicks); + m_wbAvgSlider->setFixedSize(130, 12); + m_wbAvgSlider->setSingleStep(1); + m_wbAvgSlider->setRange(1, 100); + m_wbAvgSlider->setValue(m_wbAvgValue); + m_wbAvgSlider->setStyleSheet(set->getVolSliderStyle()); + + CHECKED_CONNECT(m_wbAvgSlider, SIGNAL(valueChanged(int)), this, SLOT(setWidebandAveragingCnt(int))); + + QString str = "%1 "; + m_wbAvgLevelLabel = new QLabel(str.arg(m_wbAvgValue, 2, 10, QLatin1Char(' ')), this); + m_wbAvgLevelLabel->setFont(m_fonts.smallFont); + m_wbAvgLevelLabel->setFixedSize(fontMaxWidth, 12); + m_wbAvgLevelLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_wbAvgLevelLabel->setStyleSheet(set->getSliderLabelStyle()); + + m_wbAvgLabel = new QLabel("Avg Filter:", this); + m_wbAvgLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_wbAvgLabel->setStyleSheet(set->getLabelStyle()); + + QHBoxLayout* hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(m_wbPanLineBtn); + hbox1->addWidget(m_wbPanFilledLineBtn); + hbox1->addWidget(m_wbPanSolidBtn); + + QHBoxLayout* hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addWidget(m_wbAvgLabel); + hbox2->addStretch(); + hbox2->addWidget(m_wbAvgSlider); + hbox2->addWidget(m_wbAvgLevelLabel); + + QVBoxLayout* vbox = new QVBoxLayout; + vbox->setSpacing(6); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + m_widebandPanOptions = new QGroupBox(tr("Wideband Panadapter Spectrum"), this); + m_widebandPanOptions->setMinimumWidth(m_minimumGroupBoxWidth); + m_widebandPanOptions->setLayout(vbox); + m_widebandPanOptions->setStyleSheet(set->getWidgetStyle()); + m_widebandPanOptions->setFont(QFont("Arial", 8)); +} + +void DisplayOptionsWidget::createWaterfallSpectrumOptions() { + + m_waterfallSimpleBtn = new AeroButton("Simple", this); + m_waterfallSimpleBtn->setRoundness(0); + m_waterfallSimpleBtn->setFixedSize(btn_width, btn_height); + m_waterfallColorBtnList.append(m_waterfallSimpleBtn); + + CHECKED_CONNECT( + m_waterfallSimpleBtn, + SIGNAL(clicked()), + this, + SLOT(waterfallColorChanged())); + + m_waterfallEnhancedBtn = new AeroButton("Enhanced", this); + m_waterfallEnhancedBtn->setRoundness(0); + m_waterfallEnhancedBtn->setFixedSize(btn_width, btn_height); + m_waterfallColorBtnList.append(m_waterfallEnhancedBtn); + + CHECKED_CONNECT( + m_waterfallEnhancedBtn, + SIGNAL(clicked()), + this, + SLOT(waterfallColorChanged())); + + /*m_waterfallSpectranBtn = new AeroButton("Spectran", this); + m_waterfallSpectranBtn->setRoundness(0); + m_waterfallSpectranBtn->setFixedSize(btn_width, btn_height); + m_waterfallColorBtnList.append(m_waterfallSpectranBtn); + + CHECKED_CONNECT( + m_waterfallSpectranBtn, + SIGNAL(clicked()), + this, + SLOT(waterfallColorChanged()));*/ + + switch (m_waterColorMode) { + + case (WaterfallColorMode) Simple: + + m_waterfallSimpleBtn->setBtnState(AeroButton::ON); + m_waterfallEnhancedBtn->setBtnState(AeroButton::OFF); + //m_waterfallSpectranBtn->setBtnState(AeroButton::OFF); + break; + + case (WaterfallColorMode) Enhanced: + + m_waterfallEnhancedBtn->setBtnState(AeroButton::ON); + m_waterfallSimpleBtn->setBtnState(AeroButton::OFF); + //m_waterfallSpectranBtn->setBtnState(AeroButton::OFF); + break; + + //case QSDRGraphics::spectran: + // + // m_waterfallSpectranBtn->setBtnState(AeroButton::ON); + // m_waterfallSimpleBtn->setBtnState(AeroButton::OFF); + // m_waterfallEnhancedBtn->setBtnState(AeroButton::OFF); + // break; + } + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + hbox1->addStretch(); + //hbox1->addSpacing(77); + hbox1->addWidget(m_waterfallSimpleBtn); + hbox1->addWidget(m_waterfallEnhancedBtn); + //hbox1->addWidget(m_waterfallSpectranBtn); + + /*m_waterfallTimeSpinBox = new QSpinBox(this); + m_waterfallTimeSpinBox->setMinimum(5); + m_waterfallTimeSpinBox->setMaximum(250); + m_waterfallTimeSpinBox->setSingleStep(5); + m_waterfallTimeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_waterfallTimeSpinBox->setValue(m_rxDataList.at(m_currentReceiver).waterfallTime); + + CHECKED_CONNECT( + m_waterfallTimeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(waterfallTimeChanged(int)));*/ + + m_waterfallLoOffsetSpinBox = new QSpinBox(this); + m_waterfallLoOffsetSpinBox->setMinimum(-200); + m_waterfallLoOffsetSpinBox->setMaximum(200); + m_waterfallLoOffsetSpinBox->setSingleStep(1); + m_waterfallLoOffsetSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_waterfallLoOffsetSpinBox->setValue(m_rxDataList.at(m_currentReceiver).waterfallOffsetLo); + + CHECKED_CONNECT( + m_waterfallLoOffsetSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(waterfallLoOffsetChanged(int))); + + m_waterfallHiOffsetSpinBox = new QSpinBox(this); + m_waterfallHiOffsetSpinBox->setMinimum(-200); + m_waterfallHiOffsetSpinBox->setMaximum(200); + m_waterfallHiOffsetSpinBox->setSingleStep(1); + m_waterfallHiOffsetSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_waterfallHiOffsetSpinBox->setValue(m_rxDataList.at(m_currentReceiver).waterfallOffsetHi); + + CHECKED_CONNECT( + m_waterfallHiOffsetSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(waterfallHiOffsetChanged(int))); + + //m_waterfallTimeLabel = new QLabel("Timing (ms):", this); + //m_waterfallTimeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + //m_waterfallTimeLabel->setStyleSheet(set->getLabelStyle()); + + m_waterfallLoOffsetLabel = new QLabel("Offset Low (dBm):", this); + m_waterfallLoOffsetLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_waterfallLoOffsetLabel->setStyleSheet(set->getLabelStyle()); + + m_waterfallHiOffsetLabel = new QLabel("Offset High (dBm):", this); + m_waterfallHiOffsetLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_waterfallHiOffsetLabel->setStyleSheet(set->getLabelStyle()); + + /*QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(4); + hbox2->addWidget(m_waterfallTimeLabel); + hbox2->addStretch(); + hbox2->addWidget(m_waterfallTimeSpinBox);*/ + + QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(4); + hbox3->addWidget(m_waterfallLoOffsetLabel); + hbox3->addStretch(); + hbox3->addWidget(m_waterfallLoOffsetSpinBox); + + QHBoxLayout *hbox4 = new QHBoxLayout; + hbox4->setSpacing(4); + hbox4->addWidget(m_waterfallHiOffsetLabel); + hbox4->addStretch(); + hbox4->addWidget(m_waterfallHiOffsetSpinBox); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(6); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + //vbox->addLayout(hbox2); + vbox->addLayout(hbox3); + vbox->addLayout(hbox4); + + m_waterfallSpectrumOptions = new QGroupBox(tr("Waterfall Spectrum"), this); + m_waterfallSpectrumOptions->setMinimumWidth(m_minimumGroupBoxWidth); + m_waterfallSpectrumOptions->setLayout(vbox); + m_waterfallSpectrumOptions->setStyleSheet(set->getWidgetStyle()); + m_waterfallSpectrumOptions->setFont(QFont("Arial", 8)); +} + +void DisplayOptionsWidget::createSMeterOptions() { + + /*m_sMeterA = new AeroButton("S-Meter A", this); + m_sMeterA->setRoundness(0); + m_sMeterA->setFixedSize (btn_width, btn_height); + + CHECKED_CONNECT( + m_sMeterA, + SIGNAL(clicked()), + this, + SLOT(sMeterChanged())); + + m_sMeterB = new AeroButton("S-Meter B", this); + m_sMeterB->setRoundness(0); + m_sMeterB->setFixedSize (btn_width, btn_height); + + CHECKED_CONNECT( + m_sMeterA, + SIGNAL(clicked()), + this, + SLOT(sMeterChanged()));*/ + + m_sMeterHoldTimeSpinBox = new QSpinBox(this); + m_sMeterHoldTimeSpinBox->setMinimum(500); + m_sMeterHoldTimeSpinBox->setMaximum(10000); + m_sMeterHoldTimeSpinBox->setSingleStep(500); + m_sMeterHoldTimeSpinBox->setStyleSheet(set->getSpinBoxStyle()); + m_sMeterHoldTimeSpinBox->setValue(m_sMeterHoldTime); + + CHECKED_CONNECT( + m_sMeterHoldTimeSpinBox, + SIGNAL(valueChanged(int)), + this, + SLOT(sMeterHoldTimeChanged(int))); + + m_sMeterHoldTimeLabel = new QLabel("Hold Time (ms):", this); + m_sMeterHoldTimeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_sMeterHoldTimeLabel->setStyleSheet(set->getLabelStyle()); + + /*QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(m_sMeterA); + hbox1->addWidget(m_sMeterB);*/ + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(4); + //hbox2->addSpacing(77); + hbox2->addWidget(m_sMeterHoldTimeLabel); + hbox2->addStretch(); + hbox2->addWidget(m_sMeterHoldTimeSpinBox); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(6); + vbox->addSpacing(6); + //vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + //vbox->addLayout(hbox3); + //vbox->addLayout(hbox4); + + m_sMeterOptions = new QGroupBox(tr("S-Meter"), this); + m_sMeterOptions->setMinimumWidth(m_minimumGroupBoxWidth); + m_sMeterOptions->setLayout(vbox); + m_sMeterOptions->setStyleSheet(set->getWidgetStyle()); + m_sMeterOptions->setFont(QFont("Arial", 8)); +} + +void DisplayOptionsWidget::createCallSignEditor() { + + callSignLineEdit = new QLineEdit(this); + callSignLineEdit->setStyleSheet(set->getLineEditStyle()); + callSignLineEdit->setText(set->getCallsign()); + + CHECKED_CONNECT( + callSignLineEdit, + SIGNAL(textEdited(const QString &)), + this, + SLOT(callSignTextChanged(const QString &))); + + m_setCallSignBtn = new AeroButton("Set", this); + m_setCallSignBtn->setRoundness(0); + m_setCallSignBtn->setFixedSize(btn_width, btn_height); + + CHECKED_CONNECT( + m_setCallSignBtn, + SIGNAL(clicked()), + this, + SLOT(callSignChanged())); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(4); + //hbox1->addStretch(); + hbox1->addWidget(callSignLineEdit); + hbox1->addStretch(); + hbox1->addWidget(m_setCallSignBtn); + //hbox1->addWidget(m_sMeterB); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(6); + vbox->addLayout(hbox1); + //vbox->addLayout(hbox2); + + m_callSignEditor = new QGroupBox(tr("Call Sign Editor"), this); + m_callSignEditor->setMinimumWidth(m_minimumGroupBoxWidth); + m_callSignEditor->setLayout(vbox); + m_callSignEditor->setStyleSheet(set->getWidgetStyle()); + m_callSignEditor->setFont(QFont("Arial", 8)); +} + +void DisplayOptionsWidget::panModeChanged() { + + AeroButton *button = qobject_cast(sender()); + int btnHit = m_panadapterBtnList.indexOf(button); + + foreach(AeroButton *btn, m_panadapterBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (btnHit) { + + case 0: + m_panadapterMode = (PanGraphicsMode) Line; + DISPLAYOPTIONS_DEBUG << "set panadapter to line."; + break; + + case 1: + m_panadapterMode = (PanGraphicsMode) FilledLine; + DISPLAYOPTIONS_DEBUG << "set panadapter to filled line."; + break; + + case 2: + m_panadapterMode = (PanGraphicsMode) Solid; + DISPLAYOPTIONS_DEBUG << "set panadapter to solid."; + break; + } + + set->setGraphicsState(this, m_currentReceiver, m_panadapterMode, m_waterColorMode); +} + +void DisplayOptionsWidget::wbPanModeChanged() { + + AeroButton *button = qobject_cast(sender()); + int btnHit = m_wbpanadapterBtnList.indexOf(button); + + foreach(AeroButton *btn, m_wbpanadapterBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (btnHit) { + + case 0: + m_wbPanadapterMode = (PanGraphicsMode) Line; + DISPLAYOPTIONS_DEBUG << "set wideband panadapter to line."; + break; + + case 1: + m_wbPanadapterMode = (PanGraphicsMode) FilledLine; + DISPLAYOPTIONS_DEBUG << "set wideband panadapter to filled line."; + break; + + case 2: + m_wbPanadapterMode = (PanGraphicsMode) Solid; + DISPLAYOPTIONS_DEBUG << "set wideband panadapter to solid."; + break; + } + + set->setGraphicsState(this, -1, m_wbPanadapterMode, m_waterColorMode); +} + +void DisplayOptionsWidget::sMeterChanged() { +} + +void DisplayOptionsWidget::waterfallColorChanged() { + + AeroButton *button = qobject_cast(sender()); + int btnHit = m_waterfallColorBtnList.indexOf(button); + + foreach(AeroButton *btn, m_waterfallColorBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (btnHit) { + + case 0: + m_waterColorMode = (WaterfallColorMode) Simple; + DISPLAYOPTIONS_DEBUG << "set waterfall scheme to simple."; + break; + + case 1: + m_waterColorMode = (WaterfallColorMode) Enhanced; + DISPLAYOPTIONS_DEBUG << "set waterfall scheme to enhanced."; + break; + + //case 2: + // m_waterColorMode = QSDRGraphics::spectran; + // DISPLAYOPTIONS_DEBUG << "set waterfall scheme to spectran."; + // break; + } + + set->setGraphicsState(this, m_currentReceiver, m_panadapterMode, m_waterColorMode); +} + +void DisplayOptionsWidget::fpsValueChanged(int value) { + + m_framesPerSecond = value; + + QString str = "%1 "; + m_fpsLevelLabel->setText(str.arg(m_framesPerSecond, 2, 10, QLatin1Char(' '))); + set->setFramesPerSecond(this, m_currentReceiver, value); +} + +void DisplayOptionsWidget::setFramesPerSecond(QObject *sender, int rx, int value) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + + disconnect(m_fpsSlider, SIGNAL(valueChanged(int)), this, SLOT(fpsValueChanged(int))); + m_fpsSlider->setValue(value); + m_fpsSlider->update(); + connect(m_fpsSlider, SIGNAL(valueChanged(int)), this, SLOT(fpsValueChanged(int))); + + QString str = "%1 "; + m_fpsLevelLabel->setText(str.arg(value, 2, 10, QLatin1Char(' '))); +} + +void DisplayOptionsWidget::averagingFilterCntChanged(int value) { + + m_avgValue = value; + + QString str = "%1 "; + m_avgLevelLabel->setText(str.arg(m_avgValue, 2, 10, QLatin1Char(' '))); + + set->setSpectrumAveragingCnt(this, m_currentReceiver, value); +} + +void DisplayOptionsWidget::setWidebandAveragingCnt(int value) { + + m_wbAvgValue = value; + + QString str = "%1 "; + m_wbAvgLevelLabel->setText(str.arg(m_wbAvgValue, 2, 10, QLatin1Char(' '))); + + set->setSpectrumAveragingCnt(this, -1, value); +} + +void DisplayOptionsWidget::sampleRateChanged(QObject *sender, int value) { + + Q_UNUSED(sender) + + m_sampleRate = value; + //int currentValue = m_framesPerSecondSpinBox->value(); + + //m_framesPerSecondSpinBox->setMaximum(m_sampleRate/1000); + + //if (currentValue > m_sampleRate/1000) { + + // m_framesPerSecondSpinBox->setValue(m_sampleRate/1000); + // set->setFramesPerSecond(value); + //} +} + +void DisplayOptionsWidget::waterfallTimeChanged(int value) { + + set->setWaterfallTime(m_currentReceiver, value); +} + +void DisplayOptionsWidget::waterfallLoOffsetChanged(int value) { + + set->setWaterfallOffesetLo(m_currentReceiver, value); +} + +void DisplayOptionsWidget::waterfallHiOffsetChanged(int value) { + + set->setWaterfallOffesetHi(m_currentReceiver, value); +} + +void DisplayOptionsWidget::sMeterHoldTimeChanged(int value) { + + set->setSMeterHoldTime(value); +} + +void DisplayOptionsWidget::setCurrentReceiver(QObject *sender, int rx) { + + Q_UNUSED (sender) + + if (m_currentReceiver == rx) return; + m_currentReceiver = rx; + + setPanadapterMode(m_currentReceiver); + setWaterfallColorMode(m_currentReceiver); + + int sliderValue = set->getSpectrumAveragingCnt(m_currentReceiver); + m_avgSlider->blockSignals(true); + m_avgSlider->setValue(sliderValue); + + QString str = "%1 "; + m_avgLevelLabel->setText(str.arg(sliderValue, 2, 10, QLatin1Char(' '))); + m_avgSlider->blockSignals(false); +} + +void DisplayOptionsWidget::setPanadapterMode(int rx) { + + PanGraphicsMode panadapterMode = set->getPanadapterMode(rx); + + if (panadapterMode != m_panadapterMode) { + + foreach(AeroButton *btn, m_panadapterBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + m_panadapterBtnList.at(panadapterMode)->setBtnState(AeroButton::ON); + m_panadapterBtnList.at(panadapterMode)->update(); + + m_panadapterMode = panadapterMode; + } +} + +void DisplayOptionsWidget::setWaterfallColorMode(int rx) { + + WaterfallColorMode waterColorMode = set->getWaterfallColorMode(rx); + + if (waterColorMode != m_waterColorMode) { + + foreach(AeroButton *btn, m_waterfallColorBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + m_waterfallColorBtnList.at(waterColorMode)->setBtnState(AeroButton::ON); + m_waterfallColorBtnList.at(waterColorMode)->update(); + + m_waterColorMode = waterColorMode; + } +} + +void DisplayOptionsWidget::callSignTextChanged(const QString& text) { + + m_callSingText = text; +} + +void DisplayOptionsWidget::callSignChanged() { + + set->setCallsign(m_callSingText); +} diff --git a/Source/src/cusdr_displayWidget.h b/Source/src/cusdr_displayWidget.h new file mode 100644 index 0000000..978d09e --- /dev/null +++ b/Source/src/cusdr_displayWidget.h @@ -0,0 +1,196 @@ +/** +* @file cusdr_displayWidget.h +* @brief OpenGL display options widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-08-19 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_DISPLAY_OPTIONS_WIDGET_H +#define _CUSDR_DISPLAY_OPTIONS_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" + + +#ifdef LOG_DISPLAYOPTIONS_WIDGET +# define DISPLAYOPTIONS_DEBUG qDebug().nospace() << "DisplayWidget::\t" +#else +# define DISPLAYOPTIONS_DEBUG nullDebug() +#endif + + +class DisplayOptionsWidget : public QWidget { + + Q_OBJECT + +public: + DisplayOptionsWidget(QWidget* parent = 0); + ~DisplayOptionsWidget(); + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + PanGraphicsMode m_panadapterMode; + PanGraphicsMode m_wbPanadapterMode; + WaterfallColorMode m_waterColorMode; + + QList m_rxDataList; + TWideband m_widebandOptions; + + QString m_menu_style; + QString m_callSingText; + + CFonts* fonts; + TFonts m_fonts; + + QGroupBox* m_fpsGroupBox; + QGroupBox* m_panSpectrumOptions; + QGroupBox* m_widebandPanOptions; + QGroupBox* m_waterfallSpectrumOptions; + QGroupBox* m_wideBandSpectrumOptions; + QGroupBox* m_sMeterOptions; + QGroupBox* m_callSignEditor; + + QLineEdit* callSignLineEdit; + + QSlider* m_fpsSlider; + QSlider* m_avgSlider; + QSlider* m_wbAvgSlider; + + QSpinBox* m_waterfallLoOffsetSpinBox; + QSpinBox* m_waterfallHiOffsetSpinBox; + QSpinBox* m_sMeterHoldTimeSpinBox; + + QLabel* m_fpsLabel; + QLabel* m_fpsLevelLabel; + QLabel* m_avgLabel; + QLabel* m_wbAvgLabel; + QLabel* m_avgLevelLabel; + QLabel* m_wbAvgLevelLabel; + QLabel* m_resolutionLabel; + QLabel* m_waterfallTimeLabel; + QLabel* m_waterfallLoOffsetLabel; + QLabel* m_waterfallHiOffsetLabel; + QLabel* m_sMeterHoldTimeLabel; + + AeroButton* m_PanLineBtn; + AeroButton* m_PanFilledLineBtn; + AeroButton* m_PanSolidBtn; + AeroButton* m_wbPanLineBtn; + AeroButton* m_wbPanFilledLineBtn; + AeroButton* m_wbPanSolidBtn; + AeroButton* m_setCallSignBtn; + AeroButton* m_waterfallSimpleBtn; + AeroButton* m_waterfallEnhancedBtn; + AeroButton* m_waterfallSpectranBtn; + + QList m_panadapterBtnList; + QList m_wbpanadapterBtnList; + QList m_waterfallColorBtnList; + + int m_fontHeight; + int m_maxFontWidth; + + bool m_antialiased; + bool m_mouseOver; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_btnSpacing; + + int m_currentReceiver; + int m_btnChooserHit; + int m_panStyle; + int m_framesPerSecond; + int m_avgValue; + int m_wbAvgValue; + int m_sampleRate; + int m_waterfallTime; + int m_sMeterHoldTime; + + void setupConnections(); + void createFPSGroupBox(); + void createPanSpectrumOptions(); + void createWidebandPanOptions(); + void createWaterfallSpectrumOptions(); + void createSMeterOptions(); + void createCallSignEditor(); + + void setPanadapterMode(int rx); + void setWaterfallColorMode(int rx); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setCurrentReceiver(QObject *sender, int rx); + void setFramesPerSecond(QObject *sender, int rx, int value); + void panModeChanged(); + void wbPanModeChanged(); + void waterfallColorChanged(); + void sMeterChanged(); + void waterfallTimeChanged(int value); + void waterfallLoOffsetChanged(int value); + void waterfallHiOffsetChanged(int value); + void sMeterHoldTimeChanged(int value); + void fpsValueChanged(int value); + void averagingFilterCntChanged(int value); + void setWidebandAveragingCnt(int value); + void sampleRateChanged(QObject *sender, int value); + void callSignTextChanged(const QString &text); + void callSignChanged(); + +signals: + void averagingModeChanged(bool value); + //void showEvent(QObject *sender); + //void closeEvent(QObject *sender); +}; + +#endif // _CUSDR_DISPLAY_OPTIONS_WIDGET_H diff --git a/Source/src/cusdr_extCtrlWidget.cpp b/Source/src/cusdr_extCtrlWidget.cpp new file mode 100644 index 0000000..e75804e --- /dev/null +++ b/Source/src/cusdr_extCtrlWidget.cpp @@ -0,0 +1,474 @@ +/** +* @file cusdr_extCtrlWidget.cpp +* @brief J6-Pins settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-13 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_PENNY_WIDGET + + +//#include +//#include +//#include +//#include +#include +#include +#include + +#include "cusdr_extCtrlWidget.h" + +#define btn_height 15 +#define btn_width 20 +#define btn_width2 28 +#define btn_width3 32 + +ExtCtrlWidget::ExtCtrlWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_pennyOCEnabled(false) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(0) +{ + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 8, 4, 0); + setMouseTracking(true); + + createReceivePinsGroup(); + createTransmitPinsGroup(); + + enableBtn = new AeroButton("Enable", this); + enableBtn->setRoundness(0); + enableBtn->setFixedSize (65, btn_height); + enableBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + enableBtn, + SIGNAL(clicked()), + this, + SLOT(enable())); + + // disable all buttons + foreach(QList btnList, receivePinsBtnMatrix) { + + foreach(AeroButton *btn, btnList) { + + btn->setEnabled(false); + btn->update(); + } + } + + foreach(QList btnList, transmitPinsBtnMatrix) { + + foreach(AeroButton *btn, btnList) { + + btn->setEnabled(false); + btn->update(); + } + } + + + // set main layout + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 4, 0); + hbox1->addWidget(enableBtn); + hbox1->addStretch(); + + QHBoxLayout *hbox2 = new QHBoxLayout; + hbox2->setSpacing(0); + hbox2->setContentsMargins(4, 0, 4, 0); + hbox2->addWidget(receivePinsGroup); + + QHBoxLayout *hbox3 = new QHBoxLayout; + hbox3->setSpacing(0); + hbox3->setContentsMargins(4, 0, 4, 0); + hbox3->addWidget(transmitPinsGroup); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addStretch(); + + setLayout(mainLayout); + + setValues(); + setupConnections(); +} + +ExtCtrlWidget::~ExtCtrlWidget() { + + // disconnect all signals + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void ExtCtrlWidget::setupConnections() { +} + +void ExtCtrlWidget::createReceivePinsGroup() { + + QLabel* emptyLabel = new QLabel(" ", this); + emptyLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel->setStyleSheet(set->getLabelStyle()); + + // band label + QStringList bandNames; + bandNames << "2200m" << "630m" << "160 m" << "80 m" << "60 m" << "40 m" << "30 m" << "20 m" << "17 m" << "15 m" << "12 m" << "10 m" << "6 m"; + + QList bandLabelList; + + for (int i = 0; i < MAX_BANDS-1; i++) { + + QLabel *label = new QLabel(bandNames.at(i), this); + label->setFrameStyle(QFrame::Box | QFrame::Raised); + label->setStyleSheet(set->getLabelStyle()); + + bandLabelList << label; + } + + + // buttons + QString str = "%1"; + for (int i = 0; i < MAX_BANDS-1; i++) { // bands + + QList btnList; + for (int j = 0; j < 7; j++) { // pins + + AeroButton* btn = new AeroButton(str.arg(j+1), this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + //receivePinsBtnList.append(btn); + btnList.append(btn); + + CHECKED_CONNECT( + btn, + SIGNAL(clicked()), + this, + SLOT(receivePinsBtnClicked())); + } + receivePinsBtnMatrix.append(btnList); + } + + + QGridLayout* grid = new QGridLayout(this); + grid->setVerticalSpacing(2); + grid->setHorizontalSpacing(0); + grid->setContentsMargins(5, 10, 20, 10); + + grid->addWidget(emptyLabel, 0, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(emptyLabel, 0, 1, 1, 1, Qt::AlignCenter); + grid->addWidget(emptyLabel, 0, 2, 1, 7, Qt::AlignCenter); + + for (int i = 0; i < MAX_BANDS-1; i++) { // bands + + grid->addWidget(bandLabelList.at(i), i+1, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(emptyLabel, i+1, 1, 1, 1, Qt::AlignCenter); + + for (int j = 0; j < 7; j++) { // pins + + grid->addWidget(receivePinsBtnMatrix.at(i).at(j), i+1, j+2, 1, 1, Qt::AlignCenter); + } + } + + + receivePinsGroup = new QGroupBox(tr("Receive Pins"), this); + receivePinsGroup->setMinimumWidth(m_minimumGroupBoxWidth); + receivePinsGroup->setLayout(grid); + receivePinsGroup->setStyleSheet(set->getWidgetStyle()); + receivePinsGroup->setFont(QFont("Arial", 8)); +} + +void ExtCtrlWidget::createTransmitPinsGroup() { + + QLabel* emptyLabel = new QLabel(" ", this); + emptyLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + emptyLabel->setStyleSheet(set->getLabelStyle()); + + // band label + QStringList bandNames; + bandNames << "2200 m" << "630 m" << "160 m" << "80 m" << "60 m" << "40 m" << "30 m" << "20 m" << "17 m" << "15 m" << "12 m" << "10 m" << "6 m"; + + QList bandLabelList; + + for (int i = 0; i < MAX_BANDS-1; i++) { + + QLabel *label = new QLabel(bandNames.at(i), this); + label->setFrameStyle(QFrame::Box | QFrame::Raised); + label->setStyleSheet(set->getLabelStyle()); + + bandLabelList << label; + } + + + QString str = "%1"; + for (int i = 0; i < MAX_BANDS-1; i++) { // bands + + QList btnList; + for (int j = 0; j < 7; j++) { // pins + + AeroButton* btn = new AeroButton(str.arg(j+1), this); + btn->setRoundness(0); + btn->setFixedSize (btn_width, btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + btnList.append(btn); + + CHECKED_CONNECT( + btn, + SIGNAL(clicked()), + this, + SLOT(transmitPinsBtnClicked())); + } + transmitPinsBtnMatrix.append(btnList); + } + + QGridLayout* grid = new QGridLayout(this); + grid->setVerticalSpacing(2); + grid->setHorizontalSpacing(0); + grid->setContentsMargins(5, 10, 20, 10); + + grid->addWidget(emptyLabel, 0, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(emptyLabel, 0, 1, 1, 1, Qt::AlignCenter); + grid->addWidget(emptyLabel, 0, 2, 1, 7, Qt::AlignCenter); + + for (int i = 0; i < MAX_BANDS-1; i++) { // bands + + grid->addWidget(bandLabelList.at(i), i+1, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(emptyLabel, i+1, 1, 1, 1, Qt::AlignCenter); + + for (int j = 0; j < 7; j++) { // pins + + grid->addWidget(transmitPinsBtnMatrix.at(i).at(j), i+1, j+2, 1, 1, Qt::AlignCenter); + } + } + + transmitPinsGroup = new QGroupBox(tr("Transmit Pins"), this); + transmitPinsGroup->setMinimumWidth(m_minimumGroupBoxWidth); + transmitPinsGroup->setLayout(grid); + transmitPinsGroup->setStyleSheet(set->getWidgetStyle()); + transmitPinsGroup->setFont(QFont("Arial", 8)); +} + + +//************** +void ExtCtrlWidget::enable() { + + if (enableBtn->btnState() == AeroButton::OFF) { + + enableBtn->setBtnState(AeroButton::ON); + + foreach(QList btnList, receivePinsBtnMatrix) { + + foreach(AeroButton *btn, btnList) { + + btn->setEnabled(true); + btn->update(); + } + } + + foreach(QList btnList, transmitPinsBtnMatrix) { + + foreach(AeroButton *btn, btnList) { + + btn->setEnabled(true); + btn->update(); + } + } + + m_pennyOCEnabled = true; + } + else { + + enableBtn->setBtnState(AeroButton::OFF); + + foreach(QList btnList, receivePinsBtnMatrix) { + + foreach(AeroButton *btn, btnList) { + + btn->setEnabled(false); + btn->update(); + } + } + + foreach(QList btnList, transmitPinsBtnMatrix) { + + foreach(AeroButton *btn, btnList) { + + btn->setEnabled(false); + btn->update(); + } + } + m_pennyOCEnabled = false; + } + set->setPennyOCEnabled(this, m_pennyOCEnabled); +} + +void ExtCtrlWidget::receivePinsBtnClicked() { + + AeroButton *button = qobject_cast(sender()); + + int band = -1; + int pin = -1; + for (int i = 0; i < MAX_BANDS-1; i++) { // bands + + pin = receivePinsBtnMatrix.at(i).indexOf(button); + if (pin < 0) + continue; + else { + + band = i; + break; + } + } + + if (button->btnState() == AeroButton::ON) { + + button->setBtnState(AeroButton::OFF); + button->update(); + + if (pin >= 0) + m_rxPins[band] &= getMask(pin); + } + else { + + button->setBtnState(AeroButton::ON); + button->update(); + + if (pin >= 0) { + + m_rxPins[band] &= getMask(pin); + m_rxPins[band] |= (1 << (pin+1)); + } + } + + set->setRxJ6Pins(this, m_rxPins); +} + +void ExtCtrlWidget::transmitPinsBtnClicked() { + + AeroButton *button = qobject_cast(sender()); + + int band = -1; + int pin = -1; + for (int i = 0; i < MAX_BANDS-1; i++) { // bands + + pin = transmitPinsBtnMatrix.at(i).indexOf(button); + if (pin < 0) + continue; + else { + + band = i; + break; + } + } + + if (button->btnState() == AeroButton::ON) { + + button->setBtnState(AeroButton::OFF); + button->update(); + + if (pin >= 0) + m_txPins[band] &= getMask(pin); + } + else { + + button->setBtnState(AeroButton::ON); + button->update(); + + if (pin >= 0) { + + m_txPins[band] &= getMask(pin);//mask; + m_txPins[band] |= (1 << (pin+1)); + } + } + + set->setTxJ6Pins(this, m_txPins); +} + +void ExtCtrlWidget::setValues() { + + m_pennyOCEnabled = set->getPennyOCEnabled(); + + if (m_pennyOCEnabled) enable(); + + m_rxPins = set->getRxJ6Pins(); + m_txPins = set->getTxJ6Pins(); + + for (int i = 0; i < 11; i++) { // bands + + for (int j = 0; j < 7; j++) { // pins + + if (0x1 & (m_rxPins.at(i) >> (j+1))) + receivePinsBtnMatrix.at(i).at(j)->setBtnState(AeroButton::ON); + + if (0x1 & (m_txPins.at(i) >> (j+1))) + transmitPinsBtnMatrix.at(i).at(j)->setBtnState(AeroButton::ON); + } + } +} + +uchar ExtCtrlWidget::getMask(int value) { + + uchar mask = 0x0; + switch (value) { + + case 0: + mask = 0xFD; + break; + + case 1: + mask = 0xFB; + break; + + case 2: + mask = 0xF7; + break; + + case 3: + mask = 0xEF; + break; + + case 4: + mask = 0xDF; + break; + + case 5: + mask = 0xBF; + break; + + case 6: + mask = 0x7F; + break; + + default: + mask = 0x0; + break; + } + return mask; +} + diff --git a/Source/src/cusdr_extCtrlWidget.h b/Source/src/cusdr_extCtrlWidget.h new file mode 100644 index 0000000..56c2a01 --- /dev/null +++ b/Source/src/cusdr_extCtrlWidget.h @@ -0,0 +1,93 @@ +/** +* @file cusdr_extCtrlWidget.h +* @brief J6-Pins settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-13 +*/ + +/* + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_PENNY_WIDGET_H +#define _CUSDR_PENNY_WIDGET_H + +//#include +//#include +#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + + +class ExtCtrlWidget : public QWidget { + + Q_OBJECT + +public: + ExtCtrlWidget(QWidget *parent = 0); + ~ExtCtrlWidget(); + +public slots: + +private: + void setupConnections(); + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QGroupBox* receivePinsGroup; + QGroupBox* transmitPinsGroup; + + AeroButton* enableBtn; + + QList > receivePinsBtnMatrix; + QList > transmitPinsBtnMatrix; + + QList m_rxPins; + QList m_txPins; + + bool m_pennyOCEnabled; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void createReceivePinsGroup(); + void createTransmitPinsGroup(); + void setValues(); + uchar getMask(int value); + +private slots: + void enable(); + + void receivePinsBtnClicked(); + void transmitPinsBtnClicked(); + +signals: + void showEvent(QObject* sender); + void closeEvent(QObject* sender); + void messageEvent(QString); +}; + +#endif // _CUSDR_PENNY_WIDGET_H diff --git a/Source/src/cusdr_fonts.cpp b/Source/src/cusdr_fonts.cpp new file mode 100644 index 0000000..e0969e6 --- /dev/null +++ b/Source/src/cusdr_fonts.cpp @@ -0,0 +1,224 @@ +/** +* @file cusdr_fonts.cpp +* @brief Fonts class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-11-01 +*/ + +/* + * Copyright (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cusdr_fonts.h" + + +CFonts::CFonts(QObject *parent) + : QObject(parent) +{ + m_fonts.tinyFont.setStyleStrategy(QFont::PreferAntialias); + m_fonts.tinyFont.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.tinyFont.setPixelSize(8); + m_fonts.tinyFont.setFamily("Arial"); + //#endif + #elif defined(Q_OS_WIN32) + m_fonts.tinyFont.setPixelSize(8); + m_fonts.tinyFont.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.tinyFont.setPixelSize(7); + m_fonts.tinyFont.setFamily("Arial"); + #endif + + m_fonts.tinyFontMetrics = new QFontMetrics(m_fonts.tinyFont); + m_fonts.fontHeightTinyFont = m_fonts.tinyFontMetrics->tightBoundingRect("M").height(); + + m_fonts.smallFont.setStyleStrategy(QFont::PreferAntialias); + m_fonts.smallFont.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + //m_fonts.smallFont.setBold(true); + m_fonts.smallFont.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.smallFont.setPixelSize(9); + m_fonts.smallFont.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.smallFont.setPixelSize(10); + m_fonts.smallFont.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.smallFont.setPixelSize(10); + m_fonts.smallFont.setFamily("Arial"); + #endif + + m_fonts.smallFontMetrics = new QFontMetrics(m_fonts.smallFont); + m_fonts.fontHeightSmallFont = m_fonts.smallFontMetrics->tightBoundingRect("M").height(); + + + //m_fonts.normalFont.setStyleStrategy(QFont::PreferAntialias); + //m_fonts.normalFont.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.normalFont.setStyleStrategy(QFont::OpenGLCompatible); + m_fonts.normalFont.setBold(true); + m_fonts.normalFont.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.normalFont.setPixelSize(10); + m_fonts.normalFont.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.normalFont.setPixelSize(10); + m_fonts.normalFont.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.normalFont.setPixelSize(10); + m_fonts.normalFont.setFamily("Arial"); + #endif + + m_fonts.normalFontMetrics = new QFontMetrics(m_fonts.normalFont); + m_fonts.fontHeightNormalFont = m_fonts.normalFontMetrics->tightBoundingRect("M").height(); + + + m_fonts.bigFont.setStyleStrategy(QFont::PreferAntialias); + m_fonts.bigFont.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.bigFont.setBold(true); + m_fonts.bigFont.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.bigFont.setPixelSize(18); + m_fonts.bigFont.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.bigFont.setPixelSize(18); + m_fonts.bigFont.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.bigFont.setPixelSize(18); + m_fonts.bigFont.setFamily("Arial"); + #endif + + m_fonts.bigFontMetrics = new QFontMetrics(m_fonts.bigFont); + m_fonts.fontHeightBigFont = m_fonts.bigFontMetrics->tightBoundingRect("M").height(); + + + m_fonts.bigFont1.setStyleStrategy(QFont::PreferAntialias); + m_fonts.bigFont1.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.bigFont1.setBold(true); + m_fonts.bigFont1.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.bigFont1.setPixelSize(12); + m_fonts.bigFont1.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.bigFont1.setPixelSize(12); + m_fonts.bigFont1.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.bigFont1.setPixelSize(12); + m_fonts.bigFont1.setFamily("Arial"); + #endif + + m_fonts.bigFont1Metrics = new QFontMetrics(m_fonts.bigFont1); + m_fonts.fontHeightBigFont1 = m_fonts.bigFont1Metrics->tightBoundingRect("M").height(); + + + m_fonts.bigFont2.setStyleStrategy(QFont::PreferAntialias); + m_fonts.bigFont2.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.bigFont2.setBold(true); + m_fonts.bigFont2.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.bigFont2.setPixelSize(10); + m_fonts.bigFont2.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.bigFont2.setPixelSize(10); + m_fonts.bigFont2.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.bigFont2.setPixelSize(10); + m_fonts.bigFont2.setFamily("Arial"); + #endif + + m_fonts.bigFont2Metrics = new QFontMetrics(m_fonts.bigFont2); + m_fonts.fontHeightBigFont2 = m_fonts.bigFont2Metrics->tightBoundingRect("M").height(); + + + m_fonts.freqFont1.setStyleStrategy(QFont::PreferAntialias); + m_fonts.freqFont1.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.freqFont1.setBold(true); + m_fonts.freqFont1.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.freqFont1.setPixelSize(36); + m_fonts.freqFont1.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.freqFont1.setPixelSize(36); + m_fonts.freqFont1.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.freqFont1.setPixelSize(36); + m_fonts.freqFont1.setFamily("Arial"); + #endif + + m_fonts.freqFont1Metrics = new QFontMetrics(m_fonts.freqFont1); + m_fonts.fontHeightFreqFont1 = m_fonts.freqFont1Metrics->tightBoundingRect("M").height(); + + + m_fonts.freqFont2.setStyleStrategy(QFont::PreferAntialias); + m_fonts.freqFont2.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.freqFont2.setBold(true); + m_fonts.freqFont2.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.freqFont2.setPixelSize(24); + m_fonts.freqFont2.setFamily("Arial"); + #elif defined(Q_OS_WIN32) + m_fonts.freqFont2.setPixelSize(24); + m_fonts.freqFont2.setFamily("Arial"); + #elif defined(Q_OS_LINUX) + m_fonts.freqFont2.setPixelSize(24); + m_fonts.freqFont2.setFamily("Arial"); + #endif + + m_fonts.freqFont2Metrics = new QFontMetrics(m_fonts.freqFont2); + m_fonts.fontHeightFreqFont2 = m_fonts.freqFont2Metrics->tightBoundingRect("M").height(); + + + m_fonts.impactFont.setStyleStrategy(QFont::PreferAntialias); + m_fonts.impactFont.setItalic(true); + m_fonts.impactFont.setFixedPitch(true); + #if defined(Q_OS_MAC) + m_fonts.impactFont.setPixelSize(12); + m_fonts.impactFont.setFamily("Impact"); + #elif defined(Q_OS_WIN32) + m_fonts.impactFont.setPixelSize(12); + m_fonts.impactFont.setFamily("Impact"); + #elif defined(Q_OS_LINUX) + m_fonts.impactFont.setPixelSize(18); + m_fonts.impactFont.setFamily("Impact"); + #endif + + m_fonts.impactFontMetrics = new QFontMetrics(m_fonts.impactFont); + m_fonts.fontHeightImpactFont = m_fonts.impactFontMetrics->tightBoundingRect("M").height(); + + + m_fonts.hugeFont.setStyleStrategy(QFont::PreferAntialias); + //m_fonts.hugeFont.setStyleHint(QFont::SansSerif, QFont::PreferAntialias); + m_fonts.hugeFont.setBold(true); + m_fonts.hugeFont.setFixedPitch(true); + #ifdef Q_OS_MAC + m_fonts.hugeFont.setPixelSize(72); + m_fonts.hugeFont.setFamily("Impact"); + #elif defined(Q_OS_WIN32) + m_fonts.hugeFont.setPixelSize(72); + m_fonts.hugeFont.setFamily("Impact"); + #elif defined(Q_OS_LINUX) + m_fonts.hugeFont.setPixelSize(72); + m_fonts.hugeFont.setFamily("Impact"); + #endif + + m_fonts.hugeFontMetrics = new QFontMetrics(m_fonts.hugeFont); + m_fonts.fontHeightHugeFont = m_fonts.hugeFontMetrics->tightBoundingRect("M").height(); +} + +CFonts::~CFonts() { + +} + diff --git a/Source/src/cusdr_fonts.h b/Source/src/cusdr_fonts.h new file mode 100644 index 0000000..704c733 --- /dev/null +++ b/Source/src/cusdr_fonts.h @@ -0,0 +1,89 @@ +/** +* @file cusdr_fonts.h +* @brief Fonts header for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-11-01 +*/ + +/* + * Copyright (C) 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_FONTS_H +#define _CUSDR_FONTS_H + +#include +#include +#include + + +typedef struct _fonts { + + QFont tinyFont; + QFont smallFont; + QFont normalFont; + QFont bigFont; + QFont bigFont1; + QFont bigFont2; + QFont freqFont1; + QFont freqFont2; + QFont impactFont; + QFont hugeFont; + + QFontMetrics *tinyFontMetrics; + QFontMetrics *smallFontMetrics; + QFontMetrics *normalFontMetrics; + QFontMetrics *bigFontMetrics; + QFontMetrics *bigFont1Metrics; + QFontMetrics *bigFont2Metrics; + QFontMetrics *freqFont1Metrics; + QFontMetrics *freqFont2Metrics; + QFontMetrics *impactFontMetrics; + QFontMetrics *hugeFontMetrics; + + int fontHeightTinyFont; + int fontHeightSmallFont; + int fontHeightNormalFont; + int fontHeightBigFont; + int fontHeightBigFont1; + int fontHeightBigFont2; + int fontHeightFreqFont1; + int fontHeightFreqFont2; + int fontHeightImpactFont; + int fontHeightHugeFont; + +} TFonts; + +class CFonts : public QObject { + + Q_OBJECT + +public: + CFonts(QObject *parent = 0); + ~CFonts(); + + TFonts getFonts() { return m_fonts; } + +public slots: + +private: + TFonts m_fonts; + +}; + +#endif // _CUSDR_FONTS_H diff --git a/Source/src/cusdr_hamDatabase.cpp b/Source/src/cusdr_hamDatabase.cpp new file mode 100644 index 0000000..d1c23ff --- /dev/null +++ b/Source/src/cusdr_hamDatabase.cpp @@ -0,0 +1,25 @@ +/** +* @file cusdr_hamDatabase.cpp +* @brief Ham database class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-01-27 +*/ + +/* + * Copyright 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ \ No newline at end of file diff --git a/Source/src/cusdr_hamDatabase.h b/Source/src/cusdr_hamDatabase.h new file mode 100644 index 0000000..48a7486 --- /dev/null +++ b/Source/src/cusdr_hamDatabase.h @@ -0,0 +1,1404 @@ +/** +* @file cusdr_hamDatabase.h +* @brief Ham database header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-01-27 +*/ + +/* + * Copyright 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_HAMDATABASE_H +#define CUSDR_HAMDATABASE_H + +#include + + + +typedef enum _iaruRegion { + + region1, // 0 + region2, // 1 + region3, // 2 + +} IARURegion; + +Q_DECLARE_METATYPE (_iaruRegion) + +typedef enum _hamBand { + + m2200, // 0 + m630, // 1 + m160, // 2 + m80, // 3 + m60, // 4 + m40, // 5 + m30, // 6 + m20, // 7 + m17, // 8 + m15, // 9 + m12, // 10 + m10, // 11 + m6, // 12 + gen // 13 + +} HamBand; + +typedef enum _dspMode { + + LSB, // 0 + USB, // 1 + DSB, // 2 + CWL, // 3 + CWU, // 4 + FMN, // 5 + AM, // 6 + DIGU, // 7 + SPEC, // 8 + DIGL, // 9 + SAM, // 10 + DRM // 11 + +} DSPMode; + +typedef enum _agcMode { + + agcOFF, + agcLONG, + agcSLOW, + agcMED, + agcFAST, + agcUser + +} AGCMode; + +typedef enum _defaultFilterMode { + + filterLSB, + filterUSB, + filterDSB, + filterCWL, + filterCWU, + filterFMN, + filterAM, + filterDIGU, + filterSPEC, + filterDIGL, + filterSAM, + filterDRM + +} TDefaultFilterMode; + +Q_DECLARE_METATYPE (HamBand) +Q_DECLARE_METATYPE (DSPMode) +Q_DECLARE_METATYPE (AGCMode) +Q_DECLARE_METATYPE (TDefaultFilterMode) + +typedef struct _filter { + + DSPMode dspMode; + //QRadio::_DSPMode dspMode; + TDefaultFilterMode defaultFilterMode; + qreal filterLo; + qreal filterHi; + +} TDefaultFilter; + +typedef struct _hamBandFrequencies { + + HamBand hamBand; + IARURegion region; + + QString bandString; + long frequencyLo; + long frequencyHi; + +} THamBandFrequencies; + +typedef struct _hamBandText { + + HamBand hamBand; + IARURegion region; + + long frequencyLo; + long frequencyHi; + int maxBandwith; + + QString text; + QString shortText; + QStringList freqTextList; + +} THamBandText; + +typedef struct _hamBandDefaults { + + HamBand hamBand; + DSPMode dspMode; + + long frequencyLo; + +} THamBandDefaults; + +//*********************************************************************** + +inline QList getHamBandFrequencies() { + + QList hamBandFreqList; + + THamBandFrequencies hamBandFreq; + + hamBandFreq.frequencyLo = 135700; + hamBandFreq.frequencyHi = 137800; + hamBandFreq.hamBand = (HamBand) m2200; + hamBandFreq.bandString = "2200m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 472000; + hamBandFreq.frequencyHi = 479000; + hamBandFreq.hamBand = (HamBand) m630; + hamBandFreq.bandString = "630m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 1810000; + hamBandFreq.frequencyHi = 2000000; + hamBandFreq.hamBand = (HamBand) m160; + hamBandFreq.bandString = "160m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 3500000; + hamBandFreq.frequencyHi = 3800000; + hamBandFreq.hamBand = (HamBand) m80; + hamBandFreq.bandString = "80m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 5260000; + hamBandFreq.frequencyHi = 5410000; + hamBandFreq.hamBand = (HamBand) m60; + hamBandFreq.bandString = "60m"; + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 7000000; + hamBandFreq.frequencyHi = 7200000; + hamBandFreq.hamBand = (HamBand) m40; + hamBandFreq.bandString = "40m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 10100000; + hamBandFreq.frequencyHi = 10150000; + hamBandFreq.hamBand = (HamBand) m30; + hamBandFreq.bandString = "30m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 14000000; + hamBandFreq.frequencyHi = 14350000; + hamBandFreq.hamBand = (HamBand) m20; + hamBandFreq.bandString = "20m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 18068000; + hamBandFreq.frequencyHi = 18168000; + hamBandFreq.hamBand = (HamBand) m17; + hamBandFreq.bandString = "17m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 21000000; + hamBandFreq.frequencyHi = 21450000; + hamBandFreq.hamBand = (HamBand) m15; + hamBandFreq.bandString = "15m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 24890000; + hamBandFreq.frequencyHi = 24990000; + hamBandFreq.hamBand = (HamBand) m12; + hamBandFreq.bandString = "12m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 28000000; + hamBandFreq.frequencyHi = 29700000; + hamBandFreq.hamBand = (HamBand) m10; + hamBandFreq.bandString = "10m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 50000000; + hamBandFreq.frequencyHi = 54000000; + hamBandFreq.hamBand = (HamBand) m6; + hamBandFreq.bandString = "6m"; + hamBandFreq.region = (IARURegion) region1; + + hamBandFreqList << hamBandFreq; + + hamBandFreq.frequencyLo = 0; + hamBandFreq.frequencyHi = 61440000; + hamBandFreq.hamBand = (HamBand) gen; + hamBandFreq.bandString = "Gen"; + + hamBandFreqList << hamBandFreq; + + return hamBandFreqList; +} + +inline QList getHamBandText() { + + QList hamBandTextList; + + THamBandText hamBandText; + + hamBandText.frequencyLo = 135700; + hamBandText.frequencyHi = 135800; + hamBandText.hamBand = (HamBand) m2200; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW only, International DX window"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 135800; + hamBandText.frequencyHi = 136000; + hamBandText.hamBand = (HamBand) m2200; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW only, Test transmissions and beacons"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 136000; + hamBandText.frequencyHi = 137400; + hamBandText.hamBand = (HamBand) m2200; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW only"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 137400; + hamBandText.frequencyHi = 137600; + hamBandText.hamBand = (HamBand) m2200; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "Narrow band digital modes"; + hamBandText.shortText = "Digital Modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 137600; + hamBandText.frequencyHi = 137800; + hamBandText.hamBand = (HamBand) m2200; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "Slow CW, QRSS etc."; + hamBandText.shortText = "Slow CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 472000; + hamBandText.frequencyHi = 479000; + hamBandText.hamBand = (HamBand) m630; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2100; + hamBandText.text = "CW, Digi and SSB narrow band modes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + hamBandText.frequencyLo = 1810000; + hamBandText.frequencyHi = 1838000; + hamBandText.hamBand = (HamBand) m160; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "1836 kHz: QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 1838000; + hamBandText.frequencyHi = 1840000; + hamBandText.hamBand = (HamBand) m160; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 1840000; + hamBandText.frequencyHi = 1843000; + hamBandText.hamBand = (HamBand) m160; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, digimodes, Lowest dial setting for LSB Voice mode: 1843, 3603 and 7053 kHz"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 1843000; + hamBandText.frequencyHi = 2000000; + hamBandText.hamBand = (HamBand) m160; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, Lowest dial setting for LSB Voice mode: 1843, 3603 and 7053 kHz"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3500000; + hamBandText.frequencyHi = 3510000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW, priority for intercontinental operation"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3510000; + hamBandText.frequencyHi = 3560000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW, contest preferred"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "3555 kHz: QRS Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3560000; + hamBandText.frequencyHi = 3580000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "3560 kHz: QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3580000; + hamBandText.frequencyHi = 3590000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3590000; + hamBandText.frequencyHi = 3600000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3600000; + hamBandText.frequencyHi = 3620000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "All modes, digimodes, automatically controlled data station (unattended)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3620000; + hamBandText.frequencyHi = 3650000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "3630 kHz: Digital Voice Centre of Activity, SSB contest preferred"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3650000; + hamBandText.frequencyHi = 3700000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "3690 kHz: SSB QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3700000; + hamBandText.frequencyHi = 3775000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, SSB contest preferred"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "3735 kHz: Image Centre of Activity"; + hamBandText.freqTextList << "3760 kHz: Region 1 Emergency Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 3775000; + hamBandText.frequencyHi = 3800000; + hamBandText.hamBand = (HamBand) m80; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, priority for intercontinental operation"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7000000; + hamBandText.frequencyHi = 7040000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "7030 kHz: QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7040000; + hamBandText.frequencyHi = 7047000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7047000; + hamBandText.frequencyHi = 7050000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7050000; + hamBandText.frequencyHi = 7053000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7053000; + hamBandText.frequencyHi = 7060000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, digimodes"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7060000; + hamBandText.frequencyHi = 7100000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, SSB contest preferred"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "7070 kHz: Digital Voice Centre of Activity"; + hamBandText.freqTextList << "7090 kHz: SSB QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7100000; + hamBandText.frequencyHi = 7130000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "7110 kHz: Region 1 Emergency Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7130000; + hamBandText.frequencyHi = 7175000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, SSB contest preferred"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "7165 kHz: Image Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 7175000; + hamBandText.frequencyHi = 7200000; + hamBandText.hamBand = (HamBand) m40; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, priority for intercontinental operation"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 10100000; + hamBandText.frequencyHi = 10140000; + hamBandText.hamBand = (HamBand) m30; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "10116 kHz: QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 10140000; + hamBandText.frequencyHi = 10150000; + hamBandText.hamBand = (HamBand) m30; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14000000; + hamBandText.frequencyHi = 14060000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW, contest preferred;"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "14055 kHz: QRS Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14060000; + hamBandText.frequencyHi = 14070000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW, 14060 kHz, QRP Centre of Activity"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14070000; + hamBandText.frequencyHi = 14089000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14089000; + hamBandText.frequencyHi = 14099000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14099000; + hamBandText.frequencyHi = 14101000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, exclusively for beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14101000; + hamBandText.frequencyHi = 14112000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14112000; + hamBandText.frequencyHi = 14125000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14125000; + hamBandText.frequencyHi = 14300000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, SSB contest preferred"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "14130 kHz: Digital Voice Centre of Activity"; + hamBandText.freqTextList << "14195 kHz ± 5 kHz: Priority for Dxpeditions"; + hamBandText.freqTextList << "14230 kHz: Image Centre of Activity"; + hamBandText.freqTextList << "14285 kHz: SSB QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 14300000; + hamBandText.frequencyHi = 14350000; + hamBandText.hamBand = (HamBand) m20; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "14300 kHz: Global Emergency centre of activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 18068000; + hamBandText.frequencyHi = 18095000; + hamBandText.hamBand = (HamBand) m17; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "18086 kHz: QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 18095000; + hamBandText.frequencyHi = 18105000; + hamBandText.hamBand = (HamBand) m17; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 18105000; + hamBandText.frequencyHi = 18109000; + hamBandText.hamBand = (HamBand) m17; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 18109000; + hamBandText.frequencyHi = 18111000; + hamBandText.hamBand = (HamBand) m17; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, exclusively for beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 18111000; + hamBandText.frequencyHi = 18120000; + hamBandText.hamBand = (HamBand) m17; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "IBP, exclusively for beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 18120000; + hamBandText.frequencyHi = 18168000; + hamBandText.hamBand = (HamBand) m17; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "18130 kHz: SSB QRP Centre of Activity"; + hamBandText.freqTextList << "18150 kHz: Digital Voice Centre of Activity"; + hamBandText.freqTextList << "18160 kHz: Global Emergency Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21000000; + hamBandText.frequencyHi = 21070000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW"; + hamBandText.shortText = "CW"; + hamBandText.freqTextList << "21055 kHz: QRS Centre of Activity"; + hamBandText.freqTextList << "21060 kHz: QRP Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21070000; + hamBandText.frequencyHi = 21090000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21090000; + hamBandText.frequencyHi = 21110000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21110000; + hamBandText.frequencyHi = 21120000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes (excluding SSB), digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "All modes (excluding SSB)"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21120000; + hamBandText.frequencyHi = 21149000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21149000; + hamBandText.frequencyHi = 21151000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, exclusively for beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 21151000; + hamBandText.frequencyHi = 21450000; + hamBandText.hamBand = (HamBand) m15; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "21180 kHz: Digital Voice Centre of Activity"; + hamBandText.freqTextList << "21285 kHz: SSB QRP Centre of Activity"; + hamBandText.freqTextList << "21340 kHz: Image Centre of Activity"; + hamBandText.freqTextList << "21360 kHz: Global Emergency Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 24890000; + hamBandText.frequencyHi = 24915000; + hamBandText.hamBand = (HamBand) m12; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW, 24906 kHz, QRP centre of activity"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 24915000; + hamBandText.frequencyHi = 24925000; + hamBandText.hamBand = (HamBand) m12; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 24925000; + hamBandText.frequencyHi = 24929000; + hamBandText.hamBand = (HamBand) m12; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 24929000; + hamBandText.frequencyHi = 24931000; + hamBandText.hamBand = (HamBand) m12; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, exclusively for beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 24931000; + hamBandText.frequencyHi = 24940000; + hamBandText.hamBand = (HamBand) m12; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 24940000; + hamBandText.frequencyHi = 24990000; + hamBandText.hamBand = (HamBand) m12; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, 24960 kHz: Digital Voice Centre of Activity"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28000000; + hamBandText.frequencyHi = 28070000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 200; + hamBandText.text = "CW, 28055 kHz: QRS Centre of Activity"; + hamBandText.shortText = "CW"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28070000; + hamBandText.frequencyHi = 28120000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28120000; + hamBandText.frequencyHi = 28150000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28150000; + hamBandText.frequencyHi = 28190000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 500; + hamBandText.text = "Narrow band modes"; + hamBandText.shortText = "Narrow band modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28190000; + hamBandText.frequencyHi = 28199000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, regional time shared beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28199000; + hamBandText.frequencyHi = 28201000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, worldwide time shared beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28201000; + hamBandText.frequencyHi = 28225000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "IBP, continuous duty beacons"; + hamBandText.shortText = "IBP"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28225000; + hamBandText.frequencyHi = 28300000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, beacons"; + hamBandText.shortText = "All modes, beacons"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28300000; + hamBandText.frequencyHi = 28320000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 28320000; + hamBandText.frequencyHi = 29100000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 2700; + hamBandText.text = "All modes"; + hamBandText.shortText = "All modes"; + hamBandText.freqTextList << "28330 kHz: Digital Voice Centre of Activity"; + hamBandText.freqTextList << "28360 kHz: SSB QRP Centre of Activity"; + hamBandText.freqTextList << "28680 kHz: Image Centre of Activity"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29100000; + hamBandText.frequencyHi = 29200000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "All modes, FM simplex: 10 kHz channels"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29200000; + hamBandText.frequencyHi = 29300000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "All modes, digimodes, automatically controlled data stations (unattended)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29300000; + hamBandText.frequencyHi = 29510000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "Satellite-downlink"; + hamBandText.shortText = "Satellite-downlink"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29510000; + hamBandText.frequencyHi = 29520000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 0; + hamBandText.text = "Guard channel"; + hamBandText.shortText = "Guard channel"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29520000; + hamBandText.frequencyHi = 29590000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "All modes, FM repeater input (RH1 to RH8)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29590000; + hamBandText.frequencyHi = 29600000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "All modes, FM calling channel"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29600000; + hamBandText.frequencyHi = 29610000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "All modes, FM simplex repeater (parrot, input and output)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + hamBandText.frequencyLo = 29610000; + hamBandText.frequencyHi = 29700000; + hamBandText.hamBand = (HamBand) m10; + hamBandText.region = (IARURegion) region1; + hamBandText.maxBandwith = 6000; + hamBandText.text = "All modes, FM repeater outputs (RH1 to RH8)"; + hamBandText.shortText = "All modes"; + + hamBandTextList << hamBandText; + + return hamBandTextList; +} + +inline QList getDefaultFilterFrequencies() { + + QList defaultFilters; + + TDefaultFilter defaultFilter; + + defaultFilter.dspMode = (DSPMode) LSB; + defaultFilter.defaultFilterMode = filterLSB; + defaultFilter.filterLo = -3050.0f; + defaultFilter.filterHi = -150.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) USB; + defaultFilter.defaultFilterMode = filterUSB; + defaultFilter.filterLo = 150.0f; + defaultFilter.filterHi = 3050.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) DSB; + defaultFilter.defaultFilterMode = filterDSB; + defaultFilter.filterLo = -3300.0f; + defaultFilter.filterHi = 3300.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) CWL; + defaultFilter.defaultFilterMode = filterCWL; + defaultFilter.filterLo = -1100.0f; + defaultFilter.filterHi = -100.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) CWU; + defaultFilter.defaultFilterMode = filterCWU; + defaultFilter.filterLo = 100.0f; + defaultFilter.filterHi = 1100.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) FMN; + defaultFilter.defaultFilterMode = filterFMN; + defaultFilter.filterLo = -2000.0f; + defaultFilter.filterHi = 2000.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) AM; + defaultFilter.defaultFilterMode = filterAM; + defaultFilter.filterLo = -4000.0f; + defaultFilter.filterHi = 4000.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) DIGU; + defaultFilter.defaultFilterMode = filterDIGU; + defaultFilter.filterLo = 150.0f; + defaultFilter.filterHi = 3050.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) SPEC; + defaultFilter.defaultFilterMode = filterSPEC; + defaultFilter.filterLo = -6000.0f; + defaultFilter.filterHi = 6000.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) DIGL; + defaultFilter.defaultFilterMode = filterDIGL; + defaultFilter.filterLo = -3050.0f; + defaultFilter.filterHi = -150.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) SAM; + defaultFilter.defaultFilterMode = filterSAM; + defaultFilter.filterLo = -3300.0f; + defaultFilter.filterHi = 3300.0f; + + defaultFilters << defaultFilter; + + defaultFilter.dspMode = (DSPMode) DRM; + defaultFilter.defaultFilterMode = filterDRM; + defaultFilter.filterLo = -6000.0f; + defaultFilter.filterHi = 6000.0f; + + defaultFilters << defaultFilter; + + return defaultFilters; +} + +inline QList > getHamBandDefaults() { + + QList > hamBandDefaults; + + QList hamBandDefault; + + THamBandDefaults defaults; + + defaults.hamBand = (HamBand) m160; + defaults.dspMode = (DSPMode) CWL; + defaults.frequencyLo = 1810000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m160; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 1835000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m160; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 1845000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m80; + defaults.dspMode = (DSPMode) CWL; + defaults.frequencyLo = 3501000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m80; + defaults.dspMode = (DSPMode) LSB; + defaults.frequencyLo = 3751000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m80; + defaults.dspMode = (DSPMode) LSB; + defaults.frequencyLo = 3850000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m60; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 5258500; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m40; + defaults.dspMode = (DSPMode) CWL; + defaults.frequencyLo = 7001000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m40; + defaults.dspMode = (DSPMode) LSB; + defaults.frequencyLo = 7152000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m30; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 10120000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m20; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 14010000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m20; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 14230000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m17; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 18090000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m17; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 18125000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m15; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 21001000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m15; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 21255000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m12; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 24895000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m12; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 24900000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m10; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 28010000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m10; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 28300000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) m6; + defaults.dspMode = (DSPMode) CWU; + defaults.frequencyLo = 50010000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) m6; + defaults.dspMode = (DSPMode) USB; + defaults.frequencyLo = 50125000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + defaults.hamBand = (HamBand) gen; + defaults.dspMode = (DSPMode) SAM; + defaults.frequencyLo = 590000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) gen; + defaults.dspMode = (DSPMode) SAM; + defaults.frequencyLo = 3850000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) gen; + defaults.dspMode = (DSPMode) SAM; + defaults.frequencyLo = 5975000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) gen; + defaults.dspMode = (DSPMode) SAM; + defaults.frequencyLo = 9550000; + hamBandDefault << defaults; + + defaults.hamBand = (HamBand) gen; + defaults.dspMode = (DSPMode) SAM; + defaults.frequencyLo = 13845000; + hamBandDefault << defaults; + + hamBandDefaults << hamBandDefault; + + return hamBandDefaults; +} + +inline HamBand getBandFromFrequency(const QList bandList, long frequency) { + + HamBand band; + + for (int i = 0; i < bandList.size(); ++i) { + + if (bandList.at(i).frequencyLo <= frequency && bandList.at(i).frequencyHi >= frequency) { + + band = bandList.at(i).hamBand; + return band; + } + } + return (HamBand) gen; + +} + +inline TDefaultFilter getFilterFromDSPMode(const QList filterList, DSPMode mode) { + + TDefaultFilter filter; + + for (int i = 0; i < filterList.size(); ++i) { + + if (filterList.at(i).dspMode == mode) { + + filter = filterList.at(i); + return filter; + } + } + return filterList.at(0); +} + +inline QString getHamBandTextString(const QList textList, bool shortText, long frequency) { + + QString str = ""; + + for (int i = 0; i < textList.size(); ++i) { + + if (textList.at(i).frequencyLo <= frequency && textList.at(i).frequencyHi >= frequency) { + + if (shortText) + str = textList.at(i).shortText; + else + str = textList.at(i).text; + + return str; + } + else + str = "Out of Band"; + } + return str; +} + + +#endif // CUSDR_HAMDATABASE_H diff --git a/Source/src/cusdr_hpsdrTabWidget.cpp b/Source/src/cusdr_hpsdrTabWidget.cpp new file mode 100644 index 0000000..8c9c643 --- /dev/null +++ b/Source/src/cusdr_hpsdrTabWidget.cpp @@ -0,0 +1,212 @@ +/** +* @file cusdr_hpsdrTabWidget.cpp +* @brief Hardware settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "cusdr_hpsdrTabWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +HPSDRTabWidget::HPSDRTabWidget(QWidget *parent) + : QTabWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + setStyleSheet(set->getTabWidgetStyle()); + setContentsMargins(4, 4, 4, 0); + setMouseTracking(true); + + m_hpsdrWidget = new HPSDRWidget(this); + m_networkWidget = new NetworkWidget(this); + //m_transmitTabWidget = new TransmitTabWidget(this); + m_alexTabWidget = new AlexTabWidget(this); + m_extCtrlWidget = new ExtCtrlWidget(this); + + this->addTab(m_hpsdrWidget, " Config "); + this->addTab(m_networkWidget, " Network "); + //this->addTab(m_transmitTabWidget, " Transmit "); + this->addTab(m_extCtrlWidget, " Ext Ctrl "); + this->addTab(m_alexTabWidget, " Alex "); + + setTabEnabled(1, true); + + if (!set->getPenelopePresence() && !set->getPennyLanePresence() && (set->getHWInterface() != QSDR::Hermes)) { + + setTabEnabled(2, false); + //setTabEnabled(3, false); + } + + if (!set->getAlexPresence()) + setTabEnabled(3, false); + + setupConnections(); +} + +HPSDRTabWidget::~HPSDRTabWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize HPSDRTabWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize HPSDRTabWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void HPSDRTabWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(alexPresenceChanged(bool)), + this, + SLOT(setAlexPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(penelopePresenceChanged(bool)), + this, + SLOT(setPennyPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(pennyLanePresenceChanged(bool)), + this, + SLOT(setPennyPresence(bool))); +} + +void HPSDRTabWidget::systemStateChanged( + QObject *sender, /*!<[in] the sender of the signal. */ + QSDR::_Error err, /*!<[in] error state. */ + QSDR::_HWInterfaceMode hwmode, /*!<[in] HPSDR interface (Metis, Hermes, none). */ + QSDR::_ServerMode mode, /*!<[in] server mode. */ + QSDR::_DataEngineState state /*!<[in] data engine state. */ +) { + Q_UNUSED (sender) + Q_UNUSED (err) + + //if (sender == this) return; + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_hwInterface == QSDR::Hermes) + setTabEnabled(2, true); + else + setTabEnabled(2, false); + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; +} + +void HPSDRTabWidget::setPennyPresence(bool value) { + + //setTabEnabled(1, value); + setTabEnabled(2, value); + //setTabEnabled(3, value); +} + +void HPSDRTabWidget::setAlexPresence(bool value) { + + setTabEnabled(3, value); +} + +void HPSDRTabWidget::addNICChangedConnection() { + + m_networkWidget->addNICChangedConnection(); +} + +void HPSDRTabWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void HPSDRTabWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +void HPSDRTabWidget::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void HPSDRTabWidget::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void HPSDRTabWidget::mouseMoveEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void HPSDRTabWidget::mousePressEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void HPSDRTabWidget::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + + diff --git a/Source/src/cusdr_hpsdrTabWidget.h b/Source/src/cusdr_hpsdrTabWidget.h new file mode 100644 index 0000000..41320ad --- /dev/null +++ b/Source/src/cusdr_hpsdrTabWidget.h @@ -0,0 +1,105 @@ +/** +* @file cusdr_hpsdrTabWidget.h +* @brief Hardware settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_HPSDR_TABWIDGET_H +#define _CUSDR_HPSDR_TABWIDGET_H + +//#include +//#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_hpsdrWidget.h" +#include "cusdr_networkWidget.h" +//#include "cusdr_transmitTabWidget.h" +#include "cusdr_alexTabWidget.h" +#include "cusdr_extCtrlWidget.h" + + +class HPSDRTabWidget : public QTabWidget { + + Q_OBJECT + +public: + HPSDRTabWidget(QWidget *parent = 0); + ~HPSDRTabWidget(); + + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + void addNICChangedConnection(); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + Settings *set; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + HPSDRWidget *m_hpsdrWidget; + NetworkWidget *m_networkWidget; + AlexTabWidget *m_alexTabWidget; + ExtCtrlWidget *m_extCtrlWidget; + + QString m_message; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setAlexPresence(bool value); + void setPennyPresence(bool value); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString message); +}; + +#endif // _CUSDR_HPSDR_TABWIDGET_H diff --git a/Source/src/cusdr_hpsdrWidget.cpp b/Source/src/cusdr_hpsdrWidget.cpp new file mode 100644 index 0000000..ddf084d --- /dev/null +++ b/Source/src/cusdr_hpsdrWidget.cpp @@ -0,0 +1,1023 @@ +/** +* @file cusdr_hpsdrWidget.cpp +* @brief Hardware settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#define LOG_HPSDR_WIDGET + +// use: HPSDR_WIDGET_DEBUG + +//#include +//#include +//#include +//#include +#include + +#include "cusdr_hpsdrWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 42 + + +HPSDRWidget::HPSDRWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_hwInterfaceTemp(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(0) + , m_numberOfReceivers(1) + , m_hpsdrHardware(set->getHPSDRHardware()) +{ + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 8, 4, 0); + setMouseTracking(true); + + m_firmwareCheck = set->getFirmwareVersionCheck(); + + createSource10MhzExclusiveGroup(); + createSource122_88MhzExclusiveGroup(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 4, 0); + hbox1->addWidget(hpsdrHardwareBtnGroup()); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(0); + hbox2->setContentsMargins(4, 0, 4, 0); + hbox2->addWidget(source10MhzExclusiveGroup); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(0); + hbox3->setContentsMargins(4, 0, 4, 0); + hbox3->addWidget(source122_88MhzExclusiveGroup); + + QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(0); + //hbox4->setMargin(0); + //hbox4->addStretch(); + hbox4->setContentsMargins(4, 0, 4, 0); + hbox4->addWidget(sampleRateExclusiveGroup()); + + QHBoxLayout *hbox5 = new QHBoxLayout(); + hbox5->setSpacing(0); + hbox5->setContentsMargins(4, 0, 4, 0); + hbox5->addWidget(numberOfReceiversGroup()); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addLayout(hbox4); + mainLayout->addLayout(hbox5); + mainLayout->addStretch(); + setLayout(mainLayout); + + setupConnections(); + setHPSDRHardware(); +} + +HPSDRWidget::~HPSDRWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void HPSDRWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); +} + +QGroupBox* HPSDRWidget::hpsdrHardwareBtnGroup() { + + modulesPresenceBtn = new AeroButton("Modules", this); + modulesPresenceBtn->setRoundness(0); + modulesPresenceBtn->setFixedSize(btn_width, btn_height); + modulesPresenceBtn->setBtnState(AeroButton::OFF); + hardwareBtnList.append(modulesPresenceBtn); + + CHECKED_CONNECT( + modulesPresenceBtn, + SIGNAL(released()), + this, + SLOT(hpsdrHardwareChanged())); + + hermesPresenceBtn = new AeroButton("Hermes", this); + hermesPresenceBtn->setRoundness(0); + hermesPresenceBtn->setFixedSize(btn_width, btn_height); + hermesPresenceBtn->setBtnState(AeroButton::OFF); + hardwareBtnList.append(hermesPresenceBtn); + + CHECKED_CONNECT( + hermesPresenceBtn, + SIGNAL(released()), + this, + SLOT(hpsdrHardwareChanged())); + + penelopePresenceBtn = new AeroButton("Penelope", this); + penelopePresenceBtn->setRoundness(0); + penelopePresenceBtn->setFixedSize(btn_width, btn_height); + penelopePresenceBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + penelopePresenceBtn, + SIGNAL(released()), + this, + SLOT(penelopePresenceChanged())); + + pennyPresenceBtn = new AeroButton("Pennylane", this); + pennyPresenceBtn->setRoundness(0); + pennyPresenceBtn->setFixedSize(btn_width, btn_height); + pennyPresenceBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + pennyPresenceBtn, + SIGNAL(released()), + this, + SLOT(pennyPresenceChanged())); + + mercuryPresenceBtn = new AeroButton("Mercury", this); + mercuryPresenceBtn->setRoundness(0); + mercuryPresenceBtn->setFixedSize(btn_width, btn_height); + mercuryPresenceBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + mercuryPresenceBtn, + SIGNAL(released()), + this, + SLOT(mercuryPresenceChanged())); + + alexPresenceBtn = new AeroButton("Alex", this); + alexPresenceBtn->setRoundness(0); + alexPresenceBtn->setFixedSize(btn_width, btn_height); + alexPresenceBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + alexPresenceBtn, + SIGNAL(released()), + this, + SLOT(alexPresenceChanged())); + + excaliburPresenceBtn = new AeroButton("Excalibur", this); + excaliburPresenceBtn->setRoundness(0); + excaliburPresenceBtn->setFixedSize(btn_width, btn_height); + excaliburPresenceBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + excaliburPresenceBtn, + SIGNAL(released()), + this, + SLOT(excaliburPresenceChanged())); + + firmwareCheckBtn = new AeroButton("On", this); + firmwareCheckBtn->setRoundness(0); + firmwareCheckBtn->setFixedSize(btn_widths, btn_height); + + if (m_firmwareCheck) { + + firmwareCheckBtn->setBtnState(AeroButton::ON); + firmwareCheckBtn->setText("On"); + } + else { + + firmwareCheckBtn->setBtnState(AeroButton::OFF); + firmwareCheckBtn->setText("Off"); + } + + CHECKED_CONNECT( + firmwareCheckBtn, + SIGNAL(released()), + this, + SLOT(firmwareCheckChanged())); + + m_fwCheckLabel = new QLabel("Firmware Check:", this); + m_fwCheckLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_fwCheckLabel->setStyleSheet(set->getLabelStyle()); + + QHBoxLayout *hbox0 = new QHBoxLayout(); + hbox0->setSpacing(4); + hbox0->addStretch(); + hbox0->addWidget(m_fwCheckLabel); + hbox0->addWidget(firmwareCheckBtn); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(modulesPresenceBtn); + hbox1->addWidget(hermesPresenceBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(4); + hbox2->addStretch(); + hbox2->addWidget(penelopePresenceBtn); + hbox2->addWidget(pennyPresenceBtn); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(4); + hbox3->addStretch(); + hbox3->addWidget(mercuryPresenceBtn); + hbox3->addWidget(excaliburPresenceBtn); + + QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(4); + hbox4->addStretch(); + hbox4->addWidget(alexPresenceBtn); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox0); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + vbox->addLayout(hbox3); + vbox->addLayout(hbox4); + + QGroupBox *groupBox = new QGroupBox(tr("Hardware selection"), this); + groupBox->setMinimumWidth(m_minimumGroupBoxWidth); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(set->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +void HPSDRWidget::createSource10MhzExclusiveGroup() { + + atlasBtn = new AeroButton("Atlas", this); + atlasBtn->setRoundness(0); + atlasBtn->setFixedSize(btn_width, btn_height); + source10MhzBtnList.append(atlasBtn); + + CHECKED_CONNECT( + atlasBtn, + SIGNAL(released()), + this, + SLOT(source10MhzChanged())); + + penelopeBtn = new AeroButton("Penny[Lane]", this); + penelopeBtn->setRoundness(0); + penelopeBtn->setFixedSize(btn_width, btn_height); + source10MhzBtnList.append(penelopeBtn); + + CHECKED_CONNECT( + penelopeBtn, + SIGNAL(released()), + this, + SLOT(source10MhzChanged())); + + mercuryBtn = new AeroButton("Mercury", this); + mercuryBtn->setRoundness(0); + mercuryBtn->setFixedSize(btn_width, btn_height); + source10MhzBtnList.append(mercuryBtn); + + CHECKED_CONNECT( + mercuryBtn, + SIGNAL(released()), + this, + SLOT(source10MhzChanged())); + + + sources10Mhz << "Atlas" << "Penelope" << "Mercury"; + + switch(set->get10MHzSource()) { + + case 0: + atlasBtn->setBtnState(AeroButton::ON); + penelopeBtn->setBtnState(AeroButton::OFF); + mercuryBtn->setBtnState(AeroButton::OFF); + break; + + case 1: + penelopeBtn->setBtnState(AeroButton::ON); + atlasBtn->setBtnState(AeroButton::OFF); + mercuryBtn->setBtnState(AeroButton::OFF); + break; + + case 2: + mercuryBtn->setBtnState(AeroButton::ON); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + break; + + case 3: + mercuryBtn->setBtnState(AeroButton::OFF); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + break; + } + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(penelopeBtn); + hbox1->addWidget(mercuryBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(4); + hbox2->addStretch(); + hbox2->addWidget(atlasBtn); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + source10MhzExclusiveGroup = new QGroupBox(tr("10 MHz Clock"), this); + source10MhzExclusiveGroup->setMinimumWidth(m_minimumGroupBoxWidth); + source10MhzExclusiveGroup->setLayout(vbox); + source10MhzExclusiveGroup->setStyleSheet(set->getWidgetStyle()); + source10MhzExclusiveGroup->setFont(QFont("Arial", 8)); +} + +void HPSDRWidget::createSource122_88MhzExclusiveGroup() { + + penelope2Btn = new AeroButton("Penny[Lane]", this); + penelope2Btn->setRoundness(0); + penelope2Btn->setFixedSize(btn_width, btn_height); + + CHECKED_CONNECT( + penelope2Btn, + SIGNAL(clicked()), + this, + SLOT(source122_88MhzChanged())); + + mercury2Btn = new AeroButton("Mercury", this); + mercury2Btn->setRoundness(0); + mercury2Btn->setFixedSize(btn_width, btn_height); + + CHECKED_CONNECT( + mercury2Btn, + SIGNAL(clicked()), + this, + SLOT(source122_88MhzChanged())); + + switch(set->get122_8MHzSource()) { + + case 0: + penelope2Btn->setBtnState(AeroButton::ON); + mercury2Btn->setBtnState(AeroButton::OFF); + break; + + case 1: + mercury2Btn->setBtnState(AeroButton::ON); + penelope2Btn->setBtnState(AeroButton::OFF); + break; + } + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(penelope2Btn); + hbox1->addWidget(mercury2Btn); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + + source122_88MhzExclusiveGroup = new QGroupBox(tr("122.8 MHz Clock"), this); + source122_88MhzExclusiveGroup->setMinimumWidth(m_minimumGroupBoxWidth); + source122_88MhzExclusiveGroup->setLayout(vbox); + source122_88MhzExclusiveGroup->setStyleSheet(set->getWidgetStyle()); + source122_88MhzExclusiveGroup->setFont(QFont("Arial", 8)); +} + +QGroupBox *HPSDRWidget::sampleRateExclusiveGroup() { + + samplerate48Btn = new AeroButton("48 kHz", this); + samplerate48Btn->setRoundness(0); + samplerate48Btn->setFixedSize (50, btn_height); + samplerate48Btn->setStyleSheet(set->getMiniButtonStyle()); + samplerateBtnList.append(samplerate48Btn); + CHECKED_CONNECT(samplerate48Btn, SIGNAL(released()), this, SLOT(sampleRateChanged())); + + samplerate96Btn = new AeroButton("96 kHz", this); + samplerate96Btn->setRoundness(0); + samplerate96Btn->setFixedSize (50, btn_height); + samplerate96Btn->setStyleSheet(set->getMiniButtonStyle()); + samplerateBtnList.append(samplerate96Btn); + CHECKED_CONNECT(samplerate96Btn, SIGNAL(released()), this, SLOT(sampleRateChanged())); + + samplerate192Btn = new AeroButton("192 kHz", this); + samplerate192Btn->setRoundness(0); + samplerate192Btn->setFixedSize (50, btn_height); + samplerate192Btn->setStyleSheet(set->getMiniButtonStyle()); + samplerateBtnList.append(samplerate192Btn); + CHECKED_CONNECT(samplerate192Btn, SIGNAL(released()), this, SLOT(sampleRateChanged())); + + samplerate384Btn = new AeroButton("384 kHz", this); + samplerate384Btn->setRoundness(0); + samplerate384Btn->setFixedSize (50, btn_height); + samplerate384Btn->setStyleSheet(set->getMiniButtonStyle()); + //samplerate384Btn->setEnabled(false); + samplerateBtnList.append(samplerate384Btn); + CHECKED_CONNECT(samplerate384Btn, SIGNAL(released()), this, SLOT(sampleRateChanged())); + + switch(set->getSampleRate()) { + + case 48000: + samplerate48Btn->setBtnState(AeroButton::ON); + samplerate96Btn->setBtnState(AeroButton::OFF); + samplerate192Btn->setBtnState(AeroButton::OFF); + samplerate384Btn->setBtnState(AeroButton::OFF); + break; + + case 96000: + samplerate48Btn->setBtnState(AeroButton::OFF); + samplerate96Btn->setBtnState(AeroButton::ON); + samplerate192Btn->setBtnState(AeroButton::OFF); + samplerate384Btn->setBtnState(AeroButton::OFF); + break; + + case 192000: + samplerate48Btn->setBtnState(AeroButton::OFF); + samplerate96Btn->setBtnState(AeroButton::OFF); + samplerate192Btn->setBtnState(AeroButton::ON); + samplerate384Btn->setBtnState(AeroButton::OFF); + break; + + case 384000: + samplerate48Btn->setBtnState(AeroButton::OFF); + samplerate96Btn->setBtnState(AeroButton::OFF); + samplerate192Btn->setBtnState(AeroButton::OFF); + samplerate384Btn->setBtnState(AeroButton::ON); + break; + } + + QHBoxLayout *hbox = new QHBoxLayout(); + hbox->setSpacing(4); + hbox->addStretch(); + hbox->addWidget(samplerate48Btn); + hbox->addWidget(samplerate96Btn); + hbox->addWidget(samplerate192Btn); + hbox->addWidget(samplerate384Btn); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox); + + QGroupBox *groupBox = new QGroupBox(tr("Sample Rate"), this); + groupBox->setMinimumWidth(m_minimumGroupBoxWidth); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(set->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +QGroupBox *HPSDRWidget::numberOfReceiversGroup() { + + m_receiverComboBox = new QComboBox(this); + m_receiverComboBox->setStyleSheet(set->getComboBoxStyle()); + m_receiverComboBox->setMinimumContentsLength(4); + + QString str = "%1"; + for (int i = 0; i < MAX_RECEIVERS; i++) + m_receiverComboBox->addItem(str.arg(i+1)); + + CHECKED_CONNECT( + m_receiverComboBox, + SIGNAL(currentIndexChanged(int)), + this, + SLOT(setNumberOfReceivers(int))); + + m_receiversLabel = new QLabel("Receivers:", this); + m_receiversLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_receiversLabel->setStyleSheet(set->getLabelStyle()); + + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(5); + //hbox1->addStretch(); + hbox1->addWidget(m_receiversLabel); + hbox1->addStretch(); + hbox1->addWidget(m_receiverComboBox); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + + QGroupBox *groupBox = new QGroupBox(tr("Number of Receivers"), this); + groupBox->setMinimumWidth(m_minimumGroupBoxWidth); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(set->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +// ************************************************************************ + +void HPSDRWidget::setHPSDRHardware() { + + switch (m_hpsdrHardware) { + + case 0: + // HPSDR modules + modulesPresenceBtn->setBtnState(AeroButton::ON); + hermesPresenceBtn->setBtnState(AeroButton::OFF); + + mercuryPresenceBtn->setEnabled(true); + if (set->getMercuryPresence()) + mercuryPresenceBtn->setBtnState(AeroButton::ON); + else + mercuryPresenceBtn->setBtnState(AeroButton::OFF); + + penelopePresenceBtn->setEnabled(true); + pennyPresenceBtn->setEnabled(true); + + if (set->getPenelopePresence()) { + + penelopePresenceBtn->setBtnState(AeroButton::ON); + pennyPresenceBtn->setBtnState(AeroButton::OFF); + } + else if (set->getPennyLanePresence()) { + + penelopePresenceBtn->setBtnState(AeroButton::OFF); + pennyPresenceBtn->setBtnState(AeroButton::ON); + } + else { + + penelopePresenceBtn->setBtnState(AeroButton::OFF); + pennyPresenceBtn->setBtnState(AeroButton::OFF); + } + + excaliburPresenceBtn->setEnabled(true); + if (set->getExcaliburPresence()) { + + set->set10MhzSource(this, 3); // none + mercuryBtn->setBtnState(AeroButton::OFF); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + mercuryBtn->setEnabled(false); + penelopeBtn->setEnabled(false); + atlasBtn->setEnabled(false); + + excaliburPresenceBtn->setBtnState(AeroButton::ON); + } + else { + + switch(set->get10MHzSource()) { + + case 0: + atlasBtn->setBtnState(AeroButton::ON); + penelopeBtn->setBtnState(AeroButton::OFF); + mercuryBtn->setBtnState(AeroButton::OFF); + break; + + case 1: + penelopeBtn->setBtnState(AeroButton::ON); + atlasBtn->setBtnState(AeroButton::OFF); + mercuryBtn->setBtnState(AeroButton::OFF); + break; + + case 2: + mercuryBtn->setBtnState(AeroButton::ON); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + break; + + case 3: + mercuryBtn->setBtnState(AeroButton::OFF); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + break; + } + + excaliburPresenceBtn->setBtnState(AeroButton::OFF); + } + + break; + + case 1: + + // Hermes + modulesPresenceBtn->setBtnState(AeroButton::OFF); + hermesPresenceBtn->setBtnState(AeroButton::ON); + + penelopePresenceBtn->setBtnState(AeroButton::OFF); + penelopePresenceBtn->setEnabled(false); + + pennyPresenceBtn->setBtnState(AeroButton::OFF); + pennyPresenceBtn->setEnabled(false); + + mercuryPresenceBtn->setBtnState(AeroButton::OFF); + mercuryPresenceBtn->setEnabled(false); + + excaliburPresenceBtn->setBtnState(AeroButton::OFF); + excaliburPresenceBtn->setEnabled(false); + + set->set10MhzSource(this, 2); // none + source10MhzExclusiveGroup->hide(); + source122_88MhzExclusiveGroup->hide(); + + break; + + case 2: + + // Cyclops + break; + } + + if (set->getAlexPresence()) + alexPresenceBtn->setBtnState(AeroButton::ON); +} + +void HPSDRWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + //m_oldServerMode = m_serverMode; + if (m_serverMode != mode) { + + if (mode == QSDR::ChirpWSPR) + disableButtons(); + + if (m_serverMode == QSDR::ChirpWSPR) + enableButtons(); + + m_serverMode = mode; + } + + if (m_dataEngineState != state) { + + if (state == QSDR::DataEngineUp) + disableButtons(); + else + enableButtons(); + + m_dataEngineState = state; + } + update(); +} + +void HPSDRWidget::hpsdrHardwareChanged() { + + AeroButton *button = qobject_cast(sender()); + int btn = hardwareBtnList.indexOf(button); + + foreach(AeroButton *btn, hardwareBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + m_hpsdrHardware = btn; + set->setHPSDRHardware(m_hpsdrHardware); + + setHPSDRHardware(); + + switch (m_hpsdrHardware) { + + case 0: + // HPSDR modules + source10MhzExclusiveGroup->show(); + source122_88MhzExclusiveGroup->show(); + + m_hwInterface = QSDR::Metis; + + emit messageEvent("[hpsdr]: HPSDR modules chosen."); + break; + + case 1: + // Hermes + source10MhzExclusiveGroup->hide(); + source122_88MhzExclusiveGroup->hide(); + + m_hwInterface = QSDR::Hermes; + emit messageEvent("[hpsdr]: Hermes chosen."); + break; + + case 2: + break; + } + + set->setSystemState( + this, + QSDR::NoError, + m_hwInterface, + m_serverMode, + m_dataEngineState); +} + +void HPSDRWidget::penelopePresenceChanged() { + + if (penelopePresenceBtn->btnState() == AeroButton::OFF) { + + if (pennyPresenceBtn->btnState() == AeroButton::ON) { + + set->setPennyLanePresence(false); + pennyPresenceBtn->setBtnState(AeroButton::OFF); + pennyPresenceBtn->update(); + + emit messageEvent("[hpsdr]: PennyLane removed"); + } + set->setPenelopePresence(true); + penelopePresenceBtn->setBtnState(AeroButton::ON); + + emit messageEvent("[hpsdr]: Penelope added"); + + } else { + + set->setPenelopePresence(false); + penelopePresenceBtn->setBtnState(AeroButton::OFF); + emit messageEvent("[hpsdr]: Penelope removed."); + } +} + +void HPSDRWidget::pennyPresenceChanged() { + + if (pennyPresenceBtn->btnState() == AeroButton::OFF) { + + if (penelopePresenceBtn->btnState() == AeroButton::ON) { + + set->setPenelopePresence(false); + penelopePresenceBtn->setBtnState(AeroButton::OFF); + penelopePresenceBtn->update(); + + emit messageEvent("[hpsdr]: Penelope removed"); + } + set->setPennyLanePresence(true); + pennyPresenceBtn->setBtnState(AeroButton::ON); + + emit messageEvent("[hpsdr]: PennyLane added"); + + } else { + + set->setPennyLanePresence(false); + pennyPresenceBtn->setBtnState(AeroButton::OFF); + emit messageEvent("[hpsdr]: PennyLane removed."); + } +} + +void HPSDRWidget::mercuryPresenceChanged() { + + if (mercuryPresenceBtn->btnState() == AeroButton::OFF) { + + set->setMercuryPresence(true); + mercuryPresenceBtn->setBtnState(AeroButton::ON); + emit messageEvent("[hpsdr]: Mercury added."); + + } else { + + set->setMercuryPresence(false); + mercuryPresenceBtn->setBtnState(AeroButton::OFF); + emit messageEvent("[hpsdr]: Mercury removed."); + } +} + +void HPSDRWidget::alexPresenceChanged() { + + if (alexPresenceBtn->btnState() == AeroButton::OFF) { + + set->setAlexPresence(true); + alexPresenceBtn->setBtnState(AeroButton::ON); + emit messageEvent("[hpsdr]: Alex added."); + + } else { + + set->setAlexPresence(false); + alexPresenceBtn->setBtnState(AeroButton::OFF); + emit messageEvent("[hpsdr]: Alex removed."); + } +} + +void HPSDRWidget::excaliburPresenceChanged() { + + if (excaliburPresenceBtn->btnState() == AeroButton::OFF) { + + set->set10MhzSource(this, 3); // None + + mercuryBtn->setBtnState(AeroButton::OFF); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + + mercuryBtn->setEnabled(false); + penelopeBtn->setEnabled(false); + atlasBtn->setEnabled(false); + + set->setExcaliburPresence(true); + excaliburPresenceBtn->setBtnState(AeroButton::ON); + emit messageEvent("[hpsdr]: Excalibur added."); + + } else { + + set->set10MhzSource(this, 2); // Mercury + + mercuryBtn->setEnabled(true); + penelopeBtn->setEnabled(true); + atlasBtn->setEnabled(true); + + mercuryBtn->setBtnState(AeroButton::ON); + mercuryBtn->update(); + atlasBtn->setBtnState(AeroButton::OFF); + penelopeBtn->setBtnState(AeroButton::OFF); + + set->setExcaliburPresence(false); + excaliburPresenceBtn->setBtnState(AeroButton::OFF); + emit messageEvent("[hpsdr]: Excalibur removed."); + } +} + +void HPSDRWidget::firmwareCheckChanged() { + + if (firmwareCheckBtn->btnState() == AeroButton::OFF) { + + set->setCheckFirmwareVersion(this, true); + firmwareCheckBtn->setBtnState(AeroButton::ON); + firmwareCheckBtn->setText("On"); + + } else { + + set->setCheckFirmwareVersion(this, false); + firmwareCheckBtn->setBtnState(AeroButton::OFF); + firmwareCheckBtn->setText("Off"); + } +} + +void HPSDRWidget::source10MhzChanged() { + + AeroButton *button = qobject_cast(sender()); + int btn = source10MhzBtnList.indexOf(button); + + foreach(AeroButton *btn, source10MhzBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + set->set10MhzSource(this, btn); + button->setBtnState(AeroButton::ON); + button->update(); + + QString msg = "[hpsdr]: 10 MHz source changed to %1"; + emit messageEvent(msg.arg(sources10Mhz.at(btn))); +} + +void HPSDRWidget::source122_88MhzChanged() { + + switch (set->get122_8MHzSource()) { + + // penelope 0, mercury 1 + case 0: + penelope2Btn->setBtnState(AeroButton::OFF); + penelope2Btn->update(); + + set->set122_88MhzSource(this, 1); + emit messageEvent("[hpsdr]: 122.88 MHz source changed to Mercury."); + mercury2Btn->setBtnState(AeroButton::ON); + break; + + case 1: + mercury2Btn->setBtnState(AeroButton::OFF); + mercury2Btn->update(); + + set->set122_88MhzSource(this, 0); + emit messageEvent("[hpsdr]: 122.88 MHz source changed to Penelope."); + penelope2Btn->setBtnState(AeroButton::ON); + break; + } +} + +void HPSDRWidget::sampleRateChanged() { + + AeroButton *button = qobject_cast(sender()); + int btnHit = samplerateBtnList.indexOf(button); + + foreach(AeroButton *btn, samplerateBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (btnHit) { + + case 0: + set->setSampleRate(this, 48000); + HPSDR_WIDGET_DEBUG << "set sample rate to 48 kHz."; + break; + + case 1: + set->setSampleRate(this, 96000); + HPSDR_WIDGET_DEBUG << "set sample rate to 96 kHz."; + break; + + case 2: + set->setSampleRate(this, 192000); + HPSDR_WIDGET_DEBUG << "set sample rate to 192 kHz."; + break; + + case 3: + set->setSampleRate(this, 384000); + HPSDR_WIDGET_DEBUG << "set sample rate to 384 kHz."; + break; + } +} + +void HPSDRWidget::setNumberOfReceivers(int receivers) { + + m_numberOfReceivers = receivers+1; + set->setReceivers(this, m_numberOfReceivers); +} + +void HPSDRWidget::disableButtons() { + + modulesPresenceBtn->setEnabled(false); + hermesPresenceBtn->setEnabled(false); + + penelopePresenceBtn->setEnabled(false); + pennyPresenceBtn->setEnabled(false); + mercuryPresenceBtn->setEnabled(false); + excaliburPresenceBtn->setEnabled(false); + alexPresenceBtn->setEnabled(false); + atlasBtn->setEnabled(false); + penelopeBtn->setEnabled(false); + mercuryBtn->setEnabled(false); + penelope2Btn->setEnabled(false); + mercury2Btn->setEnabled(false); + + m_receiverComboBox->setEnabled(false); +} + +void HPSDRWidget::enableButtons() { + + modulesPresenceBtn->setEnabled(true); + hermesPresenceBtn->setEnabled(true); + + penelopePresenceBtn->setEnabled(true); + pennyPresenceBtn->setEnabled(true); + mercuryPresenceBtn->setEnabled(true); + excaliburPresenceBtn->setEnabled(true); + alexPresenceBtn->setEnabled(true); + atlasBtn->setEnabled(true); + penelopeBtn->setEnabled(true); + mercuryBtn->setEnabled(true); + penelope2Btn->setEnabled(true); + mercury2Btn->setEnabled(true); + + m_receiverComboBox->setEnabled(true); +} diff --git a/Source/src/cusdr_hpsdrWidget.h b/Source/src/cusdr_hpsdrWidget.h new file mode 100644 index 0000000..33fde2e --- /dev/null +++ b/Source/src/cusdr_hpsdrWidget.h @@ -0,0 +1,144 @@ +/** +* @file cusdr_hpsdrWidget.h +* @brief Hardware settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_HPSDR_WIDGET_H +#define _CUSDR_HPSDR_WIDGET_H + +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + +#ifdef LOG_HPSDR_WIDGET +# define HPSDR_WIDGET_DEBUG qDebug().nospace() << "HPSDRWidget::\t" +#else +# define HPSDR_WIDGET_DEBUG nullDebug() +#endif + + +class HPSDRWidget : public QWidget { + + Q_OBJECT + +public: + HPSDRWidget(QWidget *parent = 0); + ~HPSDRWidget(); + + +public slots: + void hpsdrHardwareChanged(); + void penelopePresenceChanged(); + void pennyPresenceChanged(); + void mercuryPresenceChanged(); + void alexPresenceChanged(); + void excaliburPresenceChanged(); + void source122_88MhzChanged(); + +private: + Settings *set; + + QGroupBox *hpsdrHardwareBtnGroup(); + QGroupBox *receiversExclusiveBtnGroup(); + QGroupBox *source10MhzExclusiveGroup; + QGroupBox *source122_88MhzExclusiveGroup; + QGroupBox *sampleRateExclusiveGroup(); + QGroupBox *numberOfReceiversGroup(); + + QComboBox *m_receiverComboBox; + + QLabel *m_fwCheckLabel; + QLabel *m_receiversLabel; + + QString m_message; + + AeroButton *hermesPresenceBtn; + AeroButton *modulesPresenceBtn; + AeroButton *penelopePresenceBtn; + AeroButton *pennyPresenceBtn; + AeroButton *mercuryPresenceBtn; + AeroButton *alexPresenceBtn; + AeroButton *excaliburPresenceBtn; + AeroButton *firmwareCheckBtn; + AeroButton *atlasBtn; + AeroButton *penelopeBtn; + AeroButton *mercuryBtn; + AeroButton *penelope2Btn; + AeroButton *mercury2Btn; + AeroButton *samplerate48Btn; + AeroButton *samplerate96Btn; + AeroButton *samplerate192Btn; + AeroButton *samplerate384Btn; + + QList hardwareBtnList; + QList source10MhzBtnList; + QList viewBtnList; + QList sources10Mhz; + QList samplerateBtnList; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_HWInterfaceMode m_hwInterfaceTemp; + QSDR::_DataEngineState m_dataEngineState; + + bool m_firmwareCheck; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_numberOfReceivers; + int m_hpsdrHardware; + int m_socketBufferSize; + + void setupConnections(); + void createSource10MhzExclusiveGroup(); + void createSource122_88MhzExclusiveGroup(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setHPSDRHardware(); + void source10MhzChanged(); + void setNumberOfReceivers(int value); + void disableButtons(); + void enableButtons(); + void firmwareCheckChanged(); + void sampleRateChanged(); + +signals: + void messageEvent(QString message); +}; + +#endif // _CUSDR_HPSDR_WIDGET_H diff --git a/Source/src/cusdr_mainWidget.cpp b/Source/src/cusdr_mainWidget.cpp new file mode 100644 index 0000000..d36f614 --- /dev/null +++ b/Source/src/cusdr_mainWidget.cpp @@ -0,0 +1,2710 @@ +/** +* @file cusdr_mainWidget.cpp +* @brief main window widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-01-06 +*/ + +/* + * Copyright 2010, 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_MAIN +//#define LOG_NETWORKDIALOG + +// use: MAIN_DEBUG +// use: NETWORKDIALOG_DEBUG + +//#include +//#include +//#include +//#include +//#include + +#include "cusdr_mainWidget.h" + + +#define window_height1 600 +#define window_height2 750 +#define window_width1 800 +#define window_width2 1030 +#define btn_width1 56//65 +#define btn_width2 54 +#define btn_width3 48 +#define btn_height1 17 +#define btn_height2 13 +#define btn_height3 16 + + + +/*! + \class MainWindow + \brief This class implements main window of the application. +*/ +/*! + \brief Creates a new #MainWindow with the given \a parent. + This function does following steps: + - set up GUI. + - set up connections. + - find network connections. +*/ +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_cudaPresence(false) + , m_mover(false) + , m_resizePosition(0) +{ + QPalette palette; + QColor color = Qt::black; + color.setAlpha(255); + palette.setColor(QPalette::Window, color); + setPalette(palette); + + setAutoFillBackground(true); + setMouseTracking(true); + setContentsMargins(0, 0, 0, 0); + + m_fullScreen = false; + + // save and reload the windows size and state + m_windowsSettingsFilename = "windowsSettings.ini"; + QSettings settings(QCoreApplication::applicationDirPath() + "/" + m_windowsSettingsFilename, QSettings::IniFormat); + restoreGeometry(settings.value("geometry").toByteArray()); + restoreState(settings.value("windowState").toByteArray()); + + // Dock windows options + setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks); + setMinimumSize(QSize(window_width1, window_height1)); + setStyleSheet(set->getSDRStyle()); + + m_oldSampleRate = set->getSampleRate(); + m_numberOfReceivers = set->getNumberOfReceivers(); + m_alexConfig = set->getAlexConfig(); + m_alexStates = set->getAlexStates(); + m_mercuryAttn = set->getMercuryAttenuators(0); + m_currentHamBand = set->getCurrentHamBand(0); + + m_alexAttnState = 0x03 & (m_alexStates[m_currentHamBand] >> 7); + m_mercuryAttnState = m_mercuryAttn.at(m_currentHamBand); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + // the SDR data engine + m_dataEngine = new DataEngine(this); + + // control widgets + m_serverWidget = new ServerWidget(this); + m_chirpWidget = new ChirpWidget(this); + m_hpsdrTabWidget = new HPSDRTabWidget(this); + m_radioTabWidget = new RadioTabWidget(this); + m_displayTabWidget = new DisplayTabWidget(this); + + m_wbDisplay = 0; + + m_serverWidget->hide(); + m_chirpWidget->hide(); + m_hpsdrTabWidget->hide(); + m_radioTabWidget->hide(); + m_displayTabWidget->hide(); + + MAIN_DEBUG << "main window init done"; +} + +/*! + \brief MainWindow Destructor +*/ +MainWindow::~MainWindow() { +} + +/*! + \brief set up connections. +*/ +void MainWindow::setupConnections() { + + CHECKED_CONNECT_OPT( + set, + SIGNAL(systemMessageEvent(const QString&, int)), + this, + SLOT(showStatusBarMessage(const QString &, int)), + Qt::DirectConnection); + + CHECKED_CONNECT( + m_dataEngine, + SIGNAL(clearSystemMessageEvent()), + this, + SLOT(clearStatusBarMessage())); + + CHECKED_CONNECT( + m_chirpWidget, + SIGNAL(loadFileEvent(QObject *, const QString)), + this, + SLOT(loadWavFile(QObject *, const QString))); + + CHECKED_CONNECT( + m_chirpWidget, + SIGNAL(suspendSignal(QObject *)), + this, + SLOT(suspendSignal(QObject *))); + + CHECKED_CONNECT( + m_chirpWidget, + SIGNAL(startPlaybackSignal(QObject *)), + this, + SLOT(startPlaybackSignal(QObject *))); + + CHECKED_CONNECT( + m_chirpWidget, + SIGNAL(showSettingsDialogSignal(QObject *)), + this, + SLOT(showSettingsDialogSignal(QObject *))); + + /*if (m_cudaPresence) { + + CHECKED_CONNECT( + m_cudaInfoWidget, + SIGNAL(showEvent(QObject *)), + this, + SLOT(showWidgetEvent(QObject *))); + + CHECKED_CONNECT( + m_cudaInfoWidget, + SIGNAL(closeEvent(QObject *)), + this, + SLOT(closeWidgetEvent(QObject *))); + }*/ + + CHECKED_CONNECT( + set, + SIGNAL(cpuLoadChanged(short)), + this, + SLOT(updateStatusBar(short))); + + CHECKED_CONNECT( + set, + SIGNAL(masterSwitchChanged(QObject *, bool)), + this, + SLOT(masterSwitchChanged(QObject *, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(numberOfRXChanged(QObject *, int)), + this, + SLOT(setNumberOfReceivers(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(callsignChanged()), + this, + SLOT(updateTitle())); + + CHECKED_CONNECT( + set, + SIGNAL(showNetworkIO()), + this, + SLOT(showNetworkIODialog())); + + CHECKED_CONNECT( + set, + SIGNAL(showWarning(const QString &)), + this, + SLOT(showWarningDialog(const QString &))); + + CHECKED_CONNECT( + set, + SIGNAL(networkIOComboBoxEntryAdded(QString)), + this, + SLOT(addNetworkIOComboBoxEntry(QString))); + + CHECKED_CONNECT( + set, + SIGNAL(clearNetworkIOComboBoxEntrySignal()), + this, + SLOT(clearNetworkIOComboBoxEntry())); + + CHECKED_CONNECT( + set, + SIGNAL(showRadioPopupChanged(bool)), + this, + SLOT(showRadioPopup(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(txAllowedChanged(QObject *, bool)), + this, + SLOT(setTxAllowed(QObject *, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(agcModeChanged(QObject *, int, AGCMode, bool)), + this, + SLOT(setAGCMode(QObject *, int, AGCMode, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(agcMaximumGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCGain(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(agcFixedGainChanged_dB(QObject *, int, qreal)), + this, + SLOT(setAGCGain(QObject *, int, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(mercuryAttenuatorChanged(QObject *, HamBand, int))); + + CHECKED_CONNECT( + set, + SIGNAL(alexPresenceChanged(bool)), + this, + SLOT(alexPresenceChanged(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(alexConfigurationChanged(quint16)), + this, + SLOT(alexConfigurationChanged(quint16))); + + CHECKED_CONNECT( + set, + SIGNAL(alexStateChanged(HamBand, const QList &)), + this, + SLOT(alexStateChanged(HamBand, const QList &))); +} + +/*! + \brief setup the main window (called in main.cpp): + - create main button group + - create dock widgets + - create mode menus + - setup main layout + - setup connections + - setup dialog windows + - get network interfaces +*/ +void MainWindow::setup() { + + //runFFTWWisdom(); + + // create the big display panel at the top of the application. + createDisplayPanelToolBar(); + + // create the main buttons tool bar + createMainBtnToolBar(); + + // create the status tool bar + createStatusToolBar(); + + // create the mode menu + createModeMenu(); + + // create the view menu + createViewMenu(); + + // create the attenuator menu + createAttenuatorMenu(); + + // the wideband display + m_wbDisplay = new QGLWidebandPanel(this); + + // create the receiver panels + createReceiverPanels(MAX_RECEIVERS); + + // setup the layout for the control widgets, the wideband panel and the receiver panels + setupLayout(); + + // set the main window title + updateTitle(); + + // show the wideband data panel as specified in the settings.ini + if (set->getWidebandData()) { + + wideBandBtn->setEnabled(true); + + if (set->getWidebandStatus()) { + wideBandBtnClickedEvent(); + } + } + + // get the network interfaces + getNetworkInterfaces(); + + // init network IO dialog to HPSDR components + m_netIODialog = new NetworkIODialog(); + + // init warning dialog + m_warningDialog = new WarningDialog(); + + // setup connection for the NIC lists of the server and hpsdr widgets. + // We need to add these connections after detecting the network interfaces. + m_serverWidget->addNICChangedConnection(); + m_hpsdrTabWidget->addNICChangedConnection(); + + // experimental: + // check for OpenCL devices + //QList clDevices = QCLDevice::allDevices(); + //if (clDevices.length() == 0) + // showMessage("[main]: no OpenCL devices found."); + + //else { + + // m_message = "[main]: found %1 OpenCL device(s)."; + // showStatusBarMessage(m_message.arg(clDevices.length()), 5000); + // //QString clNo = QString::number(m_clDevices.length()); + //} + //set->setOpenCLDevices(clDevices); + + // set the centralwidget as the central widget of the main window, + // i.e., we have a second QMainWindow as the central widget. + setCentralWidget(centralwidget); + + // update the display panel + m_oglDisplayPanel->updateGL(); + + // set the Alex configuration + alexConfigurationChanged(m_alexConfig); + + // set the value of the attenuator(s) + setAttenuatorButton(); + + m_agcMode = set->getAGCMode(0); + + // initialize all Signal/Slot connections + setupConnections(); + + updateFromSettings(); +} + +//void MainWindow::runFFTWWisdom() { +// +// QString directory = QDir::currentPath(); +// +// m_currentDir = QDir(directory); +// qDebug() << m_currentDir; +// +// if (m_currentDir.exists("wisdom")) { +// +// qDebug() << "wisdom exists !"; +// return; +// } +// else { +// +// qDebug() << "wisdom does not exist - running fftw-wisdom.exe ..."; +// QProcess process; +// process.start("fftwf-wisdom.exe"); +// process.waitForFinished(); +// } +//} + +/*! + \brief updates the OpenGL widget. +*/ +void MainWindow::update() { + + //if (m_oglWidget) + // m_oglWidget->update(); +} + +/*! + \brief set up the main layout. +*/ +void MainWindow::setupLayout() { + + centralwidget = new QMainWindow(this); + centralwidget->setWindowFlags(Qt::Widget); + centralwidget->setDockOptions(QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks); + centralwidget->setStyleSheet(set->getMainWindowStyle()); + centralwidget->setContextMenuPolicy(Qt::NoContextMenu); //setStyleSheet(set->getMenuStyle()); + + // radio control widget + QDockWidget *dock = new QDockWidget(tr("Radio Ctrl"), this); + dock->setObjectName("RadioCtrl"); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + //dock->setFeatures(QDockWidget::DockWidgetFloatable); + dock->setStyleSheet(set->getDockStyle()); + dock->setMaximumWidth(245); + dock->setMinimumWidth(245); + dock->setWidget(m_radioTabWidget); + dockWidgetList.append(dock); + + addDockWidget(Qt::RightDockWidgetArea, dock); + dock->hide(); + + // server control widget + dock = new QDockWidget(tr("Server Ctrl"), this); + dock->setObjectName("ServerCtrl"); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + //dock->setFeatures(QDockWidget::DockWidgetFloatable); + dock->setStyleSheet(set->getDockStyle()); + dock->setMaximumWidth(245); + dock->setMinimumWidth(245); + dock->setWidget(m_serverWidget); + dockWidgetList.append(dock); + + addDockWidget(Qt::RightDockWidgetArea, dock); + dock->hide(); + + // HPSDR hardware control widget + dock = new QDockWidget(tr("HPSDR Ctrl"), this); + dock->setObjectName("HPSDRCtrl"); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + //dock->setFeatures(QDockWidget::DockWidgetFloatable); + dock->setStyleSheet(set->getDockStyle()); + dock->setMaximumWidth(245); + dock->setMinimumWidth(245); + dock->setWidget(m_hpsdrTabWidget); + dockWidgetList.append(dock); + + addDockWidget(Qt::RightDockWidgetArea, dock); + dock->hide(); + + // chirp mode control widget + dock = new QDockWidget(tr("Chirp Ctrl"), this); + dock->setObjectName("ChirpCtrl"); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + dock->setStyleSheet(set->getDockStyle()); + dock->setMaximumWidth(245); + dock->setMinimumWidth(245); + dock->setWidget(m_chirpWidget); + dockWidgetList.append(dock); + + addDockWidget(Qt::RightDockWidgetArea, dock); + dock->hide(); + + // display control widget + dock = new QDockWidget(tr("Display Ctrl"), this); + dock->setObjectName("DisplayCtrl"); + dock->setAllowedAreas(Qt::LeftDockWidgetArea | Qt::RightDockWidgetArea); + dock->setFeatures(QDockWidget::NoDockWidgetFeatures); + dock->setStyleSheet(set->getDockStyle()); + dock->setMaximumWidth(245); + dock->setMinimumWidth(245); + dock->setWidget(m_displayTabWidget); + dockWidgetList.append(dock); + + addDockWidget(Qt::RightDockWidgetArea, dock); + dock->hide(); + + // receiver and wideband panel docks; + // set receiver 0 as the main receiver + centralwidget->setCentralWidget(rxWidgetList.at(0)); + + // wideband panel dock window + widebandDock = new QDockWidget(tr("Wideband"), this); + widebandDock->setObjectName("Wideband"); + widebandDock->setAllowedAreas(Qt::TopDockWidgetArea | Qt::BottomDockWidgetArea); + widebandDock->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetMovable); + widebandDock->setStyleSheet(set->getDockStyle()); + widebandDock->setWidget(m_wbDisplay); + + centralwidget->addDockWidget(Qt::TopDockWidgetArea, widebandDock); + widebandDock->hide(); + + CHECKED_CONNECT( + widebandDock, + SIGNAL(visibilityChanged(bool)), + this, + SLOT(widebandVisibilityChanged(bool))); + + // receiver dock windows + for (int i = 1; i < MAX_RECEIVERS; i++) { + + QString str = "Receiver "; + QString num = QString::number(i+1); + str.append(num); + dock = new QDockWidget(str, this); + widebandDock->setObjectName(str); + dock->setStyleSheet(set->getDockStyle()); + dock->setWidget(rxWidgetList.at(i)); + rxDockWidgetList.append(dock); + + centralwidget->addDockWidget(Qt::BottomDockWidgetArea, dock); + dock->hide(); + + rxVolumeList << 0.0f; + //viewMenu->addAction(dock->toggleViewAction()); + } + + // the outline of the receiver panels + for (int i = 0; i < (int)(MAX_RECEIVERS-1)/2; i++) { + + centralwidget->splitDockWidget(rxDockWidgetList.at(i), rxDockWidgetList.at(i+3), Qt::Vertical); + } + + //viewMenu->addAction(dock->toggleViewAction()); +} + +/*! + \brief create the receiver panels. +*/ +void MainWindow::createReceiverPanels(int rx) { + + rxWidgetList.clear(); + + for (int i = 0; i < rx; i++) { + + QGLReceiverPanel* rxPanel = new QGLReceiverPanel(this, i); + rxWidgetList.append(rxPanel); + } +} + +/*! + \brief create the status tool bar. +*/ +void MainWindow::createStatusToolBar() { + + QDateTime dateTime = QDateTime::currentDateTime(); + m_dateTimeString = dateTime.toString(); + m_dateTimeString.append(" (loc)"); + + m_cpuLoadString = "CPU load: "; + m_cpuLoadLabel = new QLabel(m_cpuLoadString, this); + m_cpuLoadLabel->setStyleSheet(set->getLabelStyle()); + + m_dateTimeLabel = new QLabel(m_dateTimeString, this); + m_dateTimeLabel->setStyleSheet(set->getLabelStyle()); + + statusBar()->setStyleSheet(set->getStatusbarStyle()); + statusBar()->addPermanentWidget(m_cpuLoadLabel); + statusBar()->insertPermanentWidget(1, m_dateTimeLabel, 0); +} + +/*! + \brief update the staus tool bar content with + the CPU load and the local date & time. +*/ +void MainWindow::updateStatusBar(short load) { + + QString str = "CPU load: %1 % \t"; + m_cpuLoadLabel->setText(str.arg(load)); + + QDateTime dateTime = QDateTime::currentDateTime(); + m_dateTimeString = dateTime.toString(); + m_dateTimeString.append(" (loc)"); + m_dateTimeLabel->setText(m_dateTimeString); + + statusBar()->update(); +} + +/*! + \brief create the display panel tool bar. +*/ +void MainWindow::createDisplayPanelToolBar() { + + displayPanelToolBar = new QToolBar(tr("Display Panel"), this); + displayPanelToolBar->setObjectName("DisplayPanel"); + displayPanelToolBar->setAllowedAreas(Qt::TopToolBarArea); + displayPanelToolBar->setMovable(false); + displayPanelToolBar->setStyleSheet(set->getDisplayToolbarStyle()); + + // The display panel has the displayPanelToolBar as parent. + m_oglDisplayPanel = new OGLDisplayPanel(displayPanelToolBar); + + displayPanelToolBar->addWidget(m_oglDisplayPanel); + + // add displayPanelToolBar to the main window. + addToolBar(displayPanelToolBar); + addToolBarBreak(Qt::TopToolBarArea); +} + +/*! + \brief create the main button tool bar. +*/ +void MainWindow::createMainBtnToolBar() { + + mainBtnToolBar = new QToolBar(tr("Main Buttons"), this); + mainBtnToolBar->setObjectName("MainButtons"); + //mainBtnToolBar->setAllowedAreas(Qt::TopToolBarArea); + mainBtnToolBar->setMovable(false); + mainBtnToolBar->setStyleSheet(set->getMainBtnToolbarStyle()); + + m_buttonWidget = new QWidget(this); + + QColor btnCol = QColor(230, 230, 230); +// QHBoxLayout *firstBtnLayout = new QHBoxLayout; +// firstBtnLayout->setSpacing(0); +// firstBtnLayout->setMargin(0); + + startBtn = new AeroButton("Start", this); + startBtn->setRoundness(10); + startBtn->setFont(m_fonts.normalFont); + startBtn->setTextColor(btnCol); + startBtn->setFixedSize(btn_width1, btn_height1); + + CHECKED_CONNECT( + startBtn, + SIGNAL(clicked()), + this, + SLOT(startButtonClickedEvent())); + + /*ctrlDisplayBtn = new AeroButton("Radio", this); + ctrlDisplayBtn->setRoundness(10); + ctrlDisplayBtn->setFixedSize(btn_width1, btn_height1); + ctrlDisplayBtn->setBtnState(AeroButton::ON); + + CHECKED_CONNECT( + ctrlDisplayBtn, + SIGNAL(clicked()), + this, + SLOT(ctrlDisplayBtnClickedEvent()));*/ + + rxCtrlBtn = new AeroButton("Radio Ctrl", this); + rxCtrlBtn->setRoundness(10); + rxCtrlBtn->setFont(m_fonts.normalFont); + rxCtrlBtn->setTextColor(btnCol); + rxCtrlBtn->setFixedSize(btn_width1, btn_height1); + mainBtnList.append(rxCtrlBtn); + + //if (m_serverMode == QSDR::ExternalDSP) + // rxCtrlBtn->setEnabled(false); + + CHECKED_CONNECT( + rxCtrlBtn, + SIGNAL(clicked()), + this, + SLOT(widgetBtnClickedEvent())); + + serverBtn = new AeroButton("Server", this); + serverBtn->setRoundness(10); + serverBtn->setFont(m_fonts.normalFont); + serverBtn->setTextColor(btnCol); + serverBtn->setFixedSize(btn_width1, btn_height1); + mainBtnList.append(serverBtn); + + CHECKED_CONNECT( + serverBtn, + SIGNAL(clicked()), + this, + SLOT(widgetBtnClickedEvent())); + + hpsdrBtn = new AeroButton("HPSDR", this); + hpsdrBtn->setRoundness(10); + hpsdrBtn->setFont(m_fonts.normalFont); + hpsdrBtn->setTextColor(btnCol); + hpsdrBtn->setFixedSize(btn_width1, btn_height1); + mainBtnList.append(hpsdrBtn); + + CHECKED_CONNECT( + hpsdrBtn, + SIGNAL(clicked()), + this, + SLOT(widgetBtnClickedEvent())); + + chirpBtn = new AeroButton("Chirp", this); + chirpBtn->setRoundness(10); + chirpBtn->setFont(m_fonts.normalFont); + chirpBtn->setTextColor(btnCol); + chirpBtn->setFixedSize(btn_width1, btn_height1); + mainBtnList.append(chirpBtn); + + if (m_serverMode != QSDR::ChirpWSPR) + chirpBtn->setEnabled(false); + + CHECKED_CONNECT( + chirpBtn, + SIGNAL(clicked()), + this, + SLOT(widgetBtnClickedEvent())); + + wideBandBtn = new AeroButton("Wideband", this); + wideBandBtn->setRoundness(10); + wideBandBtn->setFont(m_fonts.normalFont); + wideBandBtn->setTextColor(btnCol); + wideBandBtn->setFixedSize(btn_width1, btn_height1); + wideBandBtn->setEnabled(false); + //mainBtnList.append(wideBandBtn); + + if (m_serverMode == QSDR::ChirpWSPR) + wideBandBtn->setEnabled(false); + + CHECKED_CONNECT( + wideBandBtn, + SIGNAL(clicked()), + this, + SLOT(wideBandBtnClickedEvent())); + + //openclBtn = new AeroButton("OpenCL", this); + //openclBtn->setRoundness(10); + //openclBtn->setFixedSize(btn_width1, btn_height1); + //mainBtnList.append(openclBtn); + + //if (m_cudaPresence) { + // + // mainBtnList.append(cudaBtn); + + // CHECKED_CONNECT( + // cudaBtn, + // SIGNAL(clicked()), + // this, + // SLOT(widgetBtnClickedEvent())); + + // //if (set->getCudaDevices() == 0) + //} + //else { + + // cudaBtn->setEnabled(false); + //} + + //if (set->getCudaDevices() == 0) { + + // cudaGraphBtn->setEnabled(false); + + // /*CHECKED_CONNECT( + // cudaGraphBtn, + // SIGNAL(clicked()), + // this, + // SLOT(widgetBtnClickedEvent())); + // CHECKED_CONNECT(cudaTestBtn, + // SIGNAL(clicked()), + // this, + // SLOT(cudaTestBtnClickedEvent()));*/ + //} + + displayBtn = new AeroButton("Display", this); + displayBtn->setRoundness(10); + displayBtn->setFont(m_fonts.normalFont); + displayBtn->setTextColor(btnCol); + displayBtn->setFixedSize(btn_width1, btn_height1); + mainBtnList.append(displayBtn); + + CHECKED_CONNECT( + displayBtn, + SIGNAL(clicked()), + this, + SLOT(widgetBtnClickedEvent())); + + QColor col = QColor(90, 90, 90); + + nullBtn = new AeroButton(this); + nullBtn->setRoundness(0); + nullBtn->setFixedHeight(btn_height1); + nullBtn->setHighlight(col); + nullBtn->setEnabled(false); + + // +Rx disabled for now, requires addReceiver to be implemented + plusRxBtn = new AeroButton("+Rx", this); + plusRxBtn->setRoundness(10); + plusRxBtn->setFont(m_fonts.normalFont); + plusRxBtn->setTextColor(btnCol); + plusRxBtn->setFixedSize(btn_width1, btn_height1); + plusRxBtn->setEnabled(false); + + CHECKED_CONNECT( + plusRxBtn, + SIGNAL(clicked()), + this, + SLOT(addReceiver())); + + viewBtn = new AeroButton("View Rx", this); + viewBtn->setRoundness(10); + viewBtn->setFont(m_fonts.normalFont); + viewBtn->setTextColor(btnCol); + viewBtn->setFixedSize(btn_width1, btn_height1); + + modeBtn = new AeroButton("Mode", this); + modeBtn->setRoundness(10); + modeBtn->setFont(m_fonts.normalFont); + modeBtn->setTextColor(btnCol); + modeBtn->setFixedSize(btn_width1, btn_height1); + + quitBtn = new AeroButton("Quit", this); + quitBtn->setRoundness(10); + quitBtn->setFont(m_fonts.normalFont); + quitBtn->setTextColor(btnCol); + quitBtn->setFixedSize(btn_width3, btn_height1); + + CHECKED_CONNECT( + quitBtn, + SIGNAL(clicked()), + this, + SLOT(closeMainWindow())); + +// firstBtnLayout->addWidget(startBtn); +// //firstBtnLayout->addWidget(serverLogBtn); +// firstBtnLayout->addWidget(rxCtrlBtn); +// firstBtnLayout->addWidget(serverBtn); +// firstBtnLayout->addWidget(hpsdrBtn); +// firstBtnLayout->addWidget(chirpBtn); +// firstBtnLayout->addWidget(wideBandBtn); +// //firstBtnLayout->addWidget(openclBtn); +// firstBtnLayout->addWidget(displayBtn); +// firstBtnLayout->addWidget(nullBtn); +// //firstBtnLayout->addStretch(); +// firstBtnLayout->addWidget(viewBtn); +// firstBtnLayout->addWidget(modeBtn); +// firstBtnLayout->addWidget(quitBtn); + +// QHBoxLayout *firstBtnLayout = new QHBoxLayout; +// firstBtnLayout->setSpacing(0); +// firstBtnLayout->setMargin(0); +// +// firstBtnLayout->addWidget(startBtn); +// //firstBtnLayout->addWidget(serverLogBtn); +// firstBtnLayout->addWidget(rxCtrlBtn); +// firstBtnLayout->addWidget(serverBtn); +// firstBtnLayout->addWidget(hpsdrBtn); +// firstBtnLayout->addWidget(chirpBtn); +// firstBtnLayout->addWidget(wideBandBtn); +// //firstBtnLayout->addWidget(openclBtn); +// firstBtnLayout->addWidget(displayBtn); +// firstBtnLayout->addWidget(nullBtn); +// //firstBtnLayout->addStretch(); +// firstBtnLayout->addWidget(viewBtn); +// firstBtnLayout->addWidget(modeBtn); +// firstBtnLayout->addWidget(quitBtn); + +// QHBoxLayout *secondBtnLayout = new QHBoxLayout; +// secondBtnLayout->setSpacing(0); +// secondBtnLayout->setMargin(0); + + int fontMaxWidth = m_fonts.smallFontMetrics->boundingRect("100 % ").width(); + int vol = (int)(set->getMainVolume(0) * 100); + + m_volumeSlider = new QSlider(Qt::Horizontal, this); + m_volumeSlider->setTickPosition(QSlider::NoTicks); + m_volumeSlider->setFixedSize(100, 14); + m_volumeSlider->setSingleStep(1); + m_volumeSlider->setRange(0, 100); + m_volumeSlider->setValue(vol); + m_volumeSlider->setStyleSheet(set->getVolSliderStyle()); + + CHECKED_CONNECT( + m_volumeSlider, + SIGNAL(valueChanged(int)), + this, + SLOT(setMainVolume(int))); + + m_volumeLabel = new QLabel("Vol:", this); + m_volumeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_volumeLabel->setStyleSheet(set->getLabelStyle()); + + QString str = "%1 %"; + m_volLevelLabel = new QLabel(str.arg(vol, 2, 10, QLatin1Char(' ')), this); + m_volLevelLabel->setFont(m_fonts.smallFont); + m_volLevelLabel->setFixedSize(fontMaxWidth, 14); + m_volLevelLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_volLevelLabel->setStyleSheet(set->getSliderLabelStyle()); + + + int agcMaxGain = (int) set->getAGCMaximumGain_dB(0); + //MAIN_DEBUG << "agcMaximumGain = " << agcMaxGain; + m_agcGainSlider = new QSlider(Qt::Horizontal, this); + m_agcGainSlider->setTickPosition(QSlider::NoTicks); + m_agcGainSlider->setFixedSize(100, 14); + m_agcGainSlider->setSingleStep(1); + m_agcGainSlider->setRange(-20, 120); + m_agcGainSlider->setValue(agcMaxGain); + m_agcGainSlider->setStyleSheet(set->getVolSliderStyle()); + + CHECKED_CONNECT( + m_agcGainSlider, + SIGNAL(valueChanged(int)), + this, + SLOT(setAGCGain(int))); + + m_agcGainLabel = new QLabel("", this); + m_agcGainLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_agcGainLabel->setStyleSheet(set->getLabelStyle()); + if(m_agcMode == (AGCMode) agcOFF) + m_agcGainLabel->setText("AGC-F:"); + else + m_agcGainLabel->setText("AGC-G:"); + + fontMaxWidth = m_fonts.smallFontMetrics->boundingRect(" 120 dB").width(); + str = " %1 dB"; + m_agcGainLevelLabel = new QLabel(str.arg(agcMaxGain + 0, 2, 10, QLatin1Char(' ')), this); + m_agcGainLevelLabel->setFont(m_fonts.smallFont); + m_agcGainLevelLabel->setFixedSize(fontMaxWidth, 14); + m_agcGainLevelLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + m_agcGainLevelLabel->setStyleSheet(set->getSliderLabelStyle()); + + + moxBtn = new AeroButton("MOX", this); + moxBtn->setRoundness(10); + moxBtn->setFont(m_fonts.normalFont); + moxBtn->setTextColor(btnCol); + moxBtn->setFixedSize(btn_width1, btn_height3); + moxBtn->setEnabled(false); + col = QColor(200, 100, 100); + moxBtn->setColor(col); + col = QColor(200, 200, 100); + moxBtn->setHighlight(col); + col = QColor(250, 100, 100); + moxBtn->setColorOn(col); + moxBtn->setBtnState(AeroButton::OFF); + + tunBtn = new AeroButton("Tune", this); + tunBtn->setRoundness(10); + tunBtn->setFont(m_fonts.normalFont); + tunBtn->setTextColor(btnCol); + tunBtn->setFixedSize(btn_width1, btn_height3); + tunBtn->setEnabled(false); + col = QColor(200, 100, 100); + tunBtn->setColor(col); + col = QColor(200, 200, 100); + tunBtn->setHighlight(col); + col = QColor(250, 100, 100); + tunBtn->setColorOn(col); + tunBtn->setBtnState(AeroButton::OFF); + + if (set->getPenelopePresence() || set->getPennyLanePresence() || (m_hwInterface == QSDR::Hermes)) { + + moxBtn->setEnabled(true); + tunBtn->setEnabled(true); + } + else { + + moxBtn->setEnabled(false); + tunBtn->setEnabled(false); + } + + alexBtn = new AeroButton("Alex Auto", this); + alexBtn->setRoundness(10); + alexBtn->setFont(m_fonts.normalFont); + alexBtn->setTextColor(btnCol); + alexBtn->setFixedSize(btn_width1, btn_height3); + alexBtn->setBtnState(AeroButton::ON); + if (set->getAlexPresence()) + alexBtn->setEnabled(true); + else + alexBtn->setEnabled(false); + + CHECKED_CONNECT( + alexBtn, + SIGNAL(clicked()), + this, + SLOT(alexBtnClickedEvent())); + + attenuatorBtn = new AeroButton("Attenuator", this); + attenuatorBtn->setRoundness(10); + attenuatorBtn->setFont(m_fonts.normalFont); + attenuatorBtn->setTextColor(btnCol); + attenuatorBtn->setFixedSize(btn_width1, btn_height1); + + muteBtn = new AeroButton("Mute", this); + muteBtn->setRoundness(10); + muteBtn->setFont(m_fonts.normalFont); + muteBtn->setTextColor(btnCol); + muteBtn->setFixedSize(btn_width3, btn_height1); + + CHECKED_CONNECT( + muteBtn, + SIGNAL(clicked()), + this, + SLOT(muteBtnClickedEvent())); + +// lastFreqBtn = new AeroButton(" ", this); +// lastFreqBtn->setRoundness(10); +// lastFreqBtn->setFixedSize(btn_width1, btn_height3); +// lastFreqBtn->setBtnState(AeroButton::OFF); +// +// CHECKED_CONNECT( +// lastFreqBtn, +// SIGNAL(clicked()), +// this, +// SLOT(getLastFrequency())); + + QHBoxLayout *firstBtnLayout = new QHBoxLayout; + firstBtnLayout->setSpacing(0); + firstBtnLayout->setMargin(0); + + firstBtnLayout->addWidget(startBtn); + //firstBtnLayout->addWidget(serverLogBtn); + firstBtnLayout->addWidget(rxCtrlBtn); + firstBtnLayout->addWidget(serverBtn); + firstBtnLayout->addWidget(hpsdrBtn); + firstBtnLayout->addWidget(chirpBtn); + firstBtnLayout->addWidget(wideBandBtn); + //firstBtnLayout->addWidget(openclBtn); + firstBtnLayout->addWidget(displayBtn); + firstBtnLayout->addWidget(nullBtn); + firstBtnLayout->addWidget(plusRxBtn); + firstBtnLayout->addWidget(viewBtn); + firstBtnLayout->addWidget(modeBtn); + firstBtnLayout->addWidget(quitBtn); + + + QHBoxLayout* secondBtnLayout = new QHBoxLayout; + secondBtnLayout->setSpacing(0); + secondBtnLayout->setMargin(0); + + secondBtnLayout->addWidget(moxBtn); + secondBtnLayout->addWidget(tunBtn); + secondBtnLayout->addStretch(); + secondBtnLayout->addWidget(alexBtn); + secondBtnLayout->addWidget(attenuatorBtn); + secondBtnLayout->addSpacing(5); + secondBtnLayout->addWidget(m_agcGainLabel); + secondBtnLayout->addWidget(m_agcGainSlider); + secondBtnLayout->addWidget(m_agcGainLevelLabel); + secondBtnLayout->addSpacing(10); + secondBtnLayout->addWidget(m_volumeLabel); + secondBtnLayout->addWidget(m_volumeSlider); + secondBtnLayout->addWidget(m_volLevelLabel); + secondBtnLayout->addSpacing(2); + secondBtnLayout->addWidget(muteBtn); + //secondBtnLayout->addWidget(lastFreqBtn); + + /*QHBoxLayout *thirdBtnLayout = new QHBoxLayout; + thirdBtnLayout->setSpacing(0); + thirdBtnLayout->setMargin(0); + + thirdBtnLayout->addWidget(lockPanBtn); + thirdBtnLayout->addStretch();*/ + + QVBoxLayout* btnLayout = new QVBoxLayout; + btnLayout->setSpacing(0); + btnLayout->setMargin(0); + btnLayout->addLayout(firstBtnLayout); + btnLayout->addLayout(secondBtnLayout); + //btnLayout->addLayout(thirdBtnLayout); + + m_buttonWidget->setLayout(btnLayout); + + mainBtnToolBar->addWidget(m_buttonWidget); + + addToolBar(mainBtnToolBar); +} + +/*! + \brief create the Mode menu. +*/ +void MainWindow::createModeMenu() { + + modeMenu = new QMenu(this); + modeMenu->setStyleSheet(set->getMenuStyle()); + modeBtn->setMenu(modeMenu); + + modeActionGroup = new QActionGroup(this); + modeActionGroup->setExclusive(true); + +// noServerModeAction = modeActionGroup->addAction(tr("QtDSP")); +// noServerModeAction->setCheckable(true); +// noServerModeAction->setChecked(m_serverMode == QSDR::QtDSP); + + sdrModeAction = modeActionGroup->addAction(tr("SDR")); + sdrModeAction->setCheckable(true); + sdrModeAction->setChecked(m_serverMode == QSDR::SDRMode); + + chirpWSPRAction = modeActionGroup->addAction(tr("ChirpWSPR")); + chirpWSPRAction->setCheckable(false); + chirpWSPRAction->setChecked(m_serverMode == QSDR::ChirpWSPR); + + modeMenu->addActions(modeActionGroup->actions()); + + if (sdrModeAction->isCheckable()) { + + CHECKED_CONNECT( + sdrModeAction, + SIGNAL(triggered(bool)), + this, + SLOT(setSDRMode(bool))); + } + + if (chirpWSPRAction->isCheckable()) { + + CHECKED_CONNECT( + chirpWSPRAction, + SIGNAL(triggered(bool)), + this, + SLOT(setChirpWSPRMode(bool))); + } + +} + +/*! + \brief create the receiver's dock windows view menu. +*/ +void MainWindow::createViewMenu() { + + viewMenu = new QMenu(this); + viewMenu->setStyleSheet(set->getMenuStyle()); + viewBtn->setMenu(viewMenu); +} + +/*! + \brief create the attenuator menu. +*/ +void MainWindow::createAttenuatorMenu() { + + attenuatorMenu = new QMenu(this); + attenuatorMenu->setStyleSheet(set->getMenuStyle()); + attenuatorBtn->setMenu(attenuatorMenu); + + mercuryAttn_0dBAction = attenuatorMenu->addAction(tr("Mercury Attn 0 dB")); + mercuryAttn_0dBAction->setCheckable(true); + mercuryAttnActionList.append(mercuryAttn_0dBAction); + + mercuryAttn_20dBAction = attenuatorMenu->addAction(tr("Mercury Attn -20 dB")); + mercuryAttn_20dBAction->setCheckable(true); + mercuryAttnActionList.append(mercuryAttn_20dBAction); + + attenuatorMenu->addSeparator(); + alexAttn_0dBAction = attenuatorMenu->addAction(tr("Alex Attn 0 dB")); + alexAttn_0dBAction->setCheckable(true); + alexAttnActionList.append(alexAttn_0dBAction); + + alexAttn_10dBAction = attenuatorMenu->addAction(tr("Alex Attn -10 dB")); + alexAttn_10dBAction->setCheckable(true); + alexAttnActionList.append(alexAttn_10dBAction); + + alexAttn_20dBAction = attenuatorMenu->addAction(tr("Alex Attn -20 dB")); + alexAttn_20dBAction->setCheckable(true); + alexAttnActionList.append(alexAttn_20dBAction); + + alexAttn_30dBAction = attenuatorMenu->addAction(tr("Alex Attn -30 dB")); + alexAttn_30dBAction->setCheckable(true); + alexAttnActionList.append(alexAttn_30dBAction); + + if (mercuryAttn_0dBAction->isCheckable()) { + + CHECKED_CONNECT( + mercuryAttn_0dBAction, + SIGNAL(triggered(bool)), + this, + SLOT(setAttenuator())); + } + + if (mercuryAttn_20dBAction->isCheckable()) { + + CHECKED_CONNECT( + mercuryAttn_20dBAction, + SIGNAL(triggered(bool)), + this, + SLOT(setAttenuator())); + } + + if (alexAttn_0dBAction->isCheckable()) { + + CHECKED_CONNECT( + alexAttn_0dBAction, + SIGNAL(triggered(bool)), + this, + SLOT(setAttenuator())); + } + + if (alexAttn_10dBAction->isCheckable()) { + + CHECKED_CONNECT( + alexAttn_10dBAction, + SIGNAL(triggered(bool)), + this, + SLOT(setAttenuator())); + } + + if (alexAttn_20dBAction->isCheckable()) { + + CHECKED_CONNECT( + alexAttn_20dBAction, + SIGNAL(triggered(bool)), + this, + SLOT(setAttenuator())); + } + + if (alexAttn_30dBAction->isCheckable()) { + + CHECKED_CONNECT( + alexAttn_30dBAction, + SIGNAL(triggered(bool)), + this, + SLOT(setAttenuator())); + } +} + +//******************************************************************************* + +/*! + \brief the master switch functionality. + - starts/stops the data engine. + - starts/stops the server if in \a QSDR::ExternalDSP mode. +*/ +void MainWindow::masterSwitchChanged( + QObject *sender, /*!<[in] the sender of the signal. */ + bool power /*!<[in] power on or off*/ +) { + Q_UNUSED(sender) + + if (power) { + + if (m_dataEngine->initDataEngine()) { // start data engine + + //if (m_serverMode == QSDR::ExternalDSP && !m_hpsdrServer->startServer()) + // m_hpsdrServer->stopServer(); + return; + } + else { + + set->setMainPower(this, false); + startButtonClickedEvent(); + return; + } + } + else { + + m_dataEngine->stop(); + + //if (m_serverMode == QSDR::ExternalDSP) + // m_hpsdrServer->stopServer(); + set->setMainPower(this, false); + } +} + +/*! + \brief set the system state according to + - \a QSDR::_ServerMode, + - \a QSDR::_HWInterfaceMode, + - \a QSDR::_DataEngineState. +*/ +void MainWindow::systemStateChanged( + QObject *sender, /*!<[in] the sender of the signal. */ + QSDR::_Error err, /*!<[in] error state. */ + QSDR::_HWInterfaceMode hwmode, /*!<[in] HPSDR interface (Metis, Hermes, none). */ + QSDR::_ServerMode mode, /*!<[in] server mode. */ + QSDR::_DataEngineState state /*!<[in] data engine state. */ +) { + Q_UNUSED (sender) + Q_UNUSED (err) + + //if (sender == this) return; + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; + + //if (!modeBtn->isEnabled() && m_dataEngineState == QSDR::DataEngineDown) + // modeBtn->setEnabled(true); + modeBtn->setEnabled(m_dataEngineState == QSDR::DataEngineDown); + moxBtn->setEnabled(m_hwInterface == QSDR::Hermes); + tunBtn->setEnabled(m_hwInterface == QSDR::Hermes); + + /* + if (state == QSDR::DataEngineUp) { + + m_dataEngineState = QSDR::DataEngineUp; + modeBtn->setEnabled(false); + } + else + if (state == QSDR::DataEngineDown) { + + m_dataEngineState = QSDR::DataEngineDown; + modeBtn->setEnabled(true); + //setCurrentReceiver(0); + } + */ +} + +void MainWindow::setSystemState( + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + m_dataEngine->io.networkIOMutex.lock(); + set->setSystemState(this, err, hwmode, mode, state); + m_dataEngine->io.networkIOMutex.unlock(); +} + +/*! + \brief show a temporary message on the status bar. +*/ +void MainWindow::showStatusBarMessage(const QString &msg, int time) { + + statusBar()->showMessage(msg, time); +} + +/*! + \brief clear the temporary status message +*/ +void MainWindow::clearStatusBarMessage() { + + statusBar()->clearMessage(); +} + +/*! + \brief closes the application and shut down all engines. +*/ +void MainWindow::closeMainWindow() { + + if (set->getMainPower()) + startButtonClickedEvent(); + close(); +} + +/*! + \brief maximizes/minimizes the main window. +*/ +void MainWindow::maximizeMainWindow() { + + if (isMaximized()) { + + //m_titlebar->maxBtn->setIcon(QIcon(QString::fromUtf8(":/img/maximize_high.png")));//, QSize(), QIcon::Normal, QIcon::Off); + //m_titlebar->maxBtn->update(); + showNormal(); + } + else { + + //m_titlebar->maxBtn->setIcon(QIcon(QString::fromUtf8(":/img/minimize_high.png")));//, QSize(), QIcon::Normal, QIcon::Off); + //m_titlebar->maxBtn->update(); + showMaximized(); + } +} + +/*! + \brief maximizes/minimizes the main window and hide/show titlebar. +*/ +void MainWindow::setMainWindowGeometry() { + + if (isMaximized()) { + + setWindowFlags(Qt::Widget); + //this->move(m_oldPosition); + this->setGeometry(m_oldPosition.x(), m_oldPosition.y(), m_oldSize.width(), m_oldSize.height()); + showNormal(); + } + else { + + setWindowFlags(Qt::FramelessWindowHint); + + m_oldSize = this->size(); + m_oldPosition = this->pos(); + QPoint pos = m_oldPosition; + + if (pos.x() < 0) + pos.setX(0); + if (pos.y() < 0) + pos.setY(0); + + this->move(pos); + this->show(); + showMaximized(); + } +} + +/*! + \brief sets full screen operation. +*/ +void MainWindow::setFullScreen() { + + if (m_fullScreen) + this->showNormal(); + else + this->showFullScreen(); +} + +void MainWindow::showRadioPopup(bool value) { + + Q_UNUSED (value) + + //m_radioPopupWidget->showPopupWidget(this, QCursor::pos()); +} + +/*! + \brief updates entries from the ini-file. +*/ +void MainWindow::updateFromSettings() { + +} + +/*! + \brief implements the Radio-display button functionality which opens/closes the radio control widget. +*/ +void MainWindow::ctrlDisplayBtnClickedEvent() { + + if (m_oglDisplayPanel->isVisible()) { + + m_oglDisplayPanel->setVisible(false); + ctrlDisplayBtn->setBtnState(AeroButton::OFF); + } + else { + + m_oglDisplayPanel->setVisible(true); + ctrlDisplayBtn->setBtnState(AeroButton::ON); + } +} + +/*! + \brief implements various Button functionalities. +*/ +void MainWindow::widgetBtnClickedEvent() { + + AeroButton *button = qobject_cast(sender()); + int on = mainBtnList.indexOf(button); + + //foreach(QWidget *widget, widgetList) { + foreach(QDockWidget *dockWidget, dockWidgetList) { + + //int off = widgetList.indexOf(widget); + int off = dockWidgetList.indexOf(dockWidget); + + if (dockWidget->isVisible()) { + + dockWidget->hide(); + mainBtnList.at(off)->setBtnState(AeroButton::OFF); + mainBtnList.at(off)->update(); + } + else if (on == off) { + + button->setBtnState(AeroButton::ON); + button->update(); + dockWidgetList.at(on)->show(); + } + } +} + +/*! + \brief implements the Start/Stop functionality of the Start/Stop button. +*/ +void MainWindow::startButtonClickedEvent() { + + if (startBtn->btnState() == AeroButton::OFF) { + + startBtn->setBtnState(AeroButton::ON); + + QColor col = QColor(180, 0, 0); + startBtn->setColorOn(col); + + col = QColor(250, 0, 0); + startBtn->setHighlight(col); + startBtn->setText("Stop"); + set->setMainPower(this, true); + } + else if (startBtn->btnState() == AeroButton::ON) { + + startBtn->setBtnState(AeroButton::OFF); + + QColor col = QColor(0x91, 0xeb, 0xff); + startBtn->setHighlight(col); + startBtn->setText("Start"); + set->saveSettings(); + set->setMainPower(this, false); + + if (muteBtn->btnState() == AeroButton::ON) { + + muteBtn->setBtnState(AeroButton::OFF); + muteBtn->update(); + + m_volumeSlider->setEnabled(true); + for (int i = 0; i < set->getNumberOfReceivers(); i++) + set->setMainVolume(this, i, rxVolumeList.at(i)); + } + } +} + +/*! + \brief implements the Show/Hide functionality of the wide band data widget. +*/ +void MainWindow::wideBandBtnClickedEvent() { + + if (wideBandBtn->btnState() == AeroButton::OFF) { + + wideBandBtn->setBtnState(AeroButton::ON); + set->setWidebandStatus(this, true); + widebandDock->show(); + //showMessage("[server]: wide band data on."); + } + else if (wideBandBtn->btnState() == AeroButton::ON) { + + wideBandBtn->setBtnState(AeroButton::OFF); + set->setWidebandStatus(this, false); + widebandDock->hide(); + //showMessage("[server]: wide band data off."); + } +} + +void MainWindow::widebandVisibilityChanged(bool value) { + + if (value) + wideBandBtn->setBtnState(AeroButton::ON); + else + wideBandBtn->setBtnState(AeroButton::OFF); + + wideBandBtn->update(); +} + +void MainWindow::alexBtnClickedEvent() { + + if (alexBtn->btnState() == AeroButton::OFF) { + + alexBtn->setBtnState(AeroButton::ON); + alexBtn->setText("Alex Auto"); + + //m_alexConfiguration[0].value = false; + m_alexConfig &= 0xFFFE; + + set->setAlexToManual(this, false); + } + else if (alexBtn->btnState() == AeroButton::ON) { + + alexBtn->setBtnState(AeroButton::OFF); + alexBtn->setText("Alex Man"); + + //m_alexConfiguration[0].value = true; + m_alexConfig |= 0x01; + + set->setAlexToManual(this, true); + } + //set->setAlexConfiguration(this, m_alexConfiguration); +} + +void MainWindow::alexStateChanged(HamBand band, const QList &states) { + + Q_UNUSED(band) + + m_currentHamBand = set->getCurrentHamBand(0); + m_alexStates[m_currentHamBand] = states.at(m_currentHamBand); + m_alexAttnState = 0x03 & (m_alexStates[m_currentHamBand] >> 7); + + setAttenuatorButton(); +} + +void MainWindow::alexConfigurationChanged(quint16 conf) { + + if (conf & 0x01) { + + alexBtn->setBtnState(AeroButton::OFF); + alexBtn->setText("Alex Man"); + } + else { + + alexBtn->setBtnState(AeroButton::ON); + alexBtn->setText("Alex Auto"); + } + + alexBtn->update(); +} + +void MainWindow::alexPresenceChanged(bool value) { + + if (value) { + + //if (m_alexConfiguration[0].value) + if (m_alexConfig & 0x01) + alexBtn->setText(tr("Alex Man")); + else + alexBtn->setText(tr("Alex Auto")); + } + else + alexBtn->setText(tr("Alex")); + + alexBtn->setEnabled(value); + + alexAttn_0dBAction->setCheckable(value); + alexAttn_10dBAction->setCheckable(value); + alexAttn_20dBAction->setCheckable(value); + alexAttn_30dBAction->setCheckable(value); + + alexBtn->update(); +} + +void MainWindow::addReceiver() { +} + +/*! + \brief tune to last frequency. +*/ +void MainWindow::getLastFrequency() { +} + +/*! + \brief updates the main window title. +*/ +void MainWindow::updateTitle() { + + setWindowTitle( + QApplication::applicationName() + " " + \ + QApplication::applicationVersion() + " " + \ + set->getCallsign()); +} + +/*! + \brief show widget event. +*/ +void MainWindow::showWidgetEvent( + QObject *sender /*!<[in] the sender of the event. */ +) { + if (!sender) return; +} + +/*! + \brief hide widget event. +*/ +void MainWindow::closeWidgetEvent( + QObject *sender /*!<[in] the sender of the event. */ +) +{ + if (!sender) return; +} + +void MainWindow::setCurrentReceiver(QObject *sender, int rx) { + + Q_UNUSED(sender) + + MAIN_DEBUG << "setCurrentReceiver: " << rx; + //set->setCurrentReceiver(this, rx); + //m_dataEngine->io.currentReceiver = rx; + m_volumeSlider->setValue((int)(set->getMainVolume(rx) * 100)); + m_agcGainSlider->setValue(set->getAGCMaximumGain_dB(rx)); +} + +/*! + \brief enable the receiver buttons according to the actual number of available receivers. +*/ +void MainWindow::setNumberOfReceivers( + QObject *sender, /*!<[in] the sender of the event. */ + int value /*!<[in] the number of receivers. */ +) { + Q_UNUSED(sender) + + viewMenu->clear(); + for (int i = 0; i < value-1; i++) { + + viewMenu->addAction(rxDockWidgetList.at(i)->toggleViewAction()); + if (!rxDockWidgetList.at(i)->isVisible()) + rxDockWidgetList.at(i)->show(); + } + + for (int i = value-1; i < MAX_RECEIVERS-1; i++) { + + if (rxDockWidgetList.at(i)->isVisible()) + rxDockWidgetList.at(i)->hide(); + } +} + +/*! + \brief set the main volume. +*/ +void MainWindow::setMainVolume(int value) { + + if (value < 0 ) value = 0; + if (value > 100 ) value = 100; + + QString str = "%1 %"; + m_volLevelLabel->setText(str.arg(value, 2, 10, QLatin1Char(' '))); + + set->setMainVolume(this, set->getCurrentReceiver(), value / 100.0f); +} + +/*! + \brief mute Volume. +*/ +void MainWindow::muteBtnClickedEvent() { + + int rcvr = set->getNumberOfReceivers(); + if (muteBtn->btnState() == AeroButton::OFF) { + + muteBtn->setBtnState(AeroButton::ON); + m_volumeSlider->setEnabled(false); + + for (int i = 0; i < rcvr; i++) { + + rxVolumeList[i] = set->getMainVolume(i); + set->setMainVolume(this, i, 0.0f); + } + } + else if (muteBtn->btnState() == AeroButton::ON) { + + muteBtn->setBtnState(AeroButton::OFF); + m_volumeSlider->setEnabled(true); + + for (int i = 0; i < rcvr; i++) { + + set->setMainVolume(this, i, rxVolumeList.at(i)); + } + } +} + +void MainWindow::setTxAllowed(QObject *sender, bool value) { + + Q_UNUSED(sender) + + if (!value) { + + moxBtn->setEnabled(false); + tunBtn->setEnabled(false); + } + else if (set->getPenelopePresence() || set->getPennyLanePresence() || (m_hwInterface == QSDR::Hermes)) { + + moxBtn->setEnabled(true); + tunBtn->setEnabled(true); + } +} + +void MainWindow::setAGCMode(QObject *sender, int rx, AGCMode mode, bool hang) { + + Q_UNUSED(sender) + Q_UNUSED(hang) + + m_agcMode = mode; + + if(m_agcMode == (AGCMode) agcOFF) { + + int gain = (int) set->getAGCFixedGain_dB(rx); + m_agcGainLabel->setText("AGC-F:"); + m_agcGainSlider->blockSignals(true); + m_agcGainSlider->setValue(gain); + m_agcGainSlider->blockSignals(false); + + QString str = " %1 dB"; + m_agcGainLevelLabel->setText(str.arg(gain, 2, 10, QLatin1Char(' '))); + } + else { + + int gain = (int) set->getAGCMaximumGain_dB(rx); + m_agcGainLabel->setText("AGC-G:"); + m_agcGainSlider->blockSignals(true); + m_agcGainSlider->setValue(gain); + m_agcGainSlider->blockSignals(false); + + QString str = " %1 dB"; + m_agcGainLevelLabel->setText(str.arg(gain, 2, 10, QLatin1Char(' '))); + } +} + +void MainWindow::setAGCGain(int value) { + + QString str = " %1 dB"; + m_agcGainLevelLabel->setText(str.arg(value + 0, 2, 10, QLatin1Char(' '))); + + int rx = set->getCurrentReceiver(); + if (m_agcMode == (AGCMode) agcOFF) + set->setAGCFixedGain_dB(this, rx, (qreal) value); + else + set->setAGCMaximumGain_dB(this, rx, (qreal) value); +} + +void MainWindow::setAGCGain(QObject *sender, int rx, qreal value) { + + Q_UNUSED(sender) + Q_UNUSED(rx) + + m_agcGainSlider->blockSignals(true); + m_agcGainSlider->setValue((int) value); + + QString str = " %1 dB"; + m_agcGainLevelLabel->setText(str.arg((int) value + 0, 2, 10, QLatin1Char(' '))); + + m_agcGainSlider->blockSignals(false); +} + +void MainWindow::setSDRMode(bool) { + + MAIN_DEBUG << "setSDRMode"; + setServerMode(QSDR::SDRMode); + + //if (m_oldSampleRate == 48000 || m_oldSampleRate == 96000 || m_oldSampleRate == 192000) + // set->setSampleRate(this, m_oldSampleRate); + + //showMessage("[server]: switched to SDR mode."); +} + +/*! + \brief set \a QSDR::_ServerMode to \a QSDR::ChirpWSPR. +*/ +void MainWindow::setChirpWSPRMode(bool value) { + + Q_UNUSED(value) + + setServerMode(QSDR::ChirpWSPR); + + m_oldSampleRate = set->getSampleRate(); + setNumberOfReceivers(this, 1); + set->setCurrentReceiver(this, 1); + set->setSampleRate(this, 48000); + //m_dataEngine->createChirpDataProcessor(); + + MAIN_DEBUG << "switched to chirp decode mode"; +} + +void MainWindow::setAttenuator() { + + QAction *action = qobject_cast(sender()); + + int mercuryPos = mercuryAttnActionList.indexOf(action); + int alexPos = alexAttnActionList.indexOf(action); + + if (mercuryPos > -1) { + + foreach(QAction *act, mercuryAttnActionList) { + + act->setChecked(false); + } + mercuryAttnActionList.at(mercuryPos)->setChecked(true); + + switch (mercuryPos) { + + case 0: + + //attenuatorBtn->setText(tr("Attn 0 dB")); + //attenuatorBtn->setBtnState(AeroButton::OFF); + + set->setMercuryAttenuator(this, 1); + break; + + case 1: + + //attenuatorBtn->setText(tr("Attn -20 dB")); + //attenuatorBtn->setBtnState(AeroButton::ON); + + set->setMercuryAttenuator(this, 0); + break; + } + } + + if (alexPos > -1) { + + foreach(QAction *act, alexAttnActionList) { + act->setChecked(false); + } + alexAttnActionList.at(alexPos)->setChecked(true); + + int state = 0; + state &= 0x7F; // 0 0 1 1 1 1 1 1 1 + state |= alexPos << 7; + + set->setAlexState(this, state); + } + + if (mercuryAttnActionList.at(0)->isChecked()) { + + if (alexAttnActionList.at(0)->isChecked()) { + + attenuatorBtn->setText(tr("Attn 0 dB")); + attenuatorBtn->setBtnState(AeroButton::OFF); + } + else if (alexAttnActionList.at(1)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -10 dB")); + attenuatorBtn->setBtnState(AeroButton::ON); + } + else if (alexAttnActionList.at(2)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -20 dB")); + attenuatorBtn->setBtnState(AeroButton::ON); + } + else if (alexAttnActionList.at(3)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -30 dB")); + attenuatorBtn->setBtnState(AeroButton::ON); + } + } + else if (mercuryAttnActionList.at(1)->isChecked()) { + + if (alexAttnActionList.at(0)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -20 dB")); + } + else if (alexAttnActionList.at(1)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -30 dB")); + } + else if (alexAttnActionList.at(2)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -40 dB")); + } + else if (alexAttnActionList.at(3)->isChecked()) { + + attenuatorBtn->setText(tr("Attn -50 dB")); + } + attenuatorBtn->setBtnState(AeroButton::ON); + } +} + +void MainWindow::setAttenuatorButton() { + + foreach(QAction *act, mercuryAttnActionList) act->setChecked(false); + foreach(QAction *act, alexAttnActionList) act->setChecked(false); + + if (m_mercuryAttnState == 1) { + + mercuryAttnActionList.at(0)->setChecked(true); + + switch (m_alexAttnState) { + + case 0: + + attenuatorBtn->setText(tr("Attn 0 dB")); + attenuatorBtn->setBtnState(AeroButton::OFF); + break; + + case 1: + + attenuatorBtn->setText(tr("Attn -10 dB")); + attenuatorBtn->setBtnState(AeroButton::ON); + break; + + case 2: + + attenuatorBtn->setText(tr("Attn -20 dB")); + attenuatorBtn->setBtnState(AeroButton::ON); + break; + + case 3: + + attenuatorBtn->setText(tr("Attn -30 dB")); + attenuatorBtn->setBtnState(AeroButton::ON); + break; + } + } + else if (m_mercuryAttnState == 0) { + + mercuryAttnActionList.at(1)->setChecked(true); + switch (m_alexAttnState) { + + case 0: + + attenuatorBtn->setText(tr("Attn -20 dB")); + break; + + case 1: + + attenuatorBtn->setText(tr("Attn -30 dB")); + break; + + case 2: + + attenuatorBtn->setText(tr("Attn -40 dB")); + break; + + case 3: + + attenuatorBtn->setText(tr("Attn -50 dB")); + break; + } + attenuatorBtn->setBtnState(AeroButton::ON); + } + + if (m_alexAttnState > -1) + alexAttnActionList.at(m_alexAttnState)->setChecked(true); +} + +void MainWindow::mercuryAttenuatorChanged(QObject *sender, HamBand band, int value) { + + Q_UNUSED(sender) + Q_UNUSED(value) + Q_UNUSED(band) + + m_currentHamBand = set->getCurrentHamBand(0); + m_mercuryAttn[m_currentHamBand] = value; + m_mercuryAttnState = m_mercuryAttn.at(m_currentHamBand); + + setAttenuatorButton(); +} + +/*! + \brief set \a QSDR::_ServerMode to \a mode. +*/ +void MainWindow::setServerMode( + QSDR::_ServerMode mode /*!<[in] server mode. */ +) { + /* + if (mode != QSDR::ChirpWSPR && chirpBtn->btnState() == AeroButton::ON) + m_chirpWidget->hide(); + + if (mode == QSDR::ChirpWSPR && wideBandBtn->btnState() == AeroButton::ON) { + + //set->setWideBandStatus(false); + wideBandBtn->setBtnState(AeroButton::OFF); + wideBandBtn->setEnabled(false); + } + + chirpBtn->setEnabled(QSDR::ChirpWSPR == mode); + */ + + setSystemState(QSDR::NoError, m_hwInterface, mode, m_dataEngineState); +} + +/*! + \brief get all network interfaces and IP addresses. +*/ +void MainWindow::getNetworkInterfaces() { + + // find out which IP to connect to + QString localIP = QHostAddress(QHostAddress::LocalHost).toString(); + + // ip addresses from ini file + QString serverIpAddress = set->getServerAddr(); + QString hpsdrDeviceLocalIpAddress = set->getHPSDRDeviceLocalAddr(); + + MAIN_DEBUG << "server ip from ini-file: " << serverIpAddress; + MAIN_DEBUG << "HPSDR device local ip from ini-file: " << hpsdrDeviceLocalIpAddress; + + QList broadcastAddresses; + QList ipAddresses; + QList nics; + + m_ipList = QNetworkInterface::allAddresses(); + m_niList = QNetworkInterface::allInterfaces(); + + foreach (QNetworkInterface ni, m_niList) { + + //MAIN_DEBUG << "network interface " << ni.humanReadableName() << " :"; + //foreach (QNetworkAddressEntry entry, ni.addressEntries()) { + + // QHostAddress broadcastAddress = entry.broadcast(); + // MAIN_DEBUG << " -> broadcast address: " << qPrintable(broadcastAddress.toString()); + // //if (broadcastAddress != QHostAddress::Null && entry.ip() != QHostAddress::LocalHost) { + // if (entry.ip().toIPv4Address() && entry.ip() != QHostAddress::LocalHost) { + // //if (entry.ip() != QHostAddress::LocalHost) { + // broadcastAddresses << broadcastAddress; + // ipAddresses << entry.ip(); + // nics << ni; + // MAIN_DEBUG << " -> ip address: " << qPrintable(entry.ip().toString()); + // set->m_ipAddressesList.append(entry.ip()); + // set->m_networkInterfaces.append(ni); + // + // set->addServerNetworkInterface(ni.humanReadableName(), entry.ip().toString()); + // set->addHPSDRDeviceNIC(ni.humanReadableName(), entry.ip().toString()); + // } + //} + + foreach (QNetworkAddressEntry entry, ni.addressEntries()) { + + QHostAddress broadcastAddress = entry.broadcast(); + + //if (broadcastAddress != QHostAddress::Null && entry.ip() != QHostAddress::LocalHost) { + if (entry.ip().toIPv4Address() && entry.ip() != QHostAddress::LocalHost) { + //if (entry.ip() != QHostAddress::LocalHost) { + + MAIN_DEBUG << "network interface " << ni.humanReadableName() << " :"; + MAIN_DEBUG << " -> broadcast address: " << qPrintable(broadcastAddress.toString()); + broadcastAddresses << broadcastAddress; + ipAddresses << entry.ip(); + nics << ni; + MAIN_DEBUG << " -> ip address: " << qPrintable(entry.ip().toString()); + set->m_ipAddressesList.append(entry.ip()); + set->m_networkInterfaces.append(ni); + + set->addServerNetworkInterface(ni.humanReadableName(), entry.ip().toString()); + set->addHPSDRDeviceNIC(ni.humanReadableName(), entry.ip().toString()); + } + } + } + + set->setNumberOfNetworkInterfaces(nics.size()); + MAIN_DEBUG << "found " << nics.size() << " valid ip addresses."; + + //emit serverWidgetEvent(); + //emit metisWidgetEvent(); + + int serverIdx = -1; + int metisIdx = -1; + + if (ipAddresses.isEmpty()) { + + // if we did not find one, use IPv4 localhost + set->setServerAddr(this, localIP); + set->setHPSDRDeviceLocalAddr(this, localIP); + } + else { + + //int serverIdx = -1; + //int metisIdx = -1; + + for (int i = 0; i < nics.size(); ++i) { + if (broadcastAddresses.at(i) != QHostAddress::Null) { + + if (ipAddresses.at(i).toString() == serverIpAddress) { + + set->setServerWidgetNIC(i); + serverIdx = i; + } + if (ipAddresses.at(i).toString() == hpsdrDeviceLocalIpAddress) { + + set->setHPSDRWidgetNIC(i); + metisIdx = i; + } + } + } + } + + QString message; + for (int i = 0; i < nics.size(); ++i) { + if (broadcastAddresses.at(i) != QHostAddress::Null) { + + if (serverIdx < 0) { + set->setServerWidgetNIC(i); + set->setServerAddr(this, ipAddresses.at(i).toString()); + } + else { + + /*message = "[server]: network interface set to: %1 (%2)."; + showMessage( + message.arg( + nics.at(serverIdx).humanReadableName(), + ipAddresses.at(serverIdx).toString() ));*/ + } + + if (metisIdx < 0) { + + set->setHPSDRWidgetNIC(i); + set->setHPSDRDeviceLocalAddr(this, ipAddresses.at(i).toString()); + + MAIN_DEBUG << "HPSDR network device interface set to: " + << nics.at(i).humanReadableName() + << "(" << ipAddresses.at(i).toString() << ")"; + } + else { + + MAIN_DEBUG << "HPSDR network device interface set to: " + << nics.at(metisIdx).humanReadableName() + << "(" << ipAddresses.at(metisIdx).toString() << ")"; + } + } + + /*for (int i = 0; i < nics.size(); ++i) { + if (serverIdx != i) { + set->setServerWidgetNIC(i); + break; + } + } + + for (int i = 0; i < nics.size(); ++i) { + if (metisIdx != i) { + set->setHPSDRWidgetNIC(i); + break; + } + + }*/ + } + + //emit serverWidgetEvent(); + //emit metisWidgetEvent(); + + //set->setServerWidgetNIC(1); + MAIN_DEBUG << "using ip address " << qPrintable(set->getServerAddr()) << " for the server."; + MAIN_DEBUG << "using ip address " << qPrintable(set->getHPSDRDeviceLocalAddr()) << " for connecting to a HPSDR device."; + + +} + + +/*! + \brief load a wav-file. +*/ +void MainWindow::loadWavFile( + QObject *sender, /*!<[in] the sender of the event. */ + const QString &fileName /*!<[in] file name of the *.wav file. */ +) { + Q_UNUSED(sender) + + m_dataEngine->loadWavFile(fileName); +} + +/*! + \brief suspend playing wav-file. +*/ +void MainWindow::suspendSignal( + QObject *sender /*!<[in] the sender of the event. */ +) { + Q_UNUSED(sender) + + m_dataEngine->suspend(); +} + +/*! + \brief start playback. +*/ +void MainWindow::startPlaybackSignal( + QObject *sender /*!<[in] the sender of the event. */ +) { + Q_UNUSED(sender) + + m_dataEngine->startPlayback(); +} + +/*! + \brief show the audio settings dialog. +*/ +void MainWindow::showSettingsDialogSignal( + QObject *sender /*!<[in] the sender of the event. */ +) { + Q_UNUSED(sender) + + m_dataEngine->showSettingsDialog(); +} + +void MainWindow::showNetworkIODialog() { + + m_netIODialog->exec(); +} + +void MainWindow::showWarningDialog(const QString &str) { + + m_warningDialog->setWarningMessage(str); + m_warningDialog->exec(); +} + +void MainWindow::addNetworkIOComboBoxEntry(QString str) { + + m_netIODialog->addDeviceComboBoxItem(str); +} + +void MainWindow::clearNetworkIOComboBoxEntry() { + + m_netIODialog->clearDeviceComboBoxItem(); +} + +/*! + \brief generates an initial message for the logging widget- +*/ +//void MainWindow::initialMessage() { +// +// QString str = set->versionStr(); +// str.prepend("cuSDR "); +// str.append(". \nOpenGL enabled HPSDR Front end \n(C) 2010-2012 Hermann von Hasseln, DL3HVH.\n"); +// m_msgBrowser->appendPlainText(str); +// m_msgBrowser->appendPlainText(""); +//} + +//******************************************************************************* +// Application's window stuff + +/*! + \brief get the QRegion of the window borders. +*/ +void MainWindow::getRegion() { + + /*m_topBorderFrame = QRegion(QRect(8, 0, width() - 16, 2)); + m_topFrame = QRegion(QRect(8, 2, width() - 16, 3)); + m_leftFrame = QRegion(QRect(0, 8, 8, height() - 16)); + m_rightFrame = QRegion(QRect(width() - 8, 8, 8, height() - 16)); + m_bottomFrame = QRegion(QRect(8, height() - 8, width() - 16, 8)); + m_topLeftFrame = QRegion(QRect(0, 0, 8, 8)); + m_bottomLeftFrame = QRegion(QRect(0, height() - 8, 8, 8)); + m_topRightFrame = QRegion(QRect(width() - 8, 0, 8, 8)); + m_bottomRightFrame = QRegion(QRect(width() - 8, height() - 8, 8, 8));*/ +} + +/*! + \brief mouse wheel event implementation. +*/ +void MainWindow::wheelEvent( + QWheelEvent *event /*!<[in] event */ +) { + event->accept(); + QWidget::wheelEvent(event); +} + +/*! + \brief enter event implementation. +*/ +void MainWindow::enterEvent( + QEvent *event /*!<[in] event */ +) { + Q_UNUSED(event); +} + +/*! + \brief leave event implementation. +*/ +void MainWindow::leaveEvent( + QEvent *event /*!<[in] event */ +) { + Q_UNUSED(event); +} + +/*! + \brief resize event implementation. +*/ +void MainWindow::resizeEvent( + QResizeEvent *event /*!<[in] event */ +) { + //Q_UNUSED(event); + + //QTimer::singleShot(10, this, SLOT(getRegion())); + //m_resizeFrame = true; + //displayPanelToolBar->updateGeometry(); + m_oglDisplayPanel->update(); + QWidget::resizeEvent(event); +} + +/*! + \brief close event implementation. +*/ +void MainWindow::closeEvent( + QCloseEvent *event /*!<[in] event */ +) { + if (set->getMainPower()) + startButtonClickedEvent(); + + QSettings settings(QCoreApplication::applicationDirPath() + "/" + m_windowsSettingsFilename, QSettings::IniFormat); + settings.setValue("geometry", saveGeometry()); + settings.setValue("windowState", saveState()); + + mainBtnList.clear(); + + if (m_serverWidget) { + + disconnect(m_serverWidget, 0, 0, 0); + delete m_serverWidget; + m_serverWidget = NULL; + } + + if (m_dataEngine) { + + disconnect(m_dataEngine, 0, 0, 0); + delete m_dataEngine; + m_dataEngine = NULL; + } + + /*if (m_cudaInfoWidget && m_cudaPresence) { + + disconnect(m_cudaInfoWidget, 0, 0, 0); + delete m_cudaInfoWidget; + m_cudaInfoWidget = NULL; + }*/ + + if (m_oglDisplayPanel) { + + disconnect(m_oglDisplayPanel, 0, 0, 0); + delete m_oglDisplayPanel; + m_oglDisplayPanel = NULL; + } + + if (m_radioTabWidget) { + + disconnect(m_radioTabWidget, 0, 0, 0); + delete m_radioTabWidget; + m_radioTabWidget = NULL; + } + + if (m_chirpWidget) { + + disconnect(m_chirpWidget, 0, 0, 0); + delete m_chirpWidget; + m_chirpWidget = NULL; + } + + /*if (m_hpsdrWidget) { + + disconnect(m_hpsdrWidget, 0, 0, 0); + delete m_hpsdrWidget; + m_hpsdrWidget = NULL; + }*/ + + if (m_hpsdrTabWidget) { + + disconnect(m_hpsdrTabWidget, 0, 0, 0); + delete m_hpsdrTabWidget; + m_hpsdrTabWidget = NULL; + } + + if (m_displayTabWidget) { + + disconnect(m_displayTabWidget, 0, 0, 0); + delete m_displayTabWidget; + m_displayTabWidget = NULL; + } + + /*if (m_hpsdrServer) { + + disconnect(m_hpsdrServer, 0, 0, 0); + delete m_hpsdrServer; + m_hpsdrServer = NULL; + }*/ + QMainWindow::closeEvent(event); +} + +/*! + \brief show event implementation. +*/ +void MainWindow::showEvent( + QShowEvent *event /*!<[in] event */ +) { + QWidget::showEvent(event); +} + +/*! + \brief key pressed event implementation. +*/ +void MainWindow::keyPressEvent( + QKeyEvent *event /*!<[in] key event */ +) { + switch (event->key()) { + + case Qt::Key_Escape: + + setMainWindowGeometry(); + return; + + case Qt::Key_1: + + return; + } + + QWidget::keyPressEvent(event); +} + + +//*************************************************************************** +// NetworkIODialog class + +NetworkIODialog::NetworkIODialog(QWidget *parent) + : QDialog(parent) + , set(Settings::instance()) +{ + int btnWidth = 74; + int btnHeight = 18; + + m_deviceCards = set->getMetisCardsList(); + + setWindowModality(Qt::NonModal); + setWindowOpacity(0.9); + setStyleSheet(set->getDialogStyle()); + + setMouseTracking(true); + + m_titleFont.setStyleStrategy(QFont::PreferAntialias); + m_titleFont.setFixedPitch(true); + m_titleFont.setPixelSize(13); + m_titleFont.setFamily("Arial"); + m_titleFont.setBold(true); + + + QVBoxLayout *dialogLayout = new QVBoxLayout(this); + + m_deviceComboBox = new QComboBox(this); + m_deviceComboBox->setStyleSheet(set->getComboBoxStyle()); + m_deviceComboBox->setMinimumContentsLength(30); + + QScopedPointer titleLayout(new QHBoxLayout); + QLabel *titleLabel = new QLabel(tr("found more than one device:"), this); + titleLabel->setFont(m_titleFont); + titleLabel->setStyleSheet(set->getLabelStyle()); + titleLayout->addWidget(titleLabel); + dialogLayout->addLayout(titleLayout.data()); + titleLayout.take(); // ownership transferred to dialogLayout + + QScopedPointer metisDeviceLayout(new QHBoxLayout); + QLabel *ipAddressLabel = new QLabel(tr("Device (IP Addr):"), this); + ipAddressLabel->setStyleSheet(set->getLabelStyle()); + metisDeviceLayout->addWidget(ipAddressLabel); + metisDeviceLayout->addWidget(m_deviceComboBox); + dialogLayout->addLayout(metisDeviceLayout.data()); + metisDeviceLayout.take(); // ownership transferred to dialogLayout + + /*CHECKED_CONNECT( + m_metisDeviceComboBox, + SIGNAL(activated(int)), + this, + SLOT(metisDeviceChanged(int)));*/ + + AeroButton* okBtn = new AeroButton("Ok", this); + okBtn->setRoundness(10); + okBtn->setFixedSize(btnWidth, btnHeight); + CHECKED_CONNECT( + okBtn, + SIGNAL(clicked()), + this, + SLOT(okBtnClicked())); + + AeroButton* cancelBtn = new AeroButton("Cancel", this); + cancelBtn->setRoundness(10); + cancelBtn->setFixedSize(btnWidth, btnHeight); + CHECKED_CONNECT( + cancelBtn, + SIGNAL(clicked()), + this, + SLOT(reject())); + + QHBoxLayout *hbox = new QHBoxLayout; + hbox->setSpacing(1); + hbox->addWidget(okBtn); + hbox->addWidget(cancelBtn); + + dialogLayout->addLayout(hbox); + + setLayout(dialogLayout); +} + +NetworkIODialog::~NetworkIODialog() { +} + +void NetworkIODialog::okBtnClicked() { + + if (m_deviceCards.length() > 0) { + + set->setCurrentHPSDRDevice(m_deviceCards.at(m_deviceComboBox->currentIndex())); + NETWORKDIALOG_DEBUG << "Network device at: " << m_deviceCards.at(m_deviceComboBox->currentIndex()).ip_address.toString() << " selected."; + accept(); + } + else + NETWORKDIALOG_DEBUG << "HPSDR network device list length:" << m_deviceCards.length(); +} + +void NetworkIODialog::addDeviceComboBoxItem(QString str) { + + m_deviceComboBox->addItem(str); + m_deviceCards = set->getMetisCardsList(); +} + +void NetworkIODialog::clearDeviceComboBoxItem() { + + m_deviceComboBox->clear(); +} + + +//*************************************************************************** +// WarningDialog class + +WarningDialog::WarningDialog(QWidget *parent) + : QDialog(parent) + , set(Settings::instance()) + , m_btnWidth(74) + , m_btnHeight(18) +{ + setWindowModality(Qt::NonModal); + setWindowTitle("Warning"); + setWindowOpacity(0.9); + setStyleSheet(set->getDialogStyle()); + + setMouseTracking(true); + + m_titleFont.setStyleStrategy(QFont::PreferAntialias); + m_titleFont.setFixedPitch(true); + m_titleFont.setBold(true); + m_titleFont.setPixelSize(13); + m_titleFont.setFamily("Arial"); + m_titleFont.setBold(true); + + //m_warningIcon.QPixmap::fromImage(QImage(QLatin1String(":/img/warning.png")), Qt::ColorOnly); + + m_warningLabel = new QLabel("", this); + + okBtn = new AeroButton("Ok", this); + okBtn->setRoundness(10); + okBtn->setFixedSize(m_btnWidth, m_btnHeight); + + CHECKED_CONNECT( + okBtn, + SIGNAL(clicked()), + this, + SLOT(okBtnClicked())); +} + +WarningDialog::~WarningDialog() { +} + +void WarningDialog::paintEvent(QPaintEvent *) { + + QPainter p(this); + p.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing, true); + + //QRect titlebar_rect(0, 0, width(), height()); + + /*QLinearGradient titlebarGrad(0, 0, 0, 1); + titlebarGrad.setCoordinateMode(QGradient::ObjectBoundingMode); + titlebarGrad.setSpread(QGradient::PadSpread); + titlebarGrad.setColorAt(0, QColor(110, 110, 110)); + titlebarGrad.setColorAt(0.45, QColor(80, 80, 80)); + titlebarGrad.setColorAt(0.55, QColor(56, 56, 65)); + titlebarGrad.setColorAt(1, QColor(40, 40, 40));*/ + + // draw background rect + /*p.setPen(Qt::NoPen); + p.setBrush(QBrush(titlebarGrad)); + p.drawRect(titlebar_rect); + p.setPen(QColor(255, 255, 255, 140)); + p.drawLine(1, titlebar_rect.top(), width() - 2, titlebar_rect.top()); + p.setPen(QColor(255, 255, 255, 30)); + p.drawLine(1, titlebar_rect.bottom() - 2, width() - 2, titlebar_rect.bottom() - 2); + p.setPen(QColor(0, 0, 0, 255)); + p.drawLine(0, titlebar_rect.bottom(), width(), titlebar_rect.bottom());*/ + + QPixmap warningIcon = QPixmap::fromImage(QImage(QLatin1String(":/img/warning.png")), Qt::ColorOnly); + if (!warningIcon.isNull()) p.drawPixmap(13, 5, 16, 16, warningIcon); + + // draw text + p.setFont(m_titleFont); + p.setPen(QColor(95, 95, 95, 255)); + + // warning msg + p.drawText( + 40, 6, + m_msgFontWidth, m_msgFontHeight, + Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, + m_message); + + p.setPen(QColor(235, 235, 235, 255)); + p.drawText( + 39, 5, + m_msgFontWidth, m_msgFontHeight, + Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, + m_message); + + okBtn->move((width() - m_btnWidth)/2, 30); + + p.end(); +} + +void WarningDialog::setWarningMessage(const QString &msg) { + + m_message = msg; + + QFontMetrics tfm(m_titleFont); + m_msgFontWidth = tfm.width(m_message); + m_msgFontHeight = tfm.height(); + + this->setFixedWidth(m_msgFontWidth + 60); + this->setFixedHeight(60); +} + +void WarningDialog::okBtnClicked() { + + accept(); +} diff --git a/Source/src/cusdr_mainWidget.h b/Source/src/cusdr_mainWidget.h new file mode 100644 index 0000000..2281804 --- /dev/null +++ b/Source/src/cusdr_mainWidget.h @@ -0,0 +1,433 @@ +/** +* @file cusdr_mainWidget.h +* @brief main window widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-01-06 +*/ + +/* + * Copyright 2010, 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_MAIN_H +#define CUSDR_MAIN_H + +#include +//#include +//#include +#include +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include + +#include "cusdr_settings.h" +#include "cusdr_fonts.h" +#include "Util/cusdr_buttons.h" +#include "DataEngine/cusdr_dataEngine.h" +#include "cusdr_hpsdrTabWidget.h" +#include "cusdr_radioTabWidget.h" +#include "cusdr_displayTabWidget.h" +#include "cusdr_serverWidget.h" +#include "cusdr_chirpWidget.h" +//#include "cusdr_alexTabWidget.h" +//#include "cusdr_extCtrlWidget.h" +//#include "cusdr_radioWidget.h" +//#include "cusdr_radioPopupWidget.h" +#include "GL/cusdr_oglWidebandPanel.h" +#include "GL/cusdr_oglReceiverPanel.h" +#include "GL/cusdr_oglDisplayPanel.h" +//#include "cusdr_graphicOptionsWidget.h" +//#include "cusdr_server.h" + + +#ifdef LOG_MAIN +#define MAIN_DEBUG qDebug().nospace() << "MainWindow::\t" +#else +#define MAIN_DEBUG nullDebug() +#endif + +#ifdef LOG_NETWORKDIALOG +#define NETWORKDIALOG_DEBUG qDebug().nospace() << "NetworkDialog::\t" +#else +#define NETWORKDIALOG_DEBUG nullDebug() +#endif + + +class NetworkIODialog; +class WarningDialog; + + +class MainWindow : public QMainWindow { + + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + void setup(); + +public slots: + void update(); + void masterSwitchChanged(QObject *sender, bool power); + void startButtonClickedEvent(); + void widgetBtnClickedEvent(); + void wideBandBtnClickedEvent(); + //void avgBtnClickedEvent(); + //void gridBtnClickedEvent(); + //void peakHoldBtnClickedEvent(); + void alexBtnClickedEvent(); + void muteBtnClickedEvent(); + //void resizeWidget(); + + void showWidgetEvent(QObject *sender); + void closeWidgetEvent(QObject *sender); + + void loadWavFile(QObject *sender, const QString &fileName); + void suspendSignal(QObject *sender); + void startPlaybackSignal(QObject *sender); + void showSettingsDialogSignal(QObject *sender); + +private: + void setSystemState( + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + +#if defined(Q_OS_WIN32) + void getCPULoadThread(LPVOID lpParam); +#endif + + void setupConnections(); + void setupLayout(); + void createModeMenu(); + void createViewMenu(); + void createAttenuatorMenu(); + void createDisplayPanelToolBar(); + void createMainBtnToolBar(); + //void createDisplayPanel(); + void createStatusToolBar(); + //void initWidebandDisplay(); + void createReceiverPanels(int rx); + void updateFromSettings(); + //void runFFTWWisdom(); + void setAttenuatorButton(); + +private: + Settings* set; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QMutex m_mutex; + + QDir m_currentDir; + QToolBar* mainBtnToolBar; + QToolBar* displayPanelToolBar; + + QMainWindow* centralwidget; + + QList rxWidgetList; + QVector rxVolumeList; + + QDockWidget* widebandDock; + QDockWidget* rx1Dock; + QList dockWidgetList; + QList rxDockWidgetList; + + QList m_ipList; + QList m_niList; + + //QThreadEx* cpuLoadThread; + + CFonts* fonts; + TFonts m_fonts; + + QSize m_oldSize; + QPoint m_oldPosition; + + QPixmap m_originalPixmap; + QPixmap m_widgetMask; + + QTimer* m_resizeTimer; + + QPoint m_dragPosition; + QPoint m_pos; + QRect m_rect; + QString m_message; + + QGridLayout* m_contentLayout; + + QLabel* m_volumeLabel; + QLabel* m_volLevelLabel; + QLabel* m_agcGainLabel; + QLabel* m_agcGainLevelLabel; + QLabel* m_cpuLoadLabel; + QLabel* m_dateTimeLabel; + QLabel* m_statusBarMessage; + + QString m_windowsSettingsFilename; + QString m_cpuLoadString; + QString m_dateTimeString; + QString m_statusBarMessageString; + + QWidget* m_buttonWidget; + QWidget* m_secondButtonWidget; + + QSlider* m_volumeSlider; + QSlider* m_agcGainSlider; + AGCMode m_agcMode; + + DataEngine* m_dataEngine; + RadioPopupWidget* m_radioPopupWidget; + ServerWidget* m_serverWidget; + ChirpWidget* m_chirpWidget; + HPSDRTabWidget* m_hpsdrTabWidget; + RadioTabWidget* m_radioTabWidget; + DisplayTabWidget* m_displayTabWidget; + OGLDisplayPanel* m_oglDisplayPanel; + //CudaInfoWidget* m_cudaInfoWidget; + QGLWidebandPanel* m_wbDisplay; + + NetworkIODialog* m_netIODialog; + WarningDialog* m_warningDialog; + + HamBand m_currentHamBand; + + quint16 m_alexConfig; + QList m_alexStates; + QList m_mercuryAttn; + //QList m_clDevices; + + AeroButton* startBtn; + AeroButton* serverBtn; + AeroButton* hpsdrBtn; + AeroButton* modeBtn; + AeroButton* viewBtn; + AeroButton* chirpBtn; + AeroButton* openclBtn; + AeroButton* rxCtrlBtn; + AeroButton* wideBandBtn; + AeroButton* ctrlDisplayBtn; + AeroButton* displayBtn; + AeroButton* plusRxBtn; + AeroButton* quitBtn; + AeroButton* nullBtn; + + AeroButton* moxBtn; + AeroButton* tunBtn; + AeroButton* alexBtn; + AeroButton* lastFreqBtn; + AeroButton* attenuatorBtn; + AeroButton* muteBtn; + + QList mainBtnList; + + QMenu *modeMenu; + QMenu *viewMenu; + QMenu *attenuatorMenu; + + QActionGroup *modeActionGroup; + QAction *noServerModeAction; + QAction *sdrModeAction; + QAction *chirpWSPRAction; + + QActionGroup *mercuryAttnActionGroup; + QActionGroup *alexAttnActionGroup; + QAction *mercuryAttn_0dBAction; + QAction *mercuryAttn_20dBAction; + QAction *alexAttn_0dBAction; + QAction *alexAttn_10dBAction; + QAction *alexAttn_20dBAction; + QAction *alexAttn_30dBAction; + + QList mercuryAttnActionList; + QList alexAttnActionList; + + bool m_resizeFrame; + bool m_mousePressed; + bool m_quitHighBotton; + bool m_fullScreen; + bool m_cudaPresence; + bool m_mover; + bool m_msgBrowserVisible; + + double m_alpha; + + int m_deltaX_max; + int m_deltaY_max; + int m_resizePosition; + int m_numberOfReceivers; + + int m_alexAttnState; + int m_mercuryAttnState; + + int m_oldSampleRate; + + //qreal m_agcMaxGain; + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void ctrlDisplayBtnClickedEvent(); + void closeMainWindow(); + void maximizeMainWindow(); + void setMainWindowGeometry(); + void updateTitle(); + void updateStatusBar(short load); + void setFullScreen(); + void getRegion(); + + void setServerMode(QSDR::_ServerMode mode); + //void setReceiver(); + void setTxAllowed(QObject *sender, bool value); + void setCurrentReceiver(QObject *sender, int rx); + void setNumberOfReceivers(QObject *sender, int value); + //void setInternalDSPMode(bool value); + void setSDRMode(bool); + void setChirpWSPRMode(bool value); + void getNetworkInterfaces(); + void setMainVolume(int value); + //void setHamBand(QObject *sender, int rx, bool byButton, HamBand band); + void setAGCMode(QObject *sender, int rx, AGCMode mode, bool hang); + void setAGCGain(int value); + //void setAGCGain(QObject *sender, int rx, int value); + void setAGCGain(QObject *sender, int rx, qreal value); + void getLastFrequency(); + void addReceiver(); + + void alexPresenceChanged(bool value); + void alexConfigurationChanged(quint16 conf); + void alexStateChanged(HamBand band, const QList &states); + void setAttenuator(); + void mercuryAttenuatorChanged(QObject *sender, HamBand band, int value); + + void showStatusBarMessage(const QString &msg, int time); + void clearStatusBarMessage(); + void showNetworkIODialog(); + void showWarningDialog(const QString &msg); + + void addNetworkIOComboBoxEntry(QString str); + void clearNetworkIOComboBoxEntry(); + + void widebandVisibilityChanged(bool value); + void showRadioPopup(bool value); + +protected: + //void getSelectedFrame(QPoint p); + //void paintEvent(QPaintEvent *event); + void closeEvent(QCloseEvent *event); + void keyPressEvent(QKeyEvent *event); + void showEvent(QShowEvent *event); + //void focusInEvent(QFocusEvent *event); + //void focusOutEvent(QFocusEvent *event); + //void moveEvent(QMoveEvent *event); + void resizeEvent(QResizeEvent *event); + //void changeEvent(QEvent *event); + //void mousePressEvent(QMouseEvent *event); + //void mouseMoveEvent(QMouseEvent *event); + //void mouseReleaseEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + +signals: + void setAGCSliderValue(int value); +}; + +//*************************************************************************** +// NetworkIODialog class + +class NetworkIODialog : public QDialog { + + Q_OBJECT + +public: + NetworkIODialog(QWidget *parent = 0); + ~NetworkIODialog(); + +public slots: + void addDeviceComboBoxItem(QString str); + void clearDeviceComboBoxItem(); + +private: + Settings* set; + + QFont m_titleFont; + QComboBox* m_deviceComboBox; + + TNetworkDevicecard m_deviceCard; + QList m_deviceCards; + +private slots: + void okBtnClicked(); +}; + + +//*************************************************************************** +// WarningDialog class + +class WarningDialog : public QDialog { + + Q_OBJECT + +public: + WarningDialog(QWidget *parent = 0); + ~WarningDialog(); + +public slots: + void setWarningMessage(const QString &msg); + +protected: + void paintEvent(QPaintEvent *event); + +private: + Settings* set; + + QFont m_titleFont; + //QPixmap m_warningIcon; + + QLabel* m_warningLabel; + + AeroButton* okBtn; + + QString m_message; + + int m_btnWidth; + int m_btnHeight; + int m_msgFontWidth; + int m_msgFontHeight; + +private slots: + void okBtnClicked(); +}; + +#endif // CUSDR_MAIN_H diff --git a/Source/src/cusdr_networkWidget.cpp b/Source/src/cusdr_networkWidget.cpp new file mode 100644 index 0000000..723699a --- /dev/null +++ b/Source/src/cusdr_networkWidget.cpp @@ -0,0 +1,600 @@ +/** +* @file cusdr_networkWidget.cpp +* @brief Network settings widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-10-24 +*/ + +/* + * + * Copyright 2010 - 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#define LOG_NETWORK_WIDGET + +// use: NETWORK_WIDGET_DEBUG + +//#include +//#include +//#include +//#include +#include + +#include "cusdr_networkWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 42 + + +NetworkWidget::NetworkWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(set->getCurrentServerMode()) + , m_hwInterface(set->getHWInterface()) + , m_hwInterfaceTemp(set->getHWInterface()) + , m_dataEngineState(QSDR::DataEngineDown) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(0) + , m_numberOfReceivers(1) + , m_hpsdrHardware(set->getHPSDRHardware()) +{ + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 8, 4, 0); + setMouseTracking(true); + + m_deviceCards = set->getMetisCardsList(); + + createDeviceNetworkInterfaceGroup(); + createDeviceSearchGroup(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 4, 0); + hbox1->addWidget(hpsdrInterfaceExclusiveBtnGroup()); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(0); + hbox2->setContentsMargins(4, 0, 4, 0); + hbox2->addWidget(deviceNIGroupBox); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(0); + hbox3->setContentsMargins(4, 0, 4, 0); + hbox3->addWidget(searchNetworkDeviceGroupBox); + + if (m_hwInterface == QSDR::NoInterfaceMode) { + + deviceNIGroupBox->hide(); + searchNetworkDeviceGroupBox->hide(); + } + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addStretch(); + setLayout(mainLayout); + + setupConnections(); + setSocketBufSize(this, set->getSocketBufferSize()); +} + +NetworkWidget::~NetworkWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void NetworkWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(newHPSDRDeviceNIC(QString, QString)), + this, + SLOT(addDeviceNICEntry(QString, QString))); + + CHECKED_CONNECT( + set, + SIGNAL(hpsdrDeviceNICChanged(int)), + this, + SLOT(setDeviceNIC(int))); + + CHECKED_CONNECT( + set, + SIGNAL(metisCardListChanged(QList)), + this, + SLOT(setNetworkDeviceList(QList))); + + CHECKED_CONNECT( + set, + SIGNAL(hpsdrNetworkDeviceChanged(TNetworkDevicecard)), + this, + SLOT(setCurrentNetworkDevice(TNetworkDevicecard))); + + CHECKED_CONNECT( + set, + SIGNAL(socketBufferSizeChanged(QObject*, int)), + this, + SLOT(setSocketBufSize(QObject*, int))); +} + +void NetworkWidget::addNICChangedConnection() { + + CHECKED_CONNECT( + networkDeviceInterfaces, + SIGNAL(currentIndexChanged(int)), + set, + SLOT(setHPSDRDeviceNIC(int))); +} + +void NetworkWidget::setDeviceNIC(int index) { + + networkDeviceInterfaces->setCurrentIndex(index); +} + +QGroupBox* NetworkWidget::hpsdrInterfaceExclusiveBtnGroup() { + + networkPresenceBtn = new AeroButton("Network", this); + networkPresenceBtn->setRoundness(0); + networkPresenceBtn->setFixedSize (btn_width, btn_height); + + CHECKED_CONNECT( + networkPresenceBtn, + SIGNAL(clicked()), + this, + SLOT(interfaceBtnClicked())); + + noHWBtn = new AeroButton("None", this); + noHWBtn->setRoundness(0); + noHWBtn->setFixedSize (btn_width, btn_height); + + CHECKED_CONNECT( + noHWBtn, + SIGNAL(clicked()), + this, + SLOT(interfaceBtnClicked())); + + hwInterfaceChanged(); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addWidget(noHWBtn); + hbox1->addWidget(networkPresenceBtn); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + + QGroupBox *groupBox = new QGroupBox(tr("Hardware Interface"), this); + groupBox->setMinimumWidth(m_minimumGroupBoxWidth); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(set->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +void NetworkWidget::createDeviceNetworkInterfaceGroup() { + + networkDeviceInterfaces = new QComboBox(); + + networkDeviceInterfaces->setStyleSheet(set->getComboBoxStyle()); + networkDeviceInterfaces->setMinimumContentsLength(22); + + socketBufSizeBtn = new AeroButton("Enable", this); + socketBufSizeBtn->setRoundness(10); + socketBufSizeBtn->setFixedSize(btn_widths, btn_height); + socketBufSizeBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + socketBufSizeBtn, + SIGNAL(clicked()), + this, + SLOT(socketBufSizeBtnClicked())); + + socketBufferSizes = new QComboBox(); + socketBufferSizes->setStyleSheet(set->getComboBoxStyle()); + socketBufferSizes->addItem("1 kB"); + socketBufferSizes->addItem("8 kB"); + socketBufferSizes->addItem("16 kB"); + socketBufferSizes->addItem("32 kB"); + socketBufferSizes->addItem("64 kB"); + socketBufferSizes->addItem("128 kB"); + socketBufferSizes->addItem("256 kB"); + socketBufferSizes->addItem("512 kB"); + socketBufferSizes->setEnabled(false); + + CHECKED_CONNECT( + socketBufferSizes, + SIGNAL(currentIndexChanged(int)), + this, + SLOT(setSocketBufferSize(int))); + + socketBufferSizeLabel = new QLabel("Socket Buffer Size:", this); + socketBufferSizeLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + socketBufferSizeLabel->setStyleSheet(set->getLabelStyle()); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(1); + hbox1->addStretch(); + hbox1->addWidget(networkDeviceInterfaces); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(1); + //hbox2->addStretch(); + hbox2->addWidget(socketBufferSizeLabel); + hbox2->addWidget(socketBufSizeBtn); + hbox2->addSpacing(3); + hbox2->addStretch(); + hbox2->addWidget(socketBufferSizes); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(3); + vbox->addSpacing(5); + vbox->addLayout(hbox1); + vbox->addSpacing(5); + vbox->addLayout(hbox2); + + deviceNIGroupBox = new QGroupBox(tr("Local network interface"), this); + deviceNIGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + deviceNIGroupBox->setLayout(vbox); + deviceNIGroupBox->setStyleSheet(set->getWidgetStyle()); + deviceNIGroupBox->setFont(QFont("Arial", 8)); +} + +void NetworkWidget::createDeviceSearchGroup() { + + searchNetworkDeviceBtn = new AeroButton("search", this); + searchNetworkDeviceBtn->setRoundness(10); + searchNetworkDeviceBtn->setFixedSize(btn_width2, btn_height); + + CHECKED_CONNECT( + searchNetworkDeviceBtn, + SIGNAL(clicked()), + this, + SLOT(searchHPSDRDeviceBtnClicked())); + + networkDeviceIPAdresses = new QComboBox(); + + networkDeviceIPAdresses->setStyleSheet(set->getComboBoxStyle()); + networkDeviceIPAdresses->setMinimumContentsLength(22); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(1); + hbox1->addStretch(); + hbox1->addWidget(searchNetworkDeviceBtn); + hbox1->addSpacing(3); + hbox1->addWidget(networkDeviceIPAdresses); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(3); + vbox->addSpacing(5); + vbox->addLayout(hbox1); + vbox->addSpacing(5); + + searchNetworkDeviceGroupBox = new QGroupBox(tr("HPSDR device IP address"), this); + searchNetworkDeviceGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + searchNetworkDeviceGroupBox->setLayout(vbox); + searchNetworkDeviceGroupBox->setStyleSheet(set->getWidgetStyle()); + searchNetworkDeviceGroupBox->setFont(QFont("Arial", 8)); +} + +// ************************************************************************ + +void NetworkWidget::addDeviceNICEntry(QString niName, QString ipAddress) { + + //QString item = niName; + QString item = ipAddress; + //item.append(" ("); + //item.append(ipAddress); + //item.append(")"); + networkDeviceInterfaces->addItem(item); + //this->repaint(); +} + +void NetworkWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + if (m_hwInterface != hwmode) { + + m_hwInterface = hwmode; + hwInterfaceChanged(); + } + + //m_oldServerMode = m_serverMode; + if (m_serverMode != mode) { + + if (mode == QSDR::ChirpWSPR) + disableButtons(); + + if (m_serverMode == QSDR::ChirpWSPR) + enableButtons(); + + m_serverMode = mode; + } + + if (m_dataEngineState != state) { + + if (state == QSDR::DataEngineUp) + disableButtons(); + else + enableButtons(); + + m_dataEngineState = state; + } + + //if (!change) return; + update(); +} + +void NetworkWidget::hwInterfaceChanged() { + + switch (m_hwInterface) { + + case QSDR::NoInterfaceMode: + + noHWBtn->setBtnState(AeroButton::ON); + networkPresenceBtn->setBtnState(AeroButton::OFF); + break; + + case QSDR::Metis: + case QSDR::Hermes: + + noHWBtn->setBtnState(AeroButton::OFF); + networkPresenceBtn->setBtnState(AeroButton::ON); + break; + } + + m_hwInterfaceTemp = m_hwInterface; +} + +void NetworkWidget::interfaceBtnClicked() { + + AeroButton *button = qobject_cast(sender()); + + //if (button == networkPresenceBtn && m_hpsdrHardware == 0) { // HPSDR modules + if (button == networkPresenceBtn) { // HPSDR modules + + noHWBtn->setBtnState(AeroButton::OFF); + noHWBtn->update(); + networkPresenceBtn->setBtnState(AeroButton::ON); + + if (m_hpsdrHardware == 0) { + + m_hwInterface = QSDR::Metis; + NETWORK_WIDGET_DEBUG << "HW interface changed to Metis."; + } + else if (m_hpsdrHardware == 1) { + + m_hwInterface = QSDR::Hermes; + NETWORK_WIDGET_DEBUG << "HW interface changed to Hermes."; + } + + deviceNIGroupBox->show(); + searchNetworkDeviceGroupBox->show(); + //source10MhzExclusiveGroup->show(); + //source122_88MhzExclusiveGroup->show(); + //socketBufferSizeGroupBox->show(); + } + else + if (button == noHWBtn) { + + networkPresenceBtn->setBtnState(AeroButton::OFF); + networkPresenceBtn->update(); + noHWBtn->setBtnState(AeroButton::ON); + + m_hwInterface = QSDR::NoInterfaceMode; + emit messageEvent("[hpsdr]: changed to no-interface mode."); + deviceNIGroupBox->hide(); + searchNetworkDeviceGroupBox->hide(); + //source10MhzExclusiveGroup->hide(); + //source122_88MhzExclusiveGroup->hide(); + //socketBufferSizeGroupBox->hide(); + } + + qDebug() << "HPSDRWidget:: setSystemState."; + set->setSystemState( + this, + QSDR::NoError, + m_hwInterface, + m_serverMode, + m_dataEngineState); +} + +void NetworkWidget::searchHPSDRDeviceBtnClicked() { + + set->searchHpsdrNetworkDevices(); +} + +void NetworkWidget::socketBufSizeBtnClicked() { + + if (socketBufSizeBtn->btnState() == AeroButton::OFF) { + + socketBufferSizes->setEnabled(true); + socketBufferSizes->blockSignals(true); + setSocketBufSize(this, set->getSocketBufferSize()); + socketBufferSizes->blockSignals(false); + //NETWORK_WIDGET_DEBUG << "getSocketBufferSize() :" << set->getSocketBufferSize(); + set->setManualSocketBufferSize(this, true); + socketBufSizeBtn->setText("Disable"); + socketBufSizeBtn->setBtnState(AeroButton::ON); + } + else { + + socketBufferSizes->setEnabled(false); + set->setManualSocketBufferSize(this, false); + socketBufSizeBtn->setText("Enable"); + socketBufSizeBtn->setBtnState(AeroButton::OFF); + } + + socketBufSizeBtn->update(); +} + +void NetworkWidget::disableButtons() { + + noHWBtn->setEnabled(false); + networkPresenceBtn->setEnabled(false); +} + +void NetworkWidget::enableButtons() { + + noHWBtn->setEnabled(true); + networkPresenceBtn->setEnabled(true); +} + +void NetworkWidget::setNetworkDeviceList(QList list) { + + m_deviceCards = list; + + if (list.length() == 0 ) { + + emit messageEvent("[hpsdr]: Metis card list empty."); + return; + } + + networkDeviceIPAdresses->clear(); + foreach (TNetworkDevicecard device, list) { + + networkDeviceIPAdresses->addItem(device.ip_address.toString()); + networkDeviceIPAdresses->update(); + } +} + +void NetworkWidget::setCurrentNetworkDevice(TNetworkDevicecard card) { + + int i = 0; + foreach (TNetworkDevicecard dev, m_deviceCards) { + + if (dev.ip_address == card.ip_address) networkDeviceIPAdresses->setCurrentIndex(i); + i++; + } +} + +void NetworkWidget::setSocketBufSize(QObject *sender, int size) { + + Q_UNUSED (sender) + //if (sender == this) return; + + m_socketBufferSize = size; + + switch (m_socketBufferSize) { + + case 1: + socketBufferSizes->setCurrentIndex(0); + break; + + case 8: + socketBufferSizes->setCurrentIndex(1); + break; + + case 16: + socketBufferSizes->setCurrentIndex(2); + break; + + case 32: + socketBufferSizes->setCurrentIndex(3); + break; + + case 64: + socketBufferSizes->setCurrentIndex(4); + break; + + case 128: + socketBufferSizes->setCurrentIndex(5); + break; + + case 256: + socketBufferSizes->setCurrentIndex(6); + break; + + case 512: + socketBufferSizes->setCurrentIndex(7); + break; + } + +} + +void NetworkWidget::setSocketBufferSize(int value) { + + switch (value) { + + case 0: + set->setSocketBufferSize(this, 1); + break; + + case 1: + set->setSocketBufferSize(this, 8); + break; + + case 2: + set->setSocketBufferSize(this, 16); + break; + + case 3: + set->setSocketBufferSize(this, 32); + break; + + case 4: + set->setSocketBufferSize(this, 64); + break; + + case 5: + set->setSocketBufferSize(this, 128); + break; + + case 6: + set->setSocketBufferSize(this, 256); + break; + + case 7: + set->setSocketBufferSize(this, 512); + break; + } +} diff --git a/Source/src/cusdr_networkWidget.h b/Source/src/cusdr_networkWidget.h new file mode 100644 index 0000000..bc22b17 --- /dev/null +++ b/Source/src/cusdr_networkWidget.h @@ -0,0 +1,129 @@ +/** +* @file cusdr_networkWidget.h +* @brief Network settings widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-10-24 +*/ + +/* + * + * Copyright 2010 - 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_NETWORK_WIDGET_H +#define _CUSDR_NETWORK_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + +#ifdef LOG_NETWORK_WIDGET +# define NETWORK_WIDGET_DEBUG qDebug().nospace() << "NetworkWidget::\t" +#else +# define NETWORK_WIDGET_DEBUG nullDebug() +#endif + + +class NetworkWidget : public QWidget { + + Q_OBJECT + +public: + NetworkWidget(QWidget *parent = 0); + ~NetworkWidget(); + + +public slots: + void addDeviceNICEntry(QString niName, QString ipAddress); + void addNICChangedConnection(); + void setSocketBufSize(QObject *sender, int size); + void hwInterfaceChanged(); + +private: + Settings *set; + + QString m_message; + + QList m_deviceCards; + + QGroupBox *hpsdrInterfaceExclusiveBtnGroup(); + QGroupBox *receiversExclusiveBtnGroup(); + QGroupBox *source10MhzExclusiveGroup; + QGroupBox *source122_88MhzExclusiveGroup; + QGroupBox *deviceNIGroupBox; + QGroupBox *searchNetworkDeviceGroupBox; + QGroupBox *socketBufferSizeGroupBox; + + QComboBox *networkDeviceInterfaces; + QComboBox *networkDeviceIPAdresses; + QComboBox *socketBufferSizes; + QComboBox *m_receiverComboBox; + + QLabel *socketBufferSizeLabel; + + AeroButton *networkPresenceBtn; + AeroButton *noHWBtn; + + AeroButton *searchNetworkDeviceBtn; + AeroButton *socketBufSizeBtn; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_HWInterfaceMode m_hwInterfaceTemp; + QSDR::_DataEngineState m_dataEngineState; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_numberOfReceivers; + int m_hpsdrHardware; + int m_socketBufferSize; + + void setupConnections(); + void createDeviceNetworkInterfaceGroup(); + void createDeviceSearchGroup(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void interfaceBtnClicked(); + void searchHPSDRDeviceBtnClicked(); + void socketBufSizeBtnClicked(); + void setSocketBufferSize(int value); + void setDeviceNIC(int index); + void setNetworkDeviceList(QList list); + void setCurrentNetworkDevice(TNetworkDevicecard card); + void disableButtons(); + void enableButtons(); + +signals: + void messageEvent(QString message); +}; + +#endif // _CUSDR_NETWORK_WIDGET_H diff --git a/Source/src/cusdr_radioParameter.h b/Source/src/cusdr_radioParameter.h new file mode 100644 index 0000000..a4f0abb --- /dev/null +++ b/Source/src/cusdr_radioParameter.h @@ -0,0 +1,35 @@ +/** +* @file cusdr_radioParameter.h +* @brief Radio parameter header for cuSDR +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-09-22 +*/ + +/* + * Copyright 2011 Hermann von Hasseln, DL3HVH + * + * Based on the complex type CPX by Philip A Covington, p.covington@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_RADIO_PARAMETER_H +#define _CUSDR_RADIO_PARAMETER_H + + + + +#endif // _CUSDR_RADIO_PARAMETER_H diff --git a/Source/src/cusdr_radioPopupWidget.cpp b/Source/src/cusdr_radioPopupWidget.cpp new file mode 100644 index 0000000..7dc002e --- /dev/null +++ b/Source/src/cusdr_radioPopupWidget.cpp @@ -0,0 +1,2670 @@ +/** +* @file cusdr_radioPopupWidget.cpp +* @brief Radio control popup widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-22 +*/ + +/* + * Copyright 2010-2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#include +//#include + +#define LOG_RADIOPOPUP + +// use: RADIOPOPUP_DEBUG + +#include "cusdr_radioPopupWidget.h" + +#define btn_height 14 +#define btn_height1 16 +#define btn_width 40 +#define btn_widthb 66 +#define btn_widths 34 + + +RadioPopupWidget::RadioPopupWidget(QWidget *parent, int rx) + : QWidget(parent) + , set(Settings::instance()) + , m_sticky(false) + , m_receiver(rx) + , m_currentRx(set->getCurrentReceiver()) + , m_minimumWidgetWidth(210) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); + + setMouseTracking(true); + setContentsMargins(4, 4, 4, 4); + setWindowOpacity(0.9); + + + //setFixedWidth(206); + //setFixedWidth(210); + //setMinimumHeight(100); + //setFixedHeight(240); + + setFocusPolicy(Qt::StrongFocus); + + QString style = QString::fromUtf8( + "border: 0px solid rgba(166, 196, 208, 255);" + //"border: 1px solid;"// rgba(166, 196, 208, 255);" + //"border-left-color: rgba(220, 120, 120, 255);" + //"border-top-color: rgba(220, 120, 120, 255);" + //"border-right-color: rgba(0, 0, 0, 255);" + //"border-bottom-color: rgba(0, 0, 0, 255);" + "color: rgb(166, 196, 208); " + //"background-color: rgba(40, 40, 40, 255); "); + "background-color: rgba(25, 25, 25, 255); "); + + setStyleSheet(style); + + fonts = new CFonts(this); + m_fonts = fonts->getFonts(); + + m_receiverDataList = set->getReceiverDataList(); + + m_hamBand = m_receiverDataList.at(m_receiver).hamBand; + //m_dspMode = m_receiverDataList.at(m_receiver).dspMode; + m_dspModeList = m_receiverDataList.at(m_receiver).dspModeList; + m_agcMode = m_receiverDataList.at(m_receiver).agcMode; + m_filterMode = m_receiverDataList.at(m_receiver).defaultFilterMode; + m_filterLo = m_receiverDataList.at(m_receiver).filterLo; + m_filterHi = m_receiverDataList.at(m_receiver).filterHi; + + m_spectrumAveraging = m_receiverDataList.at(m_receiver).spectrumAveraging; + m_panGrid = m_receiverDataList.at(m_receiver).panGrid; + m_peakHold = m_receiverDataList.at(m_receiver).peakHold; + m_panLocked = m_receiverDataList.at(m_receiver).panLocked; + m_clickVFO = m_receiverDataList.at(m_receiver).clickVFO; + m_showCross = m_receiverDataList.at(m_receiver).hairCross; + + m_panadapterMode = m_receiverDataList.at(m_receiver).panMode; + m_waterfallColorMode = m_receiverDataList.at(m_receiver).waterfallMode; + + m_lastCtrFrequencyList = m_receiverDataList.at(m_receiver).lastCenterFrequencyList; + m_lastVfoFrequencyList = m_receiverDataList.at(m_receiver).lastVfoFrequencyList; + + stickyBtn = new AeroButton("Lock", this); + stickyBtn->setRoundness(0); + stickyBtn->setGlass(false); + QColor col = QColor(35, 35, 35); + stickyBtn->setColor(col); + col = QColor(120, 120, 120); + stickyBtn->setHighlight(col); + col = QColor(160, 100, 100); + stickyBtn->setColorOn(col); + stickyBtn->setFixedSize(btn_width, btn_height1); + //stickyBtn->move(size().width() - btn_width - 2, 2); + stickyBtn->setBtnState(AeroButton::OFF); + CHECKED_CONNECT(stickyBtn, SIGNAL(clicked()), this, SLOT(setSticky())); + + createOptionsBtnGroup(); + createBandBtnGroup(); + createModeBtnGroup(); + createAgcBtnGroup(); + createFilterBtnWidgetA(); + createFilterBtnWidgetB(); + createFilterBtnWidgetC(); + + m_filterStackedWidget = new QStackedWidget(this); + m_filterStackedWidget->setContentsMargins(0, 0, 0, 0); + m_filterStackedWidget->setFixedHeight(30); + m_filterStackedWidget->addWidget(filterAWidget); + m_filterStackedWidget->addWidget(filterBWidget); + m_filterStackedWidget->addWidget(filterCWidget); + + + QString rxStr = tr(" Rx %1 "); + QLabel* rxLabel = new QLabel(rxStr.arg(m_receiver + 1)); + rxLabel->setStyleSheet("background-color: rgba(40, 40, 40, 255);"); + + QHBoxLayout* title = new QHBoxLayout(); + title->setContentsMargins(0, 0, 0, 0); + title->setSpacing(0); + title->addWidget(rxLabel); + title->addStretch(); + title->addWidget(stickyBtn); + + QVBoxLayout *mainLayout = new QVBoxLayout; + mainLayout->setSpacing(0); + mainLayout->setMargin(0); + mainLayout->addLayout(title); + mainLayout->addSpacing(16); + //mainLayout->addStretch(); + mainLayout->addLayout(optionsVBox); + mainLayout->addSpacing(16); + mainLayout->addLayout(bandVBox); + mainLayout->addSpacing(8); + mainLayout->addLayout(modeVBox); + mainLayout->addSpacing(8); + mainLayout->addWidget(m_filterStackedWidget); + mainLayout->addSpacing(16); + mainLayout->addLayout(agcVBox); + mainLayout->addStretch(); + + setLayout(mainLayout); + + // setup values from settings.ini + bandBtnList.at(m_hamBand)->setBtnState(AeroButton::ON); + bandBtnList.at(m_hamBand)->update(); + + dspModeChanged(this, 0, m_dspModeList.at(m_hamBand)); + agcModeChanged(this, 0, m_agcMode, false); + filterChanged(this, 0, m_filterLo, m_filterHi); + + DSPMode dspMode = m_dspModeList.at(m_hamBand); + if (dspMode == (DSPMode) LSB || dspMode == (DSPMode) USB || dspMode == (DSPMode) DIGU || dspMode == (DSPMode) DIGL) { + + m_filterStackedWidget->setCurrentIndex(0); + } + else + if (dspMode == (DSPMode) DSB || dspMode == (DSPMode) FMN || dspMode == (DSPMode) AM || dspMode == (DSPMode) SAM) { + + m_filterStackedWidget->setCurrentIndex(1); + } + else + if (dspMode == (DSPMode) CWL || dspMode == (DSPMode) CWU) { + + m_filterStackedWidget->setCurrentIndex(2); + } + + setupConnections(); + + m_timerID = 0; + m_closingTimer.start(); + m_timerID = startTimer(100); +} + +RadioPopupWidget::~RadioPopupWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); + + if (m_timerID) { + + killTimer(m_timerID); + m_timerID = 0; + } +} + +//QSize RadioPopupWidget::sizeHint() const { +// +// return QSize(m_minimumWidgetWidth, height()); +//} + +QSize RadioPopupWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void RadioPopupWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode)), + this, + SLOT(graphicModeChanged( + QObject *, + int, + PanGraphicsMode, + WaterfallColorMode))); + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(vfoFrequencyChanged(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(hamBandChanged(QObject *, int, bool, HamBand)), + this, + SLOT(bandChanged(QObject *, int, bool, HamBand))); + + CHECKED_CONNECT( + set, + SIGNAL(dspModeChanged(QObject *, int, DSPMode)), + this, + SLOT(dspModeChanged(QObject *, int, DSPMode))); + + CHECKED_CONNECT( + set, + SIGNAL(agcModeChanged(QObject *, int, AGCMode, bool)), + this, + SLOT(agcModeChanged(QObject *, int, AGCMode, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)), + this, + SLOT(filterChanged(QObject *, int, qreal, qreal))); +} + +void RadioPopupWidget::createOptionsBtnGroup() { + + //m_optionsLabel = new QLabel("Options:", this); + //m_optionsLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + //m_optionsLabel->setStyleSheet(set->getLabelStyle()); + + avgBtn = new AeroButton("Pan Avg", this); + avgBtn->setRoundness(10); + avgBtn->setFont(m_fonts.smallFont); + + if (m_spectrumAveraging) + avgBtn->setBtnState(AeroButton::ON); + else + avgBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + avgBtn, + SIGNAL(clicked()), + this, + SLOT(avgBtnClicked())); + + gridBtn = new AeroButton("Pan Grid", this); + gridBtn->setRoundness(10); + gridBtn->setFont(m_fonts.smallFont); + + if (m_panGrid) + gridBtn->setBtnState(AeroButton::ON); + else + gridBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + gridBtn, + SIGNAL(clicked()), + this, + SLOT(gridBtnClicked())); + + peakHoldBtn = new AeroButton("Peak Hold", this); + peakHoldBtn->setRoundness(10); + peakHoldBtn->setFont(m_fonts.smallFont); + peakHoldBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + peakHoldBtn, + SIGNAL(clicked()), + this, + SLOT(peakHoldBtnClicked())); + + lockPanBtn = new AeroButton("Lock Pan", this); + lockPanBtn->setRoundness(10); + lockPanBtn->setFont(m_fonts.smallFont); + + if (m_panLocked) + lockPanBtn->setBtnState(AeroButton::ON); + else + lockPanBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + lockPanBtn, + SIGNAL(clicked()), + this, + SLOT(panLockedBtnClicked())); + + clickVfoBtn = new AeroButton("Click VFO", this); + clickVfoBtn->setRoundness(10); + clickVfoBtn->setFont(m_fonts.smallFont); + + if (m_clickVFO) + clickVfoBtn->setBtnState(AeroButton::ON); + else + clickVfoBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + clickVfoBtn, + SIGNAL(clicked()), + this, + SLOT(clickVfoBtnClicked())); + + showCrossBtn = new AeroButton("Hair Cross", this); + showCrossBtn->setRoundness(10); + showCrossBtn->setFont(m_fonts.smallFont); + + if (m_showCross) + showCrossBtn->setBtnState(AeroButton::ON); + else + showCrossBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + showCrossBtn, + SIGNAL(clicked()), + this, + SLOT(hairCrossBtnClicked())); + + midToVfoBtn = new AeroButton("Mid = VFO", this); + midToVfoBtn->setRoundness(10); + midToVfoBtn->setFont(m_fonts.smallFont); + + CHECKED_CONNECT( + midToVfoBtn, + SIGNAL(clicked()), + this, + SLOT(midToVfoBtnClicked())); + + vfoToMidBtn = new AeroButton("VFO = Mid", this); + vfoToMidBtn->setRoundness(10); + vfoToMidBtn->setFont(m_fonts.smallFont); + + CHECKED_CONNECT( + vfoToMidBtn, + SIGNAL(clicked()), + this, + SLOT(vfoToMidBtnClicked())); + + m_PanLineBtn = new AeroButton("Line", this); + m_PanLineBtn->setRoundness(10); + m_PanLineBtn->setFont(m_fonts.smallFont); + panadapterBtnList.append(m_PanLineBtn); + + CHECKED_CONNECT( + m_PanLineBtn, + SIGNAL(clicked()), + this, + SLOT(panModeChanged())); + + m_PanFilledLineBtn = new AeroButton("Filled Line", this); + m_PanFilledLineBtn->setRoundness(10); + m_PanFilledLineBtn->setFont(m_fonts.smallFont); + panadapterBtnList.append(m_PanFilledLineBtn); + + CHECKED_CONNECT( + m_PanFilledLineBtn, + SIGNAL(clicked()), + this, + SLOT(panModeChanged())); + + m_PanSolidBtn = new AeroButton("Solid", this); + m_PanSolidBtn->setRoundness(10); + m_PanSolidBtn->setFont(m_fonts.smallFont); + panadapterBtnList.append(m_PanSolidBtn); + + CHECKED_CONNECT( + m_PanSolidBtn, + SIGNAL(clicked()), + this, + SLOT(panModeChanged())); + + switch (m_panadapterMode) { + + case (PanGraphicsMode) Line: + + m_PanLineBtn->setBtnState(AeroButton::ON); + m_PanFilledLineBtn->setBtnState(AeroButton::OFF); + m_PanSolidBtn->setBtnState(AeroButton::OFF); + break; + + case (PanGraphicsMode) FilledLine: + + m_PanFilledLineBtn->setBtnState(AeroButton::ON); + m_PanLineBtn->setBtnState(AeroButton::OFF); + m_PanSolidBtn->setBtnState(AeroButton::OFF); + break; + + case (PanGraphicsMode) Solid: + + m_PanSolidBtn->setBtnState(AeroButton::ON); + m_PanLineBtn->setBtnState(AeroButton::OFF); + m_PanFilledLineBtn->setBtnState(AeroButton::OFF); + break; + } + + + m_WaterfallSimpleBtn = new AeroButton("Simple", this); + m_WaterfallSimpleBtn->setRoundness(10); + m_WaterfallSimpleBtn->setFont(m_fonts.smallFont); + waterfallBtnList.append(m_WaterfallSimpleBtn); + + CHECKED_CONNECT( + m_WaterfallSimpleBtn, + SIGNAL(clicked()), + this, + SLOT(waterfallModeChanged())); + + m_WaterfallEnhancedBtn = new AeroButton("Enhanced", this); + m_WaterfallEnhancedBtn->setRoundness(10); + m_WaterfallEnhancedBtn->setFont(m_fonts.smallFont); + waterfallBtnList.append(m_WaterfallEnhancedBtn); + + CHECKED_CONNECT( + m_WaterfallEnhancedBtn, + SIGNAL(clicked()), + this, + SLOT(waterfallModeChanged())); + + switch (m_waterfallColorMode) { + + case (WaterfallColorMode) Simple: + + m_WaterfallSimpleBtn->setBtnState(AeroButton::ON); + m_WaterfallEnhancedBtn->setBtnState(AeroButton::OFF); + break; + + case (WaterfallColorMode) Enhanced: + + m_WaterfallSimpleBtn->setBtnState(AeroButton::OFF); + m_WaterfallEnhancedBtn->setBtnState(AeroButton::ON); + break; + } + + /*QHBoxLayout* hbox0 = new QHBoxLayout(); + hbox0->setContentsMargins(0, 0, 0, 0); + hbox0->setSpacing(0); + hbox0->addWidget(m_optionsLabel); + hbox0->addStretch();*/ + + QHBoxLayout* hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(avgBtn); + hbox1->addWidget(gridBtn); + hbox1->addWidget(peakHoldBtn); + + QHBoxLayout* hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(lockPanBtn); + hbox2->addWidget(clickVfoBtn); + hbox2->addWidget(showCrossBtn); + + QHBoxLayout* hbox3 = new QHBoxLayout(); + hbox3->setContentsMargins(0, 0, 0, 0); + hbox3->setSpacing(0); + hbox3->addWidget(midToVfoBtn); + hbox3->addWidget(vfoToMidBtn); + + QHBoxLayout* hbox4 = new QHBoxLayout(); + hbox4->setContentsMargins(0, 0, 0, 0); + hbox4->setSpacing(0); + hbox4->addWidget(m_PanLineBtn); + hbox4->addWidget(m_PanFilledLineBtn); + hbox4->addWidget(m_PanSolidBtn); + + QHBoxLayout* hbox5 = new QHBoxLayout(); + hbox5->setContentsMargins(0, 0, 0, 0); + hbox5->setSpacing(0); + hbox5->addWidget(m_WaterfallSimpleBtn); + hbox5->addWidget(m_WaterfallEnhancedBtn); + + optionsVBox = new QVBoxLayout; + optionsVBox->setSpacing(1); + //optionsVBox->addLayout(hbox0); + optionsVBox->addLayout(hbox1); + optionsVBox->addLayout(hbox2); + optionsVBox->addLayout(hbox3); + optionsVBox->addSpacing(4); + optionsVBox->addLayout(hbox4); + optionsVBox->addLayout(hbox5); +} + +void RadioPopupWidget::createBandBtnGroup() { + + band2200mBtn = new AeroButton("2200m", this); + bandBtnList.append(band2200mBtn); + CHECKED_CONNECT(band2200mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band630mBtn = new AeroButton("630 m", this); + bandBtnList.append(band630mBtn); + CHECKED_CONNECT(band630mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band160mBtn = new AeroButton("160 m", this); + bandBtnList.append(band160mBtn); + CHECKED_CONNECT(band160mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band80mBtn = new AeroButton("80 m", this); + bandBtnList.append(band80mBtn); + CHECKED_CONNECT(band80mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band60mBtn = new AeroButton("60 m", this); + bandBtnList.append(band60mBtn); + CHECKED_CONNECT(band60mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band40mBtn = new AeroButton("40 m", this); + bandBtnList.append(band40mBtn); + CHECKED_CONNECT(band40mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band30mBtn = new AeroButton("30 m", this); + bandBtnList.append(band30mBtn); + CHECKED_CONNECT(band30mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band20mBtn = new AeroButton("20 m", this); + bandBtnList.append(band20mBtn); + CHECKED_CONNECT(band20mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band17mBtn = new AeroButton("17 m", this); + bandBtnList.append(band17mBtn); + CHECKED_CONNECT(band17mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band15mBtn = new AeroButton("15 m", this); + bandBtnList.append(band15mBtn); + CHECKED_CONNECT(band15mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band12mBtn = new AeroButton("12 m", this); + bandBtnList.append(band12mBtn); + CHECKED_CONNECT(band12mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band10mBtn = new AeroButton("10 m", this); + bandBtnList.append(band10mBtn); + CHECKED_CONNECT(band10mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band6mBtn = new AeroButton("6 m", this); + bandBtnList.append(band6mBtn); + CHECKED_CONNECT(band6mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + bandGenBtn = new AeroButton("Gen", this); + bandBtnList.append(bandGenBtn); + CHECKED_CONNECT(bandGenBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + foreach (AeroButton *btn, bandBtnList) { + + btn->setRoundness(0); + btn->setFixedHeight(btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + btn->update(); + } + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(band2200mBtn); + hbox1->addWidget(band630mBtn); + hbox1->addWidget(band160mBtn); + hbox1->addWidget(band80mBtn); + hbox1->addWidget(band60mBtn); + hbox1->addWidget(band40mBtn); + hbox1->addWidget(band30mBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(band20mBtn); + hbox2->addWidget(band17mBtn); + hbox2->addWidget(band15mBtn); + hbox2->addWidget(band12mBtn); + hbox2->addWidget(band10mBtn); + hbox2->addWidget(band6mBtn); + hbox2->addWidget(bandGenBtn); + + bandVBox = new QVBoxLayout; + bandVBox->setSpacing(1); + bandVBox->addLayout(hbox1); + bandVBox->addLayout(hbox2); + +} + +void RadioPopupWidget::createModeBtnGroup() { + + lsbBtn = new AeroButton("LSB", this); + dspModeBtnList.append(lsbBtn); + CHECKED_CONNECT(lsbBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + usbBtn = new AeroButton("USB", this); + dspModeBtnList.append(usbBtn); + CHECKED_CONNECT(usbBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + dsbBtn = new AeroButton("DSB", this); + dspModeBtnList.append(dsbBtn); + CHECKED_CONNECT(dsbBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + cwlBtn = new AeroButton("CWL", this); + dspModeBtnList.append(cwlBtn); + CHECKED_CONNECT(cwlBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + cwuBtn = new AeroButton("CWU", this); + dspModeBtnList.append(cwuBtn); + CHECKED_CONNECT(cwuBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + fmnBtn = new AeroButton("FMN", this); + dspModeBtnList.append(fmnBtn); + CHECKED_CONNECT(fmnBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + amBtn = new AeroButton("AM", this); + dspModeBtnList.append(amBtn); + CHECKED_CONNECT(amBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + diguBtn = new AeroButton("DIGU", this); + dspModeBtnList.append(diguBtn); + CHECKED_CONNECT(diguBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + diglBtn = new AeroButton("DIGL", this); + dspModeBtnList.append(diglBtn); + CHECKED_CONNECT(diglBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + specBtn = new AeroButton("SPEC", this); + dspModeBtnList.append(specBtn); + CHECKED_CONNECT(specBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + samBtn = new AeroButton("SAM", this); + dspModeBtnList.append(samBtn); + CHECKED_CONNECT(samBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + drmBtn = new AeroButton("DRM", this); + dspModeBtnList.append(drmBtn); + CHECKED_CONNECT(drmBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + foreach (AeroButton *btn, dspModeBtnList) { + + btn->setRoundness(0); + btn->setFixedHeight(btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + btn->update(); + } + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(lsbBtn); + hbox1->addWidget(usbBtn); + hbox1->addWidget(dsbBtn); + hbox1->addWidget(cwlBtn); + hbox1->addWidget(cwuBtn); + hbox1->addWidget(fmnBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(amBtn); + hbox2->addWidget(diguBtn); + hbox2->addWidget(specBtn); + hbox2->addWidget(diglBtn); + hbox2->addWidget(samBtn); + hbox2->addWidget(drmBtn); + + modeVBox = new QVBoxLayout; + modeVBox->setSpacing(1); + modeVBox->addLayout(hbox1); + modeVBox->addLayout(hbox2); +} + +void RadioPopupWidget::createAgcBtnGroup() { + + agcOFF = new AeroButton("Off", this); + agcOFF->setRoundness(0); + agcOFF->setFixedSize(btn_widths, btn_height); + agcOFF->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcOFF); + CHECKED_CONNECT(agcOFF, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcLONG = new AeroButton("Long", this); + agcLONG->setRoundness(0); + agcLONG->setFixedSize(btn_widths, btn_height); + agcLONG->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcLONG); + CHECKED_CONNECT(agcLONG, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcSLOW = new AeroButton("Slow", this); + agcSLOW->setRoundness(0); + agcSLOW->setFixedSize(btn_widths, btn_height); + agcSLOW->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcSLOW); + CHECKED_CONNECT(agcSLOW, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcMED = new AeroButton("Med", this); + agcMED->setRoundness(0); + agcMED->setFixedSize(btn_widths, btn_height); + agcMED->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcMED); + CHECKED_CONNECT(agcMED, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcFAST = new AeroButton("Fast", this); + agcFAST->setRoundness(0); + agcFAST->setFixedSize(btn_widths, btn_height); + agcFAST->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcFAST); + CHECKED_CONNECT(agcFAST, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + agcUSER = new AeroButton("User", this); + agcUSER->setRoundness(0); + agcUSER->setFixedSize(btn_widths, btn_height); + agcUSER->setStyleSheet(set->getMiniButtonStyle()); + agcModeBtnList.append(agcUSER); + CHECKED_CONNECT(agcUSER, SIGNAL(clicked()), this, SLOT(agcModeChangedByBtn())); + + showAGCLines = new AeroButton("Show Lines", this); + showAGCLines->setRoundness(0); + showAGCLines->setFixedSize(btn_widthb, btn_height); + showAGCLines->setStyleSheet(set->getMiniButtonStyle()); + CHECKED_CONNECT(showAGCLines, SIGNAL(clicked()), this, SLOT(agcShowLinesChanged())); + + if (m_receiverDataList.at(m_receiver).agcLines) + showAGCLines->setBtnState(AeroButton::ON); + else + showAGCLines->setBtnState(AeroButton::OFF); + + QHBoxLayout* hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(agcOFF); + hbox1->addWidget(agcLONG); + hbox1->addWidget(agcSLOW); + hbox1->addWidget(agcMED); + hbox1->addWidget(agcFAST); + hbox1->addWidget(agcUSER); + + QHBoxLayout* hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(showAGCLines); + hbox2->addStretch(); + + agcVBox = new QVBoxLayout; + agcVBox->setSpacing(1); + agcVBox->addLayout(hbox1); + agcVBox->addLayout(hbox2); +} + +void RadioPopupWidget::createFilterBtnWidgetA() { + + filter1kBtnA = new AeroButton("1k", this); + filter1kBtnA->setObjectName("1k"); + filterBtnListA.append(filter1kBtnA); + CHECKED_CONNECT(filter1kBtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter1k8BtnA = new AeroButton("1k8", this); + filter1k8BtnA->setObjectName("1k8"); + filterBtnListA.append(filter1k8BtnA); + CHECKED_CONNECT(filter1k8BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k1BtnA = new AeroButton("2k1", this); + filter2k1BtnA->setObjectName("2k1"); + filterBtnListA.append(filter2k1BtnA); + CHECKED_CONNECT(filter2k1BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k4BtnA = new AeroButton("2k4", this); + filter2k4BtnA->setObjectName("2k4"); + filterBtnListA.append(filter2k4BtnA); + CHECKED_CONNECT(filter2k4BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k7BtnA = new AeroButton("2k7", this); + filter2k7BtnA->setObjectName("2k7"); + filterBtnListA.append(filter2k7BtnA); + CHECKED_CONNECT(filter2k7BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k9BtnA = new AeroButton("2k9", this); + filter2k9BtnA->setObjectName("2k9"); + filterBtnListA.append(filter2k9BtnA); + CHECKED_CONNECT(filter2k9BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter3k3BtnA = new AeroButton("3k3", this); + filter3k3BtnA->setObjectName("3k3"); + filterBtnListA.append(filter3k3BtnA); + CHECKED_CONNECT(filter3k3BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter3k8BtnA = new AeroButton("3k8", this); + filter3k8BtnA->setObjectName("3k8"); + filterBtnListA.append(filter3k8BtnA); + CHECKED_CONNECT(filter3k8BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter4k4BtnA = new AeroButton("4k4", this); + filter4k4BtnA->setObjectName("4k4"); + filterBtnListA.append(filter4k4BtnA); + CHECKED_CONNECT(filter4k4BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter5kBtnA = new AeroButton("5k", this); + filter5kBtnA->setObjectName("5k"); + filterBtnListA.append(filter5kBtnA); + CHECKED_CONNECT(filter5kBtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar1BtnA = new AeroButton("Var1", this); + filterVar1BtnA->setObjectName("Var1"); + filterBtnListA.append(filterVar1BtnA); + CHECKED_CONNECT(filterVar1BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar2BtnA = new AeroButton("Var2", this); + filterVar2BtnA->setObjectName("Var2"); + filterBtnListA.append(filterVar2BtnA); + CHECKED_CONNECT(filterVar2BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + foreach(AeroButton *btn, filterBtnListA) { + + btn->setRoundness(0); + btn->setFixedHeight(btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + //filterBtnListA.at(set->getCurrentDSPMode())->setBtnState(AeroButton::ON); + + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(filter5kBtnA); + hbox1->addWidget(filter4k4BtnA); + hbox1->addWidget(filter3k8BtnA); + hbox1->addWidget(filter3k3BtnA); + hbox1->addWidget(filter2k9BtnA); + hbox1->addWidget(filter2k7BtnA); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(filter2k4BtnA); + hbox2->addWidget(filter2k1BtnA); + hbox2->addWidget(filter1k8BtnA); + hbox2->addWidget(filter1kBtnA); + hbox2->addWidget(filterVar1BtnA); + hbox2->addWidget(filterVar2BtnA); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(0); + vbox->setMargin(0); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + filterAWidget = new QWidget(); + filterAWidget->setContentsMargins(0, 0, 0, 0); + filterAWidget->setLayout(vbox); +} + +void RadioPopupWidget::createFilterBtnWidgetB() { + + filter16kBtnB = new AeroButton("16k", this); + filterBtnListB.append(filter16kBtnB); + CHECKED_CONNECT(filter16kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter12kBtnB = new AeroButton("12k", this); + filterBtnListB.append(filter12kBtnB); + CHECKED_CONNECT(filter12kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter10kBtnB = new AeroButton("10k", this); + filterBtnListB.append(filter10kBtnB); + CHECKED_CONNECT(filter10kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter8kBtnB = new AeroButton("8k", this); + filterBtnListB.append(filter8kBtnB); + CHECKED_CONNECT(filter8kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter6k6BtnB = new AeroButton("6k6", this); + filterBtnListB.append(filter6k6BtnB); + CHECKED_CONNECT(filter6k6BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter5k2BtnB = new AeroButton("5k2", this); + filterBtnListB.append(filter5k2BtnB); + CHECKED_CONNECT(filter5k2BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter4kBtnB = new AeroButton("4k", this); + filterBtnListB.append(filter4kBtnB); + CHECKED_CONNECT(filter4kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter3k1BtnB = new AeroButton("3k1", this); + filterBtnListB.append(filter3k1BtnB); + CHECKED_CONNECT(filter3k1BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k9BtnB = new AeroButton("2k9", this); + filterBtnListB.append(filter2k9BtnB); + CHECKED_CONNECT(filter2k9BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k4BtnB = new AeroButton("2k4", this); + filterBtnListB.append(filter2k4BtnB); + CHECKED_CONNECT(filter2k4BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar1BtnB = new AeroButton("Var1", this); + filterBtnListB.append(filterVar1BtnB); + CHECKED_CONNECT(filterVar1BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar2BtnB = new AeroButton("Var2", this); + filterBtnListB.append(filterVar2BtnB); + CHECKED_CONNECT(filterVar2BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + foreach(AeroButton *btn, filterBtnListB) { + + btn->setRoundness(0); + btn->setFixedHeight(btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + //filterBtnListA.at(set->getCurrentDSPMode())->setBtnState(AeroButton::ON); + + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(filter16kBtnB); + hbox1->addWidget(filter12kBtnB); + hbox1->addWidget(filter10kBtnB); + hbox1->addWidget(filter8kBtnB); + hbox1->addWidget(filter6k6BtnB); + hbox1->addWidget(filter5k2BtnB); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(filter4kBtnB); + hbox2->addWidget(filter3k1BtnB); + hbox2->addWidget(filter2k9BtnB); + hbox2->addWidget(filter2k4BtnB); + hbox2->addWidget(filterVar1BtnB); + hbox2->addWidget(filterVar2BtnB); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(0); + vbox->setMargin(0); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + filterBWidget = new QWidget(); + filterBWidget->setContentsMargins(0, 0, 0, 0); + filterBWidget->setLayout(vbox); +} + +void RadioPopupWidget::createFilterBtnWidgetC() { + + filter1kBtnC = new AeroButton("1k", this); + filterBtnListC.append(filter1kBtnC); + CHECKED_CONNECT(filter1kBtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter800BtnC = new AeroButton("800", this); + filterBtnListC.append(filter800BtnC); + CHECKED_CONNECT(filter800BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter750BtnC = new AeroButton("750", this); + filterBtnListC.append(filter750BtnC); + CHECKED_CONNECT(filter750BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter600BtnC = new AeroButton("600", this); + filterBtnListC.append(filter600BtnC); + CHECKED_CONNECT(filter600BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter500BtnC = new AeroButton("500", this); + filterBtnListC.append(filter500BtnC); + CHECKED_CONNECT(filter500BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter400BtnC = new AeroButton("400", this); + filterBtnListC.append(filter400BtnC); + CHECKED_CONNECT(filter400BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter250BtnC = new AeroButton("250", this); + filterBtnListC.append(filter250BtnC); + CHECKED_CONNECT(filter250BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter100BtnC = new AeroButton("100", this); + filterBtnListC.append(filter100BtnC); + CHECKED_CONNECT(filter100BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter50BtnC = new AeroButton("50", this); + filterBtnListC.append(filter50BtnC); + CHECKED_CONNECT(filter50BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter25BtnC = new AeroButton("25", this); + filterBtnListC.append(filter25BtnC); + CHECKED_CONNECT(filter25BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar1BtnC = new AeroButton("Var1", this); + filterBtnListC.append(filterVar1BtnC); + CHECKED_CONNECT(filterVar1BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar2BtnC = new AeroButton("Var2", this); + filterBtnListC.append(filterVar2BtnC); + CHECKED_CONNECT(filterVar2BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + foreach(AeroButton *btn, filterBtnListC) { + + btn->setRoundness(0); + btn->setFixedHeight(btn_height); + btn->setStyleSheet(set->getMiniButtonStyle()); + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + //filterBtnListC.at(set)->getCurrentDSPMode())->setBtnState(AeroButton::ON); + + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setContentsMargins(0, 0, 0, 0); + hbox1->setSpacing(0); + hbox1->addWidget(filter1kBtnC); + hbox1->addWidget(filter800BtnC); + hbox1->addWidget(filter750BtnC); + hbox1->addWidget(filter600BtnC); + hbox1->addWidget(filter500BtnC); + hbox1->addWidget(filter400BtnC); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setContentsMargins(0, 0, 0, 0); + hbox2->setSpacing(0); + hbox2->addWidget(filter250BtnC); + hbox2->addWidget(filter100BtnC); + hbox2->addWidget(filter50BtnC); + hbox2->addWidget(filter25BtnC); + hbox2->addWidget(filterVar1BtnC); + hbox2->addWidget(filterVar2BtnC); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(0); + vbox->setMargin(0); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + filterCWidget = new QWidget(); + filterCWidget->setContentsMargins(0, 0, 0, 0); + filterCWidget->setLayout(vbox); +} + + +void RadioPopupWidget::ctrFrequencyChanged(QObject* sender, int mode, int rx, long frequency) { + + Q_UNUSED (sender) + Q_UNUSED (mode) + + if (m_receiver != rx) return; + m_ctrFrequency = frequency; + + HamBand band = getBandFromFrequency(set->getBandFrequencyList(), frequency); + m_lastCtrFrequencyList[(int) band] = m_ctrFrequency; +} + +void RadioPopupWidget::vfoFrequencyChanged(QObject* sender, int mode, int rx, long frequency) { + + Q_UNUSED (sender) + Q_UNUSED (mode) + + if (m_receiver != rx) return; + m_vfoFrequency = frequency; + + HamBand band = getBandFromFrequency(set->getBandFrequencyList(), frequency); + m_lastVfoFrequencyList[(int) band] = m_vfoFrequency; +} + +void RadioPopupWidget::bandChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + int btn = bandBtnList.indexOf(button); + + foreach(AeroButton *btn, bandBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + set->setHamBand(this, m_receiver, true, (HamBand) btn); + + QString str = button->text(); + if (str == "2200m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m2200)); + else + if (str == "630 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m630)); + else + if (str == "160 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m160)); + else + if (str == "80 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m80)); + else + if (str == "60 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m60)); + else + if (str == "40 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m40)); + else + if (str == "30 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m30)); + else + if (str == "20 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m20)); + else + if (str == "17 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m17)); + else + if (str == "15 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m15)); + else + if (str == "12 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m12)); + else + if (str == "10 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m10)); + else + if (str == "6 m") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(m6)); + else + if (str == "Gen") + set->setVFOFrequency(this, 2, m_receiver, m_lastVfoFrequencyList.at(gen)); +} + +void RadioPopupWidget::bandChanged(QObject *sender, int rx, bool byButton, HamBand band) { + + Q_UNUSED (byButton) + + if (sender == this) return; + + if (m_receiver != rx) return; + m_hamBand = band; + + foreach(AeroButton *btn, bandBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + bandBtnList.at(band)->setBtnState(AeroButton::ON); + bandBtnList.at(band)->update(); +} + +void RadioPopupWidget::dspModeChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + int btn = dspModeBtnList.indexOf(button); + + foreach(AeroButton *btn, dspModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + set->setDSPMode(this, m_receiver, (DSPMode) btn); + m_dspModeList[m_hamBand] = (DSPMode) btn; + filterChanged(this, m_receiver, m_filterLo, m_filterHi); + filterGroupChanged((DSPMode) btn); + + button->setBtnState(AeroButton::ON); + button->update(); +} + +void RadioPopupWidget::dspModeChanged(QObject *sender, int rx, DSPMode mode) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + m_dspModeList[m_hamBand] = mode; + + foreach(AeroButton *btn, dspModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + dspModeBtnList.at(mode)->setBtnState(AeroButton::ON); + dspModeBtnList.at(mode)->update(); +} + +void RadioPopupWidget::filterGroupChanged(DSPMode mode) { + + if (mode == 0 || mode == 1 || mode == 7 || mode == 9) { + + //m_filterStackedLayout->setCurrentIndex(0); + m_filterStackedWidget->setCurrentIndex(0); + } + else if (mode == 2 || mode == 5 || mode == 6 || mode == 10) { + + //m_filterStackedLayout->setCurrentIndex(1); + m_filterStackedWidget->setCurrentIndex(1); + } + else if (mode == 3 || mode == 4) { + + //m_filterStackedLayout->setCurrentIndex(2); + m_filterStackedWidget->setCurrentIndex(2); + } +} + +void RadioPopupWidget::filterChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + + QList btnList; + int filterList = 0; + + if (filterBtnListA.contains(button)) { + + btnList = filterBtnListA; + filterList = 0; + } + else if (filterBtnListB.contains(button)) { + + btnList = filterBtnListB; + filterList = 1; + } + else if (filterBtnListC.contains(button)) { + + btnList = filterBtnListC; + filterList = 2; + } + + foreach(AeroButton *btn, btnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + QString str = button->text(); + DSPMode dspMode = m_dspModeList.at(m_hamBand); + switch (filterList) { + + case 0: // filterBtnList A + + if (str == "1k") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -1150.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 1150.0f; + break; + + default: + break; + + } + } + else + if (str == "1k8") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -1950.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 1950.0f; + break; + + default: + break; + } + } + else + if (str == "2k1") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -2250.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 2250.0f; + break; + + default: + break; + + } + } + else + if (str == "2k4") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -2550.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 2550.0f; + break; + + default: + break; + + } + } + else + if (str == "2k7") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -2850.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 2850.0f; + break; + + default: + break; + + } + } + else + if (str == "2k9") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -3050.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 3050.0f; + break; + + default: + break; + + } + } + else + if (str == "3k3") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -3450.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 3450.0f; + break; + + default: + break; + + } + } + else + if (str == "3k8") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -3950.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 3950.0f; + break; + + default: + break; + } + } + else + if (str == "4k4") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -4550.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 4550.0f; + break; + + default: + break; + } + } + else + if (str == "5k") { + + switch (dspMode) { + + case (DSPMode) LSB: + m_filterLo = -5150.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 5150.0f; + break; + + default: + break; + } + } + break; + + case 1: // filterBtnList B + + if (str == "2k4") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -1200.0f; + m_filterHi = 1200.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + default: + break; + } + } + else + if (str == "2k9") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -1450.0f; + m_filterHi = 1450.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "3k1") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -1550.0f; + m_filterHi = 1550.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "4k") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "5k2") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -2600.0f; + m_filterHi = 2600.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "6k6") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -3300.0f; + m_filterHi = 3300.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "8k") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "10k") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -5000.0f; + m_filterHi = 5000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "12k") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -6000.0f; + m_filterHi = 6000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "16k") { + + switch (dspMode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -8000.0f; + m_filterHi = 8000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + break; + + case 2: // filterBtnList C + + if (str == "25") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -125.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 125.0f; + break; + + default: + break; + } + } + else + if (str == "50") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -150.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 150.0f; + break; + + default: + break; + } + } + else + if (str == "100") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -200.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 200.0f; + break; + + default: + break; + } + } + else + if (str == "250") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -350.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 350.0f; + break; + + default: + break; + } + } + else + if (str == "400") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -500.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 500.0f; + break; + + default: + break; + } + } + else + if (str == "500") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -600.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 600.0f; + break; + + default: + break; + } + } + else + if (str == "600") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -700.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 700.0f; + break; + + default: + break; + } + } + else + if (str == "750") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -850.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 850.0f; + break; + + default: + break; + } + } + else + if (str == "800") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -900.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 900.0f; + break; + + default: + break; + } + } + else + if (str == "1k") { + + switch (dspMode) { + + case (DSPMode) CWL: + m_filterLo = -1100.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 1100.0f; + break; + + default: + break; + } + } + break; + } + + set->setRXFilter(this, m_receiver, m_filterLo, m_filterHi); +} + +void RadioPopupWidget::filterChanged(QObject *sender, int rx, qreal low, qreal high) { + + Q_UNUSED(sender) + + if (m_receiver != rx) return; + m_filterLo = low; + m_filterHi = high; + + DSPMode dspMode = m_dspModeList.at(m_hamBand); + if (dspMode == (DSPMode ) LSB || dspMode == (DSPMode ) USB || dspMode == (DSPMode ) DIGU || dspMode == (DSPMode ) DIGL) { + + foreach(AeroButton *btn, filterBtnListA) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + if ((m_filterLo == -5150.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 5150.0)) { + filter5kBtnA->setBtnState(AeroButton::ON); + filter5kBtnA->update(); + } + else + if ((m_filterLo == -4550.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 4550.0)) { + filter4k4BtnA->setBtnState(AeroButton::ON); + filter4k4BtnA->update(); + } + else + if ((m_filterLo == -3950.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 3950.0)) { + filter3k8BtnA->setBtnState(AeroButton::ON); + filter3k8BtnA->update(); + } + else + if ((m_filterLo == -3450.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 3450.0)) { + filter3k3BtnA->setBtnState(AeroButton::ON); + filter3k3BtnA->update(); + } + else + if ((m_filterLo == -3050.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 3050.0)) { + filter2k9BtnA->setBtnState(AeroButton::ON); + filter2k9BtnA->update(); + } + else + if ((m_filterLo == -2850.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 2850.0)) { + filter2k7BtnA->setBtnState(AeroButton::ON); + filter2k7BtnA->update(); + } + else + if ((m_filterLo == -2550.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 2550.0)) { + filter2k4BtnA->setBtnState(AeroButton::ON); + filter2k4BtnA->update(); + } + else + if ((m_filterLo == -2250.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 2250.0)) { + filter2k1BtnA->setBtnState(AeroButton::ON); + filter2k1BtnA->update(); + } + else + if ((m_filterLo == -1950.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 1950.0)) { + filter1k8BtnA->setBtnState(AeroButton::ON); + filter1k8BtnA->update(); + } + else + if ((m_filterLo == -1150.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 1150.0)) { + filter1kBtnA->setBtnState(AeroButton::ON); + filter1kBtnA->update(); + } + } + else if (dspMode == (DSPMode ) DSB || dspMode == (DSPMode ) FMN || dspMode == (DSPMode ) AM || dspMode == (DSPMode ) SAM) { + + // filterGroupBBox + foreach(AeroButton *btn, filterBtnListB) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + if (m_filterLo == -8000.0 && m_filterHi == 8000.0) { + filter16kBtnB->setBtnState(AeroButton::ON); + filter16kBtnB->update(); + } + else + if (m_filterLo == -6000.0 && m_filterHi == 6000.0) { + filter12kBtnB->setBtnState(AeroButton::ON); + filter12kBtnB->update(); + } + else + if (m_filterLo == -5000.0 && m_filterHi == 5000.0) { + filter10kBtnB->setBtnState(AeroButton::ON); + filter10kBtnB->update(); + } + else + if (m_filterLo == -4000.0 && m_filterHi == 4000.0) { + filter8kBtnB->setBtnState(AeroButton::ON); + filter8kBtnB->update(); + } + else + if (m_filterLo == -3300.0 && m_filterHi == 3300.0) { + filter6k6BtnB->setBtnState(AeroButton::ON); + filter6k6BtnB->update(); + } + else + if (m_filterLo == -2600.0 && m_filterHi == 2600.0) { + filter5k2BtnB->setBtnState(AeroButton::ON); + filter5k2BtnB->update(); + } + else + if (m_filterLo == -2000.0 && m_filterHi == 2000.0) { + filter4kBtnB->setBtnState(AeroButton::ON); + filter4kBtnB->update(); + } + else + if (m_filterLo == -1550.0 && m_filterHi == 1550.0) { + filter3k1BtnB->setBtnState(AeroButton::ON); + filter3k1BtnB->update(); + } + else + if (m_filterLo == -1450.0 && m_filterHi == 1450.0) { + filter2k9BtnB->setBtnState(AeroButton::ON); + filter2k9BtnB->update(); + } + else + if (m_filterLo == -1200.0 && m_filterHi == 1200.0) { + filter2k4BtnB->setBtnState(AeroButton::ON); + filter2k4BtnB->update(); + } + } + else if (dspMode == (DSPMode ) CWL || dspMode == (DSPMode ) CWU) { + + // filterGroupCBox + foreach(AeroButton *btn, filterBtnListC) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + if ((m_filterLo == -1100.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 1100.0)) { + filter1kBtnC->setBtnState(AeroButton::ON); + filter1kBtnC->update(); + } + else + if ((m_filterLo == -900.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 900.0)) { + filter800BtnC->setBtnState(AeroButton::ON); + filter800BtnC->update(); + } + else + if ((m_filterLo == -850.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 850.0)) { + filter750BtnC->setBtnState(AeroButton::ON); + filter750BtnC->update(); + } + else + if ((m_filterLo == -700.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 700.0)) { + filter600BtnC->setBtnState(AeroButton::ON); + filter600BtnC->update(); + } + else + if ((m_filterLo == -600.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 600.0)) { + filter500BtnC->setBtnState(AeroButton::ON); + filter500BtnC->update(); + } + else + if ((m_filterLo == -500.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 500.0)) { + filter400BtnC->setBtnState(AeroButton::ON); + filter400BtnC->update(); + } + else + if ((m_filterLo == -350.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 350.0)) { + filter250BtnC->setBtnState(AeroButton::ON); + filter250BtnC->update(); + } + else + if ((m_filterLo == -200.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 200.0)) { + filter100BtnC->setBtnState(AeroButton::ON); + filter100BtnC->update(); + } + else + if ((m_filterLo == -150.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 150.0)) { + filter50BtnC->setBtnState(AeroButton::ON); + filter50BtnC->update(); + } + else + if ((m_filterLo == -125.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 125.0)) { + filter25BtnC->setBtnState(AeroButton::ON); + filter25BtnC->update(); + } + } +} + +void RadioPopupWidget::agcModeChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + int btn = agcModeBtnList.indexOf(button); + + foreach(AeroButton *btn, agcModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + set->setAGCMode(this, m_receiver, (AGCMode) btn); + m_agcMode = (AGCMode) btn; + + button->setBtnState(AeroButton::ON); + button->update(); +} + +void RadioPopupWidget::agcModeChanged(QObject *sender, int rx, AGCMode mode, bool hang) { + + Q_UNUSED(sender) + Q_UNUSED(hang) + + if (m_receiver != rx) return; + m_agcMode = mode; + + foreach(AeroButton *btn, agcModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + agcModeBtnList.at(mode)->setBtnState(AeroButton::ON); + agcModeBtnList.at(mode)->update(); +} + +void RadioPopupWidget::agcShowLinesChanged() { + + if (showAGCLines->btnState() == AeroButton::OFF) { + + showAGCLines->setBtnState(AeroButton::ON); + set->setAGCShowLines(this, m_receiver, true); + } + else { + + showAGCLines->setBtnState(AeroButton::OFF); + set->setAGCShowLines(this, m_receiver, false); + } +} + +void RadioPopupWidget::avgBtnClicked() { + + if (avgBtn->btnState() == AeroButton::OFF) { + + avgBtn->setBtnState(AeroButton::ON); + m_spectrumAveraging = true; + set->setSpectrumAveraging(this, m_receiver, true); + } + else { + + avgBtn->setBtnState(AeroButton::OFF); + m_spectrumAveraging = false; + set->setSpectrumAveraging(this, m_receiver, false); + } +} + +void RadioPopupWidget::gridBtnClicked() { + + if (gridBtn->btnState() == AeroButton::OFF) { + + gridBtn->setBtnState(AeroButton::ON); + m_panGrid = true; + set->setPanGrid(true, m_receiver); + } + else { + + gridBtn->setBtnState(AeroButton::OFF); + m_panGrid = false; + set->setPanGrid(false, m_receiver); + } +} + +void RadioPopupWidget::peakHoldBtnClicked() { + + if (peakHoldBtn->btnState() == AeroButton::OFF) { + + peakHoldBtn->setBtnState(AeroButton::ON); + m_peakHold = true; + set->setPeakHold(true, m_receiver); + } + else { + + peakHoldBtn->setBtnState(AeroButton::OFF); + m_peakHold = false; + set->setPeakHold(false, m_receiver); + } +} + +void RadioPopupWidget::panLockedBtnClicked() { + + if (lockPanBtn->btnState() == AeroButton::OFF) { + + lockPanBtn->setBtnState(AeroButton::ON); + m_panLocked = true; + set->setPanLocked(true, m_receiver); + } + else { + + lockPanBtn->setBtnState(AeroButton::OFF); + m_panLocked = false; + set->setPanLocked(false, m_receiver); + } +} + +void RadioPopupWidget::clickVfoBtnClicked() { + + if (clickVfoBtn->btnState() == AeroButton::OFF) { + + clickVfoBtn->setBtnState(AeroButton::ON); + m_clickVFO = true; + set->setClickVFO(true, m_receiver); + } + else { + + clickVfoBtn->setBtnState(AeroButton::OFF); + m_clickVFO = false; + set->setClickVFO(false, m_receiver); + } +} + +void RadioPopupWidget::hairCrossBtnClicked() { + + if (showCrossBtn->btnState() == AeroButton::OFF) { + + showCrossBtn->setBtnState(AeroButton::ON); + m_showCross = true; + set->setHairCross(true, m_receiver); + } + else { + + showCrossBtn->setBtnState(AeroButton::OFF); + m_showCross = false; + set->setHairCross(false, m_receiver); + } +} + +void RadioPopupWidget::midToVfoBtnClicked() { + + emit midToVfoBtnEvent(); +} + +void RadioPopupWidget::vfoToMidBtnClicked() { + + emit vfoToMidBtnEvent(); +} + +void RadioPopupWidget::setCurrentReceiver(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (m_receiver == value) return; + m_receiver = value; + + TReceiver rxData = set->getReceiverDataList().at(m_receiver); + + if (m_hamBand != rxData.hamBand) { + m_hamBand = rxData.hamBand; + + foreach(AeroButton *btn, bandBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + AeroButton *button = bandBtnList.at(m_hamBand); + button->setBtnState(AeroButton::ON); + button->update(); + + } + + DSPMode dspMode = m_dspModeList.at(m_hamBand); + if (dspMode != rxData.dspModeList.at(m_hamBand)) { + + dspMode = rxData.dspModeList.at(m_hamBand); + + foreach(AeroButton *btn, dspModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + AeroButton *button = dspModeBtnList.at(dspMode); + button->setBtnState(AeroButton::ON); + button->update(); + + filterGroupChanged(dspMode); + filterChanged(this, m_receiver, m_filterLo, m_filterHi); + } + + if (m_agcMode != rxData.agcMode) { + m_agcMode = rxData.agcMode; + } + + if (m_filterLo != rxData.filterLo || m_filterHi != rxData.filterHi) { + + m_filterLo = rxData.filterLo; + m_filterHi = rxData.filterHi; + filterChanged(this, m_receiver, m_filterLo, m_filterHi); + } +} + +void RadioPopupWidget::setSticky() { + + if (stickyBtn->btnState() == AeroButton::OFF) { + + stickyBtn->setBtnState(AeroButton::ON); + stickyBtn->setText("Unlock"); + m_sticky = true; + } + else { + + stickyBtn->setBtnState(AeroButton::OFF); + stickyBtn->setText("Lock"); + m_sticky = false; + } +} + +void RadioPopupWidget::panModeChanged() { + + AeroButton *button = qobject_cast(sender()); + int btnHit = panadapterBtnList.indexOf(button); + + foreach(AeroButton *btn, panadapterBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (btnHit) { + + case 0: + m_panadapterMode = (PanGraphicsMode) Line; + break; + + case 1: + m_panadapterMode = (PanGraphicsMode) FilledLine; + break; + + case 2: + m_panadapterMode = (PanGraphicsMode) Solid; + break; + } + + set->setGraphicsState(this, m_receiver, m_panadapterMode, m_waterfallColorMode); +} + +void RadioPopupWidget::waterfallModeChanged() { + + AeroButton *button = qobject_cast(sender()); + int btnHit = waterfallBtnList.indexOf(button); + + foreach(AeroButton *btn, waterfallBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + switch (btnHit) { + + case 0: + m_waterfallColorMode = (WaterfallColorMode) Simple; + break; + + case 1: + m_waterfallColorMode = (WaterfallColorMode) Enhanced; + break; + } + + set->setGraphicsState(this, m_receiver, m_panadapterMode, m_waterfallColorMode); +} + +// ********************** +bool RadioPopupWidget::showPopupWidget(QObject *sender, QPoint position) { + + Q_UNUSED(sender) + + m_mouseOver = true; + show(); + + QDesktopWidget *desktop = QApplication::desktop(); + QRect desktopRect = desktop->availableGeometry(desktop->screenNumber()); + + position.setX(position.x() - frameGeometry().width() / 2); + position.setY(position.y() - frameGeometry().height() / 2); + + move(position); + + // stop us being lost off the edge of the screen + if (frameGeometry().right() > desktopRect.right()) move(QPoint(desktopRect.right() - frameGeometry().width(), frameGeometry().top())); + if (frameGeometry().bottom() > desktopRect.bottom()) move(QPoint(frameGeometry().left(), desktopRect.bottom() - frameGeometry().height())); + if (frameGeometry().left() < desktopRect.left()) move(QPoint(desktopRect.left(), frameGeometry().top())); + if (frameGeometry().top() < desktopRect.top()) move(QPoint(frameGeometry().left(), desktopRect.top())); + + setFocus(); + + return true; +} + +void RadioPopupWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state +) { + Q_UNUSED(sender) + Q_UNUSED(err) + Q_UNUSED(hwmode) + Q_UNUSED(mode) + Q_UNUSED(state) + +} + +void RadioPopupWidget::graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallMode) +{ + Q_UNUSED (sender) + Q_UNUSED (rx) + + bool change = false; + + if (m_panadapterMode != panMode) { + + m_panadapterMode = panMode; + change = true; + } + + if (m_waterfallColorMode != waterfallMode) { + + m_waterfallColorMode = waterfallMode; + change = true; + } + + if (!change) return; + + update(); +} + +void RadioPopupWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void RadioPopupWidget::showEvent(QShowEvent *event) { + + m_closingTimer.restart(); + //emit showEvent(this); + + QWidget::showEvent(event); +} + +void RadioPopupWidget::hideEvent(QHideEvent *event) { + + //emit hidingEvent(this); + QWidget::hideEvent(event); +} + +void RadioPopupWidget::paintEvent(QPaintEvent *event) { + + QWidget::paintEvent(event); +} + +void RadioPopupWidget::resizeEvent(QResizeEvent *event) { + + createBackground(event->size()); + QWidget::resizeEvent(event); +} + +void RadioPopupWidget::mousePressEvent(QMouseEvent *event) { + + m_closingTimer.restart(); + + m_mouseDownPos = QCursor::pos(); + m_mouseDownWindowPos = pos(); + + QWidget::mousePressEvent(event); +} + +void RadioPopupWidget::mouseMoveEvent(QMouseEvent *event) { + + m_closingTimer.restart(); + + if (event->buttons() == Qt::LeftButton) { + + QPoint delta = QCursor::pos() - m_mouseDownPos; + QPoint new_pos = m_mouseDownWindowPos + delta; + + QDesktopWidget *desktop = QApplication::desktop(); +// QRect desktopRect = desktop->availableGeometry(); + QRect desktopRect = desktop->availableGeometry(desktop->screenNumber()); +// QRect desktopRect = desktop->screenGeometry(desktop->screenNumber()); +// QRect desktopRect = desktop->geometry(); + + QRect new_rect(QPoint(0, 0), size()); + new_rect.moveTopLeft(new_pos); + + // stop us being lost off the edge of the screen + if (new_rect.right() > desktopRect.right()) new_rect.moveLeft(desktopRect.right() - (new_rect.width() - 1)); + if (new_rect.bottom() > desktopRect.bottom()) new_rect.moveTop(desktopRect.bottom() - (new_rect.height() - 1)); + if (new_rect.left() < desktopRect.left()) new_rect.moveLeft(desktopRect.left()); + if (new_rect.top() < desktopRect.top()) new_rect.moveTop(desktopRect.top()); + + move(new_rect.topLeft()); + } + + QWidget::mouseMoveEvent(event); +} + +void RadioPopupWidget::mouseReleaseEvent(QMouseEvent *event) { + + m_closingTimer.restart(); + QWidget::mouseReleaseEvent(event); +} + +void RadioPopupWidget::enterEvent(QEvent *event) { + + m_closingTimer.restart(); + m_mouseOver = true; + QWidget::enterEvent(event); +} + +void RadioPopupWidget::leaveEvent(QEvent *event) { + + if (!m_sticky) { + + m_closingTimer.restart(); + m_mouseOver = false; + } + QWidget::leaveEvent(event); +} + +void RadioPopupWidget::timerEvent(QTimerEvent *event) { + + int timerId = event->timerId(); + + if (m_timerID > 0 && timerId == m_timerID) { + + if (!m_mouseOver && isVisible()) { + + if (m_closingTimer.elapsed() >= 100) close(); + } + return; + } + + QWidget::timerEvent(event); +} + +bool RadioPopupWidget::event(QEvent *event) { + + switch (event->type()) + { + + case QEvent::NonClientAreaMouseButtonPress: + // mouse press on the title bar or window edges + m_closingTimer.restart(); + m_mouseOver = true; + break; + + case QEvent::NonClientAreaMouseMove: + // mouse move on the title bar or window edges + m_closingTimer.restart(); +// mouse_over = true; + break; + + case QEvent::NonClientAreaMouseButtonRelease: + // mouse press on the title bar or window edges + m_closingTimer.restart(); + m_mouseOver = false; + break; + + default: + break; + } + + return QWidget::event(event); +} + +void RadioPopupWidget::createBackground(QSize size) { + + if (size.width() <= 0 || size.height() <= 0) return; + + QFont font(this->font()); + font.setPixelSize(12); + + QFontMetrics fm(font); + int font_height = fm.height(); + + QImage image = QImage(size, QImage::Format_ARGB32_Premultiplied); + if (image.isNull()) return; + + image.fill(QColor(0, 0, 0, 0).rgba()); + + QPainter painter(&image); + painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::Antialiasing | QPainter::TextAntialiasing, true); + painter.setFont(font); + + painter.fillRect(image.rect(), QColor(35, 35, 35)); + //painter.fillRect(image.rect(), QColor(0, 60, 129)); + + QString titleStr = windowTitle(); + QRect title_bar_rect(0, 0, image.width(), font_height + 6); + + QLinearGradient title_bar_gradient(0, 0, 0, 1); + title_bar_gradient.setCoordinateMode(QGradient::ObjectBoundingMode); + title_bar_gradient.setSpread(QGradient::PadSpread); + title_bar_gradient.setColorAt(0.0, QColor(100, 110, 128)); + title_bar_gradient.setColorAt(0.4, QColor(74, 80, 90)); + title_bar_gradient.setColorAt(0.6, QColor(56, 62, 70)); + title_bar_gradient.setColorAt(1.0, QColor(48, 56, 64)); + painter.setPen(Qt::NoPen); + painter.setBrush(QBrush(title_bar_gradient)); + + title_bar_rect.adjust(1, 1, 1, 1); + painter.setPen(Qt::black); + painter.drawText(title_bar_rect, Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, titleStr); + title_bar_rect.adjust(-1, -1, -1, -1); + painter.setPen(Qt::white); + painter.drawText(title_bar_rect, Qt::TextSingleLine | Qt::TextDontClip | Qt::AlignVCenter | Qt::AlignLeft, titleStr); + + painter.setPen(QColor(255, 255, 255, 64)); + //painter.setPen(QColor(0, 255, 255, 255)); + painter.drawLine(0, 0, image.width() - 1, 0); // top line + painter.drawLine(0, 0, 0, image.height() - 1); // left line + painter.setPen(QColor(0, 0, 0, 64)); + painter.drawLine(0, image.height() - 1, image.width() - 1, image.height() - 1); // bottom line + painter.drawLine(image.width() - 1, 0, image.width() - 1, image.height() - 1); // right line + + painter.end(); + + QPalette palette; + palette.setBrush(backgroundRole(), QBrush(image)); + setPalette(palette); + setAutoFillBackground(true); +} diff --git a/Source/src/cusdr_radioPopupWidget.h b/Source/src/cusdr_radioPopupWidget.h new file mode 100644 index 0000000..892bc12 --- /dev/null +++ b/Source/src/cusdr_radioPopupWidget.h @@ -0,0 +1,314 @@ +/* +* @file cusdr_radioPopupWidget.h +* @brief Radio control popup widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-22 +*/ + +/* + * Copyright 2010-2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_RADIO_POPUP_WIDGET_H +#define _CUSDR_RADIO_POPUP_WIDGET_H + +#ifdef LOG_RADIOPOPUP +#define RADIOPOPUP_DEBUG qDebug().nospace() << "RadioPopup::\t" +#else +#define RADIOPOPUP_DEBUG nullDebug() +#endif + +#include +//#include +//#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_fonts.h" + +class RadioPopupWidget : public QWidget { + + Q_OBJECT + +public: + RadioPopupWidget(QWidget *parent = 0, int rx = 0); + ~RadioPopupWidget(); + + bool getSpectrumAveraging() { return m_spectrumAveraging; } + bool getPanGridStatus() { return m_panGrid; } + bool getPeakHoldStatus() { return m_peakHold; } + +public slots: + //QSize sizeHint() const; + QSize minimumSizeHint() const; + + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + bool showPopupWidget(QObject *sender, QPoint position); + +protected: + void showEvent(QShowEvent *event); + void hideEvent(QHideEvent *event); + void closeEvent(QCloseEvent *event); + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void timerEvent(QTimerEvent *event); + bool event(QEvent *event); + +private: + Settings* set; + + QTime m_closingTimer; + + CFonts* fonts; + TFonts m_fonts; + + PanGraphicsMode m_panadapterMode; + WaterfallColorMode m_waterfallColorMode; + + QVBoxLayout* optionsVBox; + QVBoxLayout* bandVBox; + QVBoxLayout* modeVBox; + QVBoxLayout* agcVBox; + //QVBoxLayout* mercuryBtnVBox(); + + QWidget* filterAWidget; + QWidget* filterBWidget; + QWidget* filterCWidget; + + QStackedLayout* m_filterStackedLayout; + QStackedWidget* m_filterStackedWidget; + + QList filterBtnListA; + QList filterBtnListB; + QList filterBtnListC; + QList panadapterBtnList; + QList waterfallBtnList; + + QLabel* m_optionsLabel; + + AeroButton* stickyBtn; + + AeroButton* lockPanBtn; + AeroButton* clickVfoBtn; + AeroButton* showCrossBtn; + AeroButton* midToVfoBtn; + AeroButton* vfoToMidBtn; + AeroButton* avgBtn; + AeroButton* peakHoldBtn; + AeroButton* gridBtn; + + AeroButton* m_PanLineBtn; + AeroButton* m_PanFilledLineBtn; + AeroButton* m_PanSolidBtn; + AeroButton* m_WaterfallSimpleBtn; + AeroButton* m_WaterfallEnhancedBtn; + + AeroButton* band2200mBtn; + AeroButton* band630mBtn; + AeroButton* band160mBtn; + AeroButton* band80mBtn; + AeroButton* band60mBtn; + AeroButton* band40mBtn; + AeroButton* band30mBtn; + AeroButton* band20mBtn; + AeroButton* band17mBtn; + AeroButton* band15mBtn; + AeroButton* band12mBtn; + AeroButton* band10mBtn; + AeroButton* band6mBtn; + AeroButton* bandGenBtn; + //AeroButton* bandxxBtn; + + QList bandBtnList; + + AeroButton* lsbBtn; + AeroButton* usbBtn; + AeroButton* dsbBtn; + AeroButton* cwlBtn; + AeroButton* cwuBtn; + AeroButton* fmnBtn; + AeroButton* amBtn; + AeroButton* diguBtn; + AeroButton* specBtn; + AeroButton* diglBtn; + AeroButton* samBtn; + AeroButton* drmBtn; + + QList dspModeBtnList; + + AeroButton* showAGCLines; + AeroButton* agcOFF; + AeroButton* agcLONG; + AeroButton* agcSLOW; + AeroButton* agcMED; + AeroButton* agcFAST; + AeroButton* agcUSER; + + QList agcModeBtnList; + + AeroButton* filter1kBtnA; + AeroButton* filter1k8BtnA; + AeroButton* filter2k1BtnA; + AeroButton* filter2k4BtnA; + AeroButton* filter2k7BtnA; + AeroButton* filter2k9BtnA; + AeroButton* filter3k3BtnA; + AeroButton* filter3k8BtnA; + AeroButton* filter4k4BtnA; + AeroButton* filter5kBtnA; + AeroButton* filterVar1BtnA; + AeroButton* filterVar2BtnA; + + AeroButton* filter2k4BtnB; + AeroButton* filter2k9BtnB; + AeroButton* filter3k1BtnB; + AeroButton* filter4kBtnB; + AeroButton* filter5k2BtnB; + AeroButton* filter6k6BtnB; + AeroButton* filter8kBtnB; + AeroButton* filter10kBtnB; + AeroButton* filter12kBtnB; + AeroButton* filter16kBtnB; + AeroButton* filterVar1BtnB; + AeroButton* filterVar2BtnB; + + AeroButton* filter25BtnC; + AeroButton* filter50BtnC; + AeroButton* filter100BtnC; + AeroButton* filter250BtnC; + AeroButton* filter400BtnC; + AeroButton* filter500BtnC; + AeroButton* filter600BtnC; + AeroButton* filter750BtnC; + AeroButton* filter800BtnC; + AeroButton* filter1kBtnC; + AeroButton* filterVar1BtnC; + AeroButton* filterVar2BtnC; + + QLabel* m_rxLabel; + + //QIcon agc_left; + //QIcon agc_right; + + QList m_receiverDataList; + QList m_dspModeList; + + HamBand m_hamBand; + //DSPMode m_dspMode; + AGCMode m_agcMode; + TDefaultFilterMode m_filterMode; + + QPoint m_mouseDownPos; + QPoint m_mouseDownWindowPos; + + bool m_mouseOver; + + //QList m_lastFrequencyList; + QList m_lastCtrFrequencyList; + QList m_lastVfoFrequencyList; + + long m_ctrFrequency; + long m_vfoFrequency; + + bool m_sticky; + bool m_spectrumAveraging; + bool m_panGrid; + bool m_peakHold; + bool m_panLocked; + bool m_clickVFO; + bool m_showCross; + + qreal m_filterLo; + qreal m_filterHi; + + int m_timerID; + int m_receiver; + int m_currentRx; + int current_band; + int current_dsp_mode; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + void createBackground(QSize size); + +private slots: + void graphicModeChanged( + QObject* sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setSticky(); + void createOptionsBtnGroup(); + void createBandBtnGroup(); + void createModeBtnGroup(); + void createAgcBtnGroup(); + void createFilterBtnWidgetA(); + void createFilterBtnWidgetB(); + void createFilterBtnWidgetC(); + + //QLabel *createLabel(const QString &text); + + void avgBtnClicked(); + void gridBtnClicked(); + void peakHoldBtnClicked(); + void panLockedBtnClicked(); + void clickVfoBtnClicked(); + void hairCrossBtnClicked(); + void midToVfoBtnClicked(); + void vfoToMidBtnClicked(); + void panModeChanged(); + void waterfallModeChanged(); + + void setCurrentReceiver(QObject *sender, int value); + void ctrFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + void vfoFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + void bandChangedByBtn(); + void bandChanged(QObject *sender, int rx, bool byButton, HamBand band); + void dspModeChangedByBtn(); + void dspModeChanged(QObject *sender, int rx, DSPMode mode); + void agcModeChangedByBtn(); + void agcModeChanged(QObject *sender, int rx, AGCMode mode, bool hang); + void agcShowLinesChanged(); + void filterChangedByBtn(); + void filterChanged(QObject *sender, int rx, qreal low, qreal high); + void filterGroupChanged(DSPMode mode); + +signals: + void showEvent(QObject *sender); + void hideEvent(QObject *sender); + void closeEvent(QObject *sender); + void newMessage(QString msg); + void midToVfoBtnEvent(); + void vfoToMidBtnEvent(); +}; + +#endif // _CUSDR_RADIO_POPUP_WIDGET_H diff --git a/Source/src/cusdr_radioTabWidget.cpp b/Source/src/cusdr_radioTabWidget.cpp new file mode 100644 index 0000000..da58064 --- /dev/null +++ b/Source/src/cusdr_radioTabWidget.cpp @@ -0,0 +1,185 @@ +/** +* @file cusdr_radioTabWidget.cpp +* @brief Radio settings tab widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-29 +*/ + +/* + * + * Copyright 2010 - 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cusdr_radioTabWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +RadioTabWidget::RadioTabWidget(QWidget *parent) + : QTabWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + setStyleSheet(set->getTabWidgetStyle()); + setContentsMargins(4, 4, 4, 0); + setMouseTracking(true); + + m_radioWidget = new RadioWidget(this); + m_agcWidget = new AGCOptionsWidget(this); + m_transmitTabWidget = new TransmitTabWidget(this); + + this->addTab(m_radioWidget, " General "); + this->addTab(m_agcWidget, " AGC "); + this->addTab(m_transmitTabWidget, " Tx Ctrl "); + + if (!set->getPenelopePresence() && !set->getPennyLanePresence() && (set->getHWInterface() != QSDR::Hermes)) { + + setTabEnabled(2, false); + } + + setupConnections(); +} + +RadioTabWidget::~RadioTabWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize RadioTabWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize RadioTabWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void RadioTabWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(penelopePresenceChanged(bool)), + this, + SLOT(setPennyPresence(bool))); + + CHECKED_CONNECT( + set, + SIGNAL(pennyLanePresenceChanged(bool)), + this, + SLOT(setPennyPresence(bool))); +} + +void RadioTabWidget::systemStateChanged( + QObject *sender, /*!<[in] the sender of the signal. */ + QSDR::_Error err, /*!<[in] error state. */ + QSDR::_HWInterfaceMode hwmode, /*!<[in] HPSDR interface (Metis, Hermes, none). */ + QSDR::_ServerMode mode, /*!<[in] server mode. */ + QSDR::_DataEngineState state /*!<[in] data engine state. */ +) { + Q_UNUSED (sender) + Q_UNUSED (err) + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_hwInterface == QSDR::Hermes) + setTabEnabled(2, true); + else + setTabEnabled(2, false); + + if (m_serverMode != mode) + m_serverMode = mode; + + if (m_dataEngineState != state) + m_dataEngineState = state; +} + +void RadioTabWidget::setPennyPresence(bool value) { + + setTabEnabled(2, value); +} + +void RadioTabWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void RadioTabWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +void RadioTabWidget::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void RadioTabWidget::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void RadioTabWidget::mouseMoveEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void RadioTabWidget::mousePressEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void RadioTabWidget::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + + diff --git a/Source/src/cusdr_radioTabWidget.h b/Source/src/cusdr_radioTabWidget.h new file mode 100644 index 0000000..79a8f46 --- /dev/null +++ b/Source/src/cusdr_radioTabWidget.h @@ -0,0 +1,100 @@ +/** +* @file cusdr_radioTabWidget.h +* @brief Radio settings tab widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-09-29 +*/ + +/* + * + * Copyright 2010 - 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_RADIO_TABWIDGET_H +#define _CUSDR_RADIO_TABWIDGET_H + +//#include +//#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_radioWidget.h" +#include "cusdr_agcWidget.h" +#include "cusdr_transmitTabWidget.h" + + +class RadioTabWidget : public QTabWidget { + + Q_OBJECT + +public: + RadioTabWidget(QWidget *parent = 0); + ~RadioTabWidget(); + + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + Settings* set; + + QSDR::_Error m_error; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QString m_message; + + RadioWidget *m_radioWidget; + AGCOptionsWidget *m_agcWidget; + TransmitTabWidget *m_transmitTabWidget; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + +private slots: + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setPennyPresence(bool value); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString message); +}; + +#endif // _CUSDR_RADIO_TABWIDGET_H diff --git a/Source/src/cusdr_radioWidget.cpp b/Source/src/cusdr_radioWidget.cpp new file mode 100644 index 0000000..a62a5f7 --- /dev/null +++ b/Source/src/cusdr_radioWidget.cpp @@ -0,0 +1,2301 @@ +/** +* @file cusdr_radioWidget.cpp +* @brief Radio control widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-10 +*/ + +/* + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "cusdr_radioWidget.h" + +#define btn_height 14 +#define btn_width 60 +#define btn_widthb 70 +#define btn_widths 34 + + +RadioWidget::RadioWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_currentRx(set->getCurrentReceiver()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + //setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 0, 4, 0); + + m_receiverDataList = set->getReceiverDataList(); + + m_hamBand = m_receiverDataList.at(0).hamBand; + //m_dspMode = m_receiverDataList.at(0).dspMode; + m_dspModeList = m_receiverDataList.at(0).dspModeList; + //m_agcMode = m_receiverDataList.at(0).agcMode; + m_filterMode = m_receiverDataList.at(0).defaultFilterMode; + m_filterLo = m_receiverDataList.at(0).filterLo; + m_filterHi = m_receiverDataList.at(0).filterHi; + + m_lastCtrFrequencyList = m_receiverDataList.at(0).lastCenterFrequencyList; + m_lastVfoFrequencyList = m_receiverDataList.at(0).lastVfoFrequencyList; + + createBandBtnGroup(); + createModeBtnGroup(); + createFilterBtnGroupA(); + createFilterBtnGroupB(); + createFilterBtnGroupC(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setContentsMargins(0, 0, 0, 0); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(0); + hbox1->setMargin(0); + hbox1->addStretch(); + hbox1->addWidget(bandGroupBox); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addStretch(); + hbox2->addWidget(modeGroupBox); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(0); + hbox3->setMargin(0); + hbox3->addStretch(); + hbox3->addWidget(filterGroupABox); + + QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(0); + hbox4->setMargin(0); + hbox4->addStretch(); + hbox4->addWidget(filterGroupBBox); + + QHBoxLayout *hbox5 = new QHBoxLayout(); + hbox5->setSpacing(0); + hbox5->setMargin(0); + hbox5->addStretch(); + hbox5->addWidget(filterGroupCBox); + + QHBoxLayout *hbox6 = new QHBoxLayout(); + hbox6->setSpacing(0); + hbox6->setMargin(0); + hbox6->addStretch(); + hbox6->addWidget(mercuryBtnGroup()); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + mainLayout->addLayout(hbox4); + mainLayout->addLayout(hbox5); + mainLayout->addLayout(hbox6); + mainLayout->addStretch(); + + // setup values from settings.ini + bandBtnList.at(m_hamBand)->setBtnState(AeroButton::ON); + bandBtnList.at(m_hamBand)->update(); + + dspModeChanged(this, 0, m_dspModeList.at(m_hamBand)); + filterChanged(this, 0, m_filterLo, m_filterHi); + + DSPMode dspMode = m_dspModeList.at(m_hamBand); + + if (dspMode == (DSPMode) LSB || dspMode == (DSPMode) USB || dspMode == (DSPMode) DIGU || dspMode == (DSPMode) DIGL) { + + filterGroupBBox->hide(); + filterGroupCBox->hide(); + } + else + if (dspMode == (DSPMode) DSB || dspMode == (DSPMode) FMN || dspMode == (DSPMode) AM || dspMode == (DSPMode) SAM) { + + filterGroupABox->hide(); + filterGroupCBox->hide(); + } + else + if (dspMode == (DSPMode) CWL || dspMode == (DSPMode) CWU) { + + filterGroupABox->hide(); + filterGroupBBox->hide(); + } + + setLayout(mainLayout); + setupConnections(); +} + +RadioWidget::~RadioWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize RadioWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize RadioWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void RadioWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(currentReceiverChanged(QObject *, int)), + this, + SLOT(setCurrentReceiver(QObject *, int))); + + CHECKED_CONNECT( + set, + SIGNAL(vfoFrequencyChanged(QObject *, int, int, long)), + this, + SLOT(vfoFrequencyChanged(QObject *, int, int, long))); + + CHECKED_CONNECT( + set, + SIGNAL(hamBandChanged(QObject *, int, bool, HamBand)), + this, + SLOT(bandChanged(QObject *, int, bool, HamBand))); + + CHECKED_CONNECT( + set, + SIGNAL(dspModeChanged(QObject *, int, DSPMode)), + this, + SLOT(dspModeChanged(QObject *, int, DSPMode))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(agcModeChanged(QObject *, int, AGCMode)), +// this, +// SLOT(agcModeChanged(QObject *, int, AGCMode))); + + CHECKED_CONNECT( + set, + SIGNAL(filterFrequenciesChanged(QObject *, int, qreal, qreal)), + this, + SLOT(filterChanged(QObject *, int, qreal, qreal))); + + CHECKED_CONNECT( + set, + SIGNAL(mercuryAttenuatorChanged(QObject *, HamBand, int)), + this, + SLOT(setMercuryAttenuator(QObject *, HamBand, int))); +} + +void RadioWidget::createBandBtnGroup() { + + band2200mBtn = new AeroButton("2200m", this); + band2200mBtn->setRoundness(0); + //band2200mBtn->setGlass(false); + band2200mBtn->setFixedSize(btn_widths, btn_height); + band2200mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band2200mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band2200mBtn); + CHECKED_CONNECT(band2200mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band630mBtn = new AeroButton("630 m", this); + band630mBtn->setRoundness(0); + //band630Btn->setGlass(false); + band630mBtn->setFixedSize(btn_widths, btn_height); + band630mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band630Btn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band630mBtn); + CHECKED_CONNECT(band630mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band160mBtn = new AeroButton("160 m", this); + band160mBtn->setRoundness(0); + //band160mBtn->setGlass(false); + band160mBtn->setFixedSize(btn_widths, btn_height); + band160mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band160mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band160mBtn); + CHECKED_CONNECT(band160mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band80mBtn = new AeroButton("80 m", this); + band80mBtn->setRoundness(0); + //band80mBtn->setGlass(false); + band80mBtn->setFixedSize(btn_widths, btn_height); + band80mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band80mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band80mBtn); + CHECKED_CONNECT(band80mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band60mBtn = new AeroButton("60 m", this); + band60mBtn->setRoundness(0); + //band60mBtn->setGlass(false); + band60mBtn->setFixedSize(btn_widths, btn_height); + band60mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band60mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band60mBtn); + CHECKED_CONNECT(band60mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band40mBtn = new AeroButton("40 m", this); + band40mBtn->setRoundness(0); + //band40mBtn->setGlass(false); + band40mBtn->setFixedSize(btn_widths, btn_height); + band40mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band40mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band40mBtn); + CHECKED_CONNECT(band40mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band30mBtn = new AeroButton("30 m", this); + band30mBtn->setRoundness(0); + //band30mBtn->setGlass(false); + band30mBtn->setFixedSize(btn_widths, btn_height); + band30mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band30mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band30mBtn); + CHECKED_CONNECT(band30mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band20mBtn = new AeroButton("20 m", this); + band20mBtn->setRoundness(0); + //band20mBtn->setGlass(false); + band20mBtn->setFixedSize(btn_widths, btn_height); + band20mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band20mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band20mBtn); + CHECKED_CONNECT(band20mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band17mBtn = new AeroButton("17 m", this); + band17mBtn->setRoundness(0); + //band17mBtn->setGlass(false); + band17mBtn->setFixedSize(btn_widths, btn_height); + band17mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band17mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band17mBtn); + CHECKED_CONNECT(band17mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band15mBtn = new AeroButton("15 m", this); + band15mBtn->setRoundness(0); + //band15mBtn->setGlass(false); + band15mBtn->setFixedSize(btn_widths, btn_height); + band15mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band15mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band15mBtn); + CHECKED_CONNECT(band15mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band12mBtn = new AeroButton("12 m", this); + band12mBtn->setRoundness(0); + //band12mBtn->setGlass(false); + band12mBtn->setFixedSize(btn_widths, btn_height); + band12mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band12mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band12mBtn); + CHECKED_CONNECT(band12mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band10mBtn = new AeroButton("10 m", this); + band10mBtn->setRoundness(0); + //band10mBtn->setGlass(false); + band10mBtn->setFixedSize(btn_widths, btn_height); + band10mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band10mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band10mBtn); + CHECKED_CONNECT(band10mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + band6mBtn = new AeroButton("6 m", this); + band6mBtn->setRoundness(0); + //band6mBtn->setGlass(false); + band6mBtn->setFixedSize(btn_widths, btn_height); + band6mBtn->setStyleSheet(set->getMiniButtonStyle()); + //band6mBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(band6mBtn); + CHECKED_CONNECT(band6mBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + bandGenBtn = new AeroButton("Gen", this); + bandGenBtn->setRoundness(0); + //bandGenBtn->setGlass(false); + bandGenBtn->setFixedSize(btn_widths, btn_height); + bandGenBtn->setStyleSheet(set->getMiniButtonStyle()); + //bandGenBtn->setTextColor(QColor(200, 200, 200)); + bandBtnList.append(bandGenBtn); + CHECKED_CONNECT(bandGenBtn, SIGNAL(clicked()), this, SLOT(bandChangedByBtn())); + + /*bandxxBtn = new AeroButton("", this); + bandxxBtn->setRoundness(0); + bandxxBtn->setGlass(false); + bandxxBtn->setFixedSize(btn_widths, btn_height); + bandxxBtn->setHighlight(QColor(90, 90, 90)); + bandxxBtn->setStyleSheet(set->getMiniButtonStyle()); + bandxxBtn->setTextColor(QColor(200, 200, 200)); + bandxxBtn->setEnabled(false);*/ + + // only for testing + //current_band = 1; // 80 m + //band80mBtn->setBtnState(AeroButton::ON); + + QGridLayout *layout = new QGridLayout(); + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(band2200mBtn, 0, 0); + layout->addWidget(band630mBtn, 0, 1); + layout->addWidget(band160mBtn, 0, 2); + layout->addWidget(band80mBtn, 0, 3); + layout->addWidget(band60mBtn, 0, 4); + layout->addWidget(band40mBtn, 0, 5); + layout->addWidget(band30mBtn, 1, 0); + layout->addWidget(band20mBtn, 1, 1); + layout->addWidget(band17mBtn, 1, 2); + layout->addWidget(band15mBtn, 1, 3); + layout->addWidget(band12mBtn, 1, 4); + layout->addWidget(band10mBtn, 1, 5); + layout->addWidget(band6mBtn, 2, 0); + layout->addWidget(bandGenBtn, 2, 1); + //layout->addWidget(bandxxBtn, 2, 3); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(10); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + //vbox->addLayout(layout); + vbox->addLayout(hbox1); + + bandGroupBox = new QGroupBox(tr("Band"), this); + bandGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + bandGroupBox->setLayout(vbox); + bandGroupBox->setStyleSheet(set->getWidgetStyle()); + //bandGroupBox->setMinimumWidth(100); + bandGroupBox->setFont(QFont("Arial", 8)); +} + +void RadioWidget::createModeBtnGroup() { + + lsbBtn = new AeroButton("LSB", this); + lsbBtn->setRoundness(0); + //lsbBtn->setGlass(false); + lsbBtn->setFixedSize(btn_widths, btn_height); + lsbBtn->setStyleSheet(set->getMiniButtonStyle()); + //lsbBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(lsbBtn); + CHECKED_CONNECT(lsbBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + usbBtn = new AeroButton("USB", this); + usbBtn->setRoundness(0); + //usbBtn->setGlass(false); + usbBtn->setFixedSize(btn_widths, btn_height); + usbBtn->setStyleSheet(set->getMiniButtonStyle()); + //usbBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(usbBtn); + CHECKED_CONNECT(usbBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + dsbBtn = new AeroButton("DSB", this); + dsbBtn->setRoundness(0); + //dsbBtn->setGlass(false); + dsbBtn->setFixedSize(btn_widths, btn_height); + dsbBtn->setStyleSheet(set->getMiniButtonStyle()); + //dsbBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(dsbBtn); + CHECKED_CONNECT(dsbBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + cwlBtn = new AeroButton("CWL", this); + cwlBtn->setRoundness(0); + //cwlBtn->setGlass(false); + cwlBtn->setFixedSize(btn_widths, btn_height); + cwlBtn->setStyleSheet(set->getMiniButtonStyle()); + //cwlBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(cwlBtn); + CHECKED_CONNECT(cwlBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + cwuBtn = new AeroButton("CWU", this); + cwuBtn->setRoundness(0); + //cwuBtn->setGlass(false); + cwuBtn->setFixedSize(btn_widths, btn_height); + cwuBtn->setStyleSheet(set->getMiniButtonStyle()); + //cwuBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(cwuBtn); + CHECKED_CONNECT(cwuBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + fmnBtn = new AeroButton("FMN", this); + fmnBtn->setRoundness(0); + //fmnBtn->setGlass(false); + fmnBtn->setFixedSize(btn_widths, btn_height); + fmnBtn->setStyleSheet(set->getMiniButtonStyle()); + //fmnBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(fmnBtn); + CHECKED_CONNECT(fmnBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + amBtn = new AeroButton("AM", this); + amBtn->setRoundness(0); + //amBtn->setGlass(false); + amBtn->setFixedSize(btn_widths, btn_height); + amBtn->setStyleSheet(set->getMiniButtonStyle()); + //amBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(amBtn); + CHECKED_CONNECT(amBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + diguBtn = new AeroButton("DIGU", this); + diguBtn->setRoundness(0); + //diguBtn->setGlass(false); + diguBtn->setFixedSize(btn_widths, btn_height); + diguBtn->setStyleSheet(set->getMiniButtonStyle()); + //diguBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(diguBtn); + CHECKED_CONNECT(diguBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + diglBtn = new AeroButton("DIGL", this); + diglBtn->setRoundness(0); + //diglBtn->setGlass(false); + diglBtn->setFixedSize(btn_widths, btn_height); + diglBtn->setStyleSheet(set->getMiniButtonStyle()); + //diglBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(diglBtn); + CHECKED_CONNECT(diglBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + specBtn = new AeroButton("SPEC", this); + specBtn->setRoundness(0); + //specBtn->setGlass(false); + specBtn->setFixedSize(btn_widths, btn_height); + specBtn->setStyleSheet(set->getMiniButtonStyle()); + //specBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(specBtn); + CHECKED_CONNECT(specBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + samBtn = new AeroButton("SAM", this); + samBtn->setRoundness(0); + //samBtn->setGlass(false); + samBtn->setFixedSize(btn_widths, btn_height); + samBtn->setStyleSheet(set->getMiniButtonStyle()); + //samBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(samBtn); + CHECKED_CONNECT(samBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + drmBtn = new AeroButton("DRM", this); + drmBtn->setRoundness(0); + //drmBtn->setGlass(false); + drmBtn->setFixedSize(btn_widths, btn_height); + drmBtn->setStyleSheet(set->getMiniButtonStyle()); + //drmBtn->setTextColor(QColor(200, 200, 200)); + dspModeBtnList.append(drmBtn); + CHECKED_CONNECT(drmBtn, SIGNAL(clicked()), this, SLOT(dspModeChangedByBtn())); + + /*foreach(AeroButton *btn, dspModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + m_dspMode = set->getCurrentDSPMode(); + dspModeBtnList.at(m_dspMode)->setBtnState(AeroButton::ON);*/ + + QGridLayout *layout = new QGridLayout(); + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(lsbBtn, 0, 0); + layout->addWidget(usbBtn, 0, 1); + layout->addWidget(dsbBtn, 0, 2); + layout->addWidget(cwlBtn, 0, 3); + layout->addWidget(cwuBtn, 0, 4); + layout->addWidget(fmnBtn, 0, 5); + layout->addWidget(amBtn, 1, 0); + layout->addWidget(diguBtn, 1, 1); + layout->addWidget(specBtn, 1, 2); + layout->addWidget(diglBtn, 1, 3); + layout->addWidget(samBtn, 1, 4); + layout->addWidget(drmBtn, 1, 5); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + modeGroupBox = new QGroupBox(tr("Mode"), this); + modeGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + modeGroupBox->setLayout(vbox); + modeGroupBox->setStyleSheet(set->getWidgetStyle()); + //modeGroupBox->setMinimumWidth(100); + modeGroupBox->setFont(QFont("Arial", 8)); +} + +void RadioWidget::createFilterBtnGroupA() { + + filter1kBtnA = new AeroButton("1k", this); + filter1kBtnA->setObjectName("1k"); + filter1kBtnA->setRoundness(0); + //filter1kBtnA->setGlass(false); + filter1kBtnA->setFixedSize(btn_widths, btn_height); + filter1kBtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter1kBtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter1kBtnA); + CHECKED_CONNECT(filter1kBtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter1k8BtnA = new AeroButton("1k8", this); + filter1kBtnA->setObjectName("1k8"); + filter1k8BtnA->setRoundness(0); + //filter1k8BtnA->setGlass(false); + filter1k8BtnA->setFixedSize(btn_widths, btn_height); + filter1k8BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter1k8BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter1k8BtnA); + CHECKED_CONNECT(filter1k8BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k1BtnA = new AeroButton("2k1", this); + filter1kBtnA->setObjectName("2k1"); + filter2k1BtnA->setRoundness(0); + //filter2k1BtnA->setGlass(false); + filter2k1BtnA->setFixedSize(btn_widths, btn_height); + filter2k1BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter2k1BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter2k1BtnA); + CHECKED_CONNECT(filter2k1BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k4BtnA = new AeroButton("2k4", this); + filter1kBtnA->setObjectName("2k4"); + filter2k4BtnA->setRoundness(0); + //filter2k4BtnA->setGlass(false); + filter2k4BtnA->setFixedSize(btn_widths, btn_height); + filter2k4BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter2k4BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter2k4BtnA); + CHECKED_CONNECT(filter2k4BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k7BtnA = new AeroButton("2k7", this); + filter1kBtnA->setObjectName("2k7"); + filter2k7BtnA->setRoundness(0); + //filter2k7BtnA->setGlass(false); + filter2k7BtnA->setFixedSize(btn_widths, btn_height); + filter2k7BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter2k7BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter2k7BtnA); + CHECKED_CONNECT(filter2k7BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k9BtnA = new AeroButton("2k9", this); + filter1kBtnA->setObjectName("2k9"); + filter2k9BtnA->setRoundness(0); + //filter2k9BtnA->setGlass(false); + filter2k9BtnA->setFixedSize(btn_widths, btn_height); + filter2k9BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter2k9BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter2k9BtnA); + CHECKED_CONNECT(filter2k9BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter3k3BtnA = new AeroButton("3k3", this); + filter1kBtnA->setObjectName("3k3"); + filter3k3BtnA->setRoundness(0); + //filter3k3BtnA->setGlass(false); + filter3k3BtnA->setFixedSize(btn_widths, btn_height); + filter3k3BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter3k3BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter3k3BtnA); + CHECKED_CONNECT(filter3k3BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter3k8BtnA = new AeroButton("3k8", this); + filter1kBtnA->setObjectName("3k8"); + filter3k8BtnA->setRoundness(0); + //filter3k8BtnA->setGlass(false); + filter3k8BtnA->setFixedSize(btn_widths, btn_height); + filter3k8BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter3k8BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter3k8BtnA); + CHECKED_CONNECT(filter3k8BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter4k4BtnA = new AeroButton("4k4", this); + filter1kBtnA->setObjectName("4k4"); + filter4k4BtnA->setRoundness(0); + //filter4k4BtnA->setGlass(false); + filter4k4BtnA->setFixedSize(btn_widths, btn_height); + filter4k4BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter4k4BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter4k4BtnA); + CHECKED_CONNECT(filter4k4BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter5kBtnA = new AeroButton("5k", this); + filter1kBtnA->setObjectName("5k"); + filter5kBtnA->setRoundness(0); + //filter5kBtnA->setGlass(false); + filter5kBtnA->setFixedSize(btn_widths, btn_height); + filter5kBtnA->setStyleSheet(set->getMiniButtonStyle()); + //filter5kBtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filter5kBtnA); + CHECKED_CONNECT(filter5kBtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar1BtnA = new AeroButton("Var1", this); + filter1kBtnA->setObjectName("Var1"); + filterVar1BtnA->setRoundness(0); + //filterVar1BtnA->setGlass(false); + filterVar1BtnA->setFixedSize(btn_widths, btn_height); + filterVar1BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filterVar1BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filterVar1BtnA); + CHECKED_CONNECT(filterVar1BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar2BtnA = new AeroButton("Var2", this); + filter1kBtnA->setObjectName("Var2"); + filterVar2BtnA->setRoundness(0); + //filterVar2BtnA->setGlass(false); + filterVar2BtnA->setFixedSize(btn_widths, btn_height); + filterVar2BtnA->setStyleSheet(set->getMiniButtonStyle()); + //filterVar2BtnA->setTextColor(QColor(200, 200, 200)); + filterBtnListA.append(filterVar2BtnA); + CHECKED_CONNECT(filterVar2BtnA, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + foreach(AeroButton *btn, filterBtnListA) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + //filterBtnListA.at(set->getCurrentDSPMode())->setBtnState(AeroButton::ON); + + QGridLayout *layout = new QGridLayout; + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(filter5kBtnA, 0, 0); + layout->addWidget(filter4k4BtnA, 0, 1); + layout->addWidget(filter3k8BtnA, 0, 2); + layout->addWidget(filter3k3BtnA, 0, 3); + layout->addWidget(filter2k9BtnA, 0, 4); + layout->addWidget(filter2k7BtnA, 0, 5); + layout->addWidget(filter2k4BtnA, 1, 0); + layout->addWidget(filter2k1BtnA, 1, 1); + layout->addWidget(filter1k8BtnA, 1, 2); + layout->addWidget(filter1kBtnA, 1, 3); + layout->addWidget(filterVar1BtnA, 1, 4); + layout->addWidget(filterVar2BtnA, 1, 5); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + filterGroupABox = new QGroupBox(tr("Filter"), this); + filterGroupABox->setMinimumWidth(m_minimumGroupBoxWidth); + filterGroupABox->setLayout(vbox); + filterGroupABox->setStyleSheet(set->getWidgetStyle()); + filterGroupABox->setFont(QFont("Arial", 8)); +} + +void RadioWidget::createFilterBtnGroupB() { + + filter16kBtnB = new AeroButton("16k", this); + filter16kBtnB->setRoundness(0); + //filter16kBtnB->setGlass(false); + filter16kBtnB->setFixedSize(btn_widths, btn_height); + filter16kBtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter16kBtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter16kBtnB); + CHECKED_CONNECT(filter16kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter12kBtnB = new AeroButton("12k", this); + filter12kBtnB->setRoundness(0); + //filter12kBtnB->setGlass(false); + filter12kBtnB->setFixedSize(btn_widths, btn_height); + filter12kBtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter12kBtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter12kBtnB); + CHECKED_CONNECT(filter12kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter10kBtnB = new AeroButton("10k", this); + filter10kBtnB->setRoundness(0); + //filter10kBtnB->setGlass(false); + filter10kBtnB->setFixedSize(btn_widths, btn_height); + filter10kBtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter10kBtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter10kBtnB); + CHECKED_CONNECT(filter10kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter8kBtnB = new AeroButton("8k", this); + filter8kBtnB->setRoundness(0); + //filter8kBtnB->setGlass(false); + filter8kBtnB->setFixedSize(btn_widths, btn_height); + filter8kBtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter8kBtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter8kBtnB); + CHECKED_CONNECT(filter8kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter6k6BtnB = new AeroButton("6k6", this); + filter6k6BtnB->setRoundness(0); + //filter6k6BtnB->setGlass(false); + filter6k6BtnB->setFixedSize(btn_widths, btn_height); + filter6k6BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter6k6BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter6k6BtnB); + CHECKED_CONNECT(filter6k6BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter5k2BtnB = new AeroButton("5k2", this); + filter5k2BtnB->setRoundness(0); + //filter5k2BtnB->setGlass(false); + filter5k2BtnB->setFixedSize(btn_widths, btn_height); + filter5k2BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter5k2BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter5k2BtnB); + CHECKED_CONNECT(filter5k2BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter4kBtnB = new AeroButton("4k", this); + filter4kBtnB->setRoundness(0); + //filter4kBtnB->setGlass(false); + filter4kBtnB->setFixedSize(btn_widths, btn_height); + filter4kBtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter4kBtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter4kBtnB); + CHECKED_CONNECT(filter4kBtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter3k1BtnB = new AeroButton("3k1", this); + filter3k1BtnB->setRoundness(0); + //filter3k1BtnB->setGlass(false); + filter3k1BtnB->setFixedSize(btn_widths, btn_height); + filter3k1BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter3k1BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter3k1BtnB); + CHECKED_CONNECT(filter3k1BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k9BtnB = new AeroButton("2k9", this); + filter2k9BtnB->setRoundness(0); + //filter2k9BtnB->setGlass(false); + filter2k9BtnB->setFixedSize(btn_widths, btn_height); + filter2k9BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter2k9BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter2k9BtnB); + CHECKED_CONNECT(filter2k9BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter2k4BtnB = new AeroButton("2k4", this); + filter2k4BtnB->setRoundness(0); + //filter2k4BtnB->setGlass(false); + filter2k4BtnB->setFixedSize(btn_widths, btn_height); + filter2k4BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filter2k4BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filter2k4BtnB); + CHECKED_CONNECT(filter2k4BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar1BtnB = new AeroButton("Var1", this); + filterVar1BtnB->setRoundness(0); + //filterVar1BtnB->setGlass(false); + filterVar1BtnB->setFixedSize(btn_widths, btn_height); + filterVar1BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filterVar1BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filterVar1BtnB); + CHECKED_CONNECT(filterVar1BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar2BtnB = new AeroButton("Var2", this); + filterVar2BtnB->setRoundness(0); + //filterVar2BtnB->setGlass(false); + filterVar2BtnB->setFixedSize(btn_widths, btn_height); + filterVar2BtnB->setStyleSheet(set->getMiniButtonStyle()); + //filterVar2BtnB->setTextColor(QColor(200, 200, 200)); + filterBtnListB.append(filterVar2BtnB); + CHECKED_CONNECT(filterVar2BtnB, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + foreach(AeroButton *btn, filterBtnListB) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + //filterBtnListA.at(set->getCurrentDSPMode())->setBtnState(AeroButton::ON); + + QGridLayout *layout = new QGridLayout; + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(filter16kBtnB, 0, 0); + layout->addWidget(filter12kBtnB, 0, 1); + layout->addWidget(filter10kBtnB, 0, 2); + layout->addWidget(filter8kBtnB, 0, 3); + layout->addWidget(filter6k6BtnB, 0, 4); + layout->addWidget(filter5k2BtnB, 0, 5); + layout->addWidget(filter4kBtnB, 1, 0); + layout->addWidget(filter3k1BtnB, 1, 1); + layout->addWidget(filter2k9BtnB, 1, 2); + layout->addWidget(filter2k4BtnB, 1, 3); + layout->addWidget(filterVar1BtnB, 1, 4); + layout->addWidget(filterVar2BtnB, 1, 5); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + filterGroupBBox = new QGroupBox(tr("Filter"), this); + filterGroupBBox->setMinimumWidth(m_minimumGroupBoxWidth); + filterGroupBBox->setLayout(vbox); + filterGroupBBox->setStyleSheet(set->getWidgetStyle()); + filterGroupBBox->setFont(QFont("Arial", 8)); +} + +void RadioWidget::createFilterBtnGroupC() { + + filter1kBtnC = new AeroButton("1k", this); + filter1kBtnC->setRoundness(0); + //filter1kBtnC->setGlass(false); + filter1kBtnC->setFixedSize(btn_widths, btn_height); + filter1kBtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter1kBtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter1kBtnC); + CHECKED_CONNECT(filter1kBtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter800BtnC = new AeroButton("800", this); + filter800BtnC->setRoundness(0); + //filter800BtnC->setGlass(false); + filter800BtnC->setFixedSize(btn_widths, btn_height); + filter800BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter800BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter800BtnC); + CHECKED_CONNECT(filter800BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter750BtnC = new AeroButton("750", this); + filter750BtnC->setRoundness(0); + //filter750BtnC->setGlass(false); + filter750BtnC->setFixedSize(btn_widths, btn_height); + filter750BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter750BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter750BtnC); + CHECKED_CONNECT(filter750BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter600BtnC = new AeroButton("600", this); + filter600BtnC->setRoundness(0); + //filter600BtnC->setGlass(false); + filter600BtnC->setFixedSize(btn_widths, btn_height); + filter600BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter600BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter600BtnC); + CHECKED_CONNECT(filter600BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter500BtnC = new AeroButton("500", this); + filter500BtnC->setRoundness(0); + //filter500BtnC->setGlass(false); + filter500BtnC->setFixedSize(btn_widths, btn_height); + filter500BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter500BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter500BtnC); + CHECKED_CONNECT(filter500BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter400BtnC = new AeroButton("400", this); + filter400BtnC->setRoundness(0); + //filter400BtnC->setGlass(false); + filter400BtnC->setFixedSize(btn_widths, btn_height); + filter400BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter400BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter400BtnC); + CHECKED_CONNECT(filter400BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter250BtnC = new AeroButton("250", this); + filter250BtnC->setRoundness(0); + //filter250BtnC->setGlass(false); + filter250BtnC->setFixedSize(btn_widths, btn_height); + filter250BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter250BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter250BtnC); + CHECKED_CONNECT(filter250BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter100BtnC = new AeroButton("100", this); + filter100BtnC->setRoundness(0); + //filter100BtnC->setGlass(false); + filter100BtnC->setFixedSize(btn_widths, btn_height); + filter100BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter100BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter100BtnC); + CHECKED_CONNECT(filter100BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter50BtnC = new AeroButton("50", this); + filter50BtnC->setRoundness(0); + //filter50BtnC->setGlass(false); + filter50BtnC->setFixedSize(btn_widths, btn_height); + filter50BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter50BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter50BtnC); + CHECKED_CONNECT(filter50BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filter25BtnC = new AeroButton("25", this); + filter25BtnC->setRoundness(0); + //filter25BtnC->setGlass(false); + filter25BtnC->setFixedSize(btn_widths, btn_height); + filter25BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filter25BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filter25BtnC); + CHECKED_CONNECT(filter25BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar1BtnC = new AeroButton("Var1", this); + filterVar1BtnC->setRoundness(0); + //filterVar1BtnC->setGlass(false); + filterVar1BtnC->setFixedSize(btn_widths, btn_height); + filterVar1BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filterVar1BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filterVar1BtnC); + CHECKED_CONNECT(filterVar1BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + filterVar2BtnC = new AeroButton("Var2", this); + filterVar2BtnC->setRoundness(0); + //filterVar2BtnC->setGlass(false); + filterVar2BtnC->setFixedSize(btn_widths, btn_height); + filterVar2BtnC->setStyleSheet(set->getMiniButtonStyle()); + //filterVar2BtnC->setTextColor(QColor(200, 200, 200)); + filterBtnListC.append(filterVar2BtnC); + CHECKED_CONNECT(filterVar2BtnC, SIGNAL(clicked()), this, SLOT(filterChangedByBtn())); + + foreach(AeroButton *btn, filterBtnListC) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + //filterBtnListC.at(set)->getCurrentDSPMode())->setBtnState(AeroButton::ON); + + QGridLayout *layout = new QGridLayout(); + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(filter1kBtnC, 0, 0); + layout->addWidget(filter800BtnC, 0, 1); + layout->addWidget(filter750BtnC, 0, 2); + layout->addWidget(filter600BtnC, 0, 3); + layout->addWidget(filter500BtnC, 0, 4); + layout->addWidget(filter400BtnC, 0, 5); + layout->addWidget(filter250BtnC, 1, 0); + layout->addWidget(filter100BtnC, 1, 1); + layout->addWidget(filter50BtnC, 1, 2); + layout->addWidget(filter25BtnC, 1, 3); + layout->addWidget(filterVar1BtnC, 1, 4); + layout->addWidget(filterVar2BtnC, 1, 5); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + filterGroupCBox = new QGroupBox(tr("Filter"), this); + filterGroupCBox->setMinimumWidth(m_minimumGroupBoxWidth); + filterGroupCBox->setLayout(vbox); + filterGroupCBox->setStyleSheet(set->getWidgetStyle()); + filterGroupCBox->setFont(QFont("Arial", 8)); +} + +QGroupBox *RadioWidget::mercuryBtnGroup() { + + attenuatorBtn = new AeroButton("Attn.", this); + attenuatorBtn->setRoundness(0); + attenuatorBtn->setFixedSize (50, btn_height); + attenuatorBtn->setStyleSheet(set->getMiniButtonStyle()); + connect(attenuatorBtn, SIGNAL(released()), this, SLOT(attenuatorChanged())); + + ditherBtn = new AeroButton("Dither", this); + ditherBtn->setRoundness(0); + //ditherBtn->setGlass(false); + ditherBtn->setFixedSize (50, btn_height); + ditherBtn->setStyleSheet(set->getMiniButtonStyle()); + //ditherBtn->setTextColor(QColor(200, 200, 200)); + connect(ditherBtn, SIGNAL(released()), this, SLOT(ditherChanged())); + + randomBtn = new AeroButton("Rand", this); + randomBtn->setRoundness(0); + //randomBtn->setGlass(false); + randomBtn->setFixedSize(50, btn_height); + randomBtn->setStyleSheet(set->getMiniButtonStyle()); + //randomBtn->setTextColor(QColor(200, 200, 200)); + CHECKED_CONNECT(randomBtn, SIGNAL(released()), this, SLOT(randomChanged())); + + HamBand band = m_receiverDataList.at(0).hamBand; + + if (m_receiverDataList.at(0).mercuryAttenuators.at(band)) { + + attenuatorBtn->setBtnState(AeroButton::OFF); + attenuatorBtn->setText("Att 0dB"); + } + else { + + attenuatorBtn->setBtnState(AeroButton::ON); + attenuatorBtn->setText("Att -20dB"); + } + + if(set->getMercuryDither()) + ditherBtn->setBtnState(AeroButton::ON); + + if(set->getMercuryRandom()) + randomBtn->setBtnState(AeroButton::ON); + + QGridLayout *layout = new QGridLayout(); + layout->setVerticalSpacing(1); + layout->setHorizontalSpacing(1); + layout->setContentsMargins(0, 0, 0, 0); + layout->addWidget(attenuatorBtn, 0, 0); + layout->addWidget(ditherBtn, 0, 1); + layout->addWidget(randomBtn, 0, 2); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + hbox1->addLayout(layout); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + QGroupBox *groupBox = new QGroupBox(tr("Mercury"), this); + groupBox->setMinimumWidth(m_minimumGroupBoxWidth); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(set->getWidgetStyle()); + //groupBox->setMinimumWidth(175); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +QLabel *RadioWidget::createLabel(const QString &text) { + + QLabel *label = new QLabel(text, this); + label->setFrameStyle(QFrame::Box | QFrame::Raised); + return label; +} + + +//****************************************** +void RadioWidget::ctrFrequencyChanged(QObject* sender, int mode, int rx, long frequency) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + if (m_currentRx != rx) return; + m_ctrFrequency = frequency; + + HamBand band = getBandFromFrequency(set->getBandFrequencyList(), frequency); + m_lastCtrFrequencyList[(int) band] = m_ctrFrequency; +} + +void RadioWidget::vfoFrequencyChanged(QObject* sender, int mode, int rx, long frequency) { + + Q_UNUSED(sender) + Q_UNUSED(mode) + + if (m_currentRx != rx) return; + m_vfoFrequency = frequency; + + HamBand band = getBandFromFrequency(set->getBandFrequencyList(), frequency); + m_lastVfoFrequencyList[(int) band] = m_vfoFrequency; +} + +void RadioWidget::bandChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + int btn = bandBtnList.indexOf(button); + + foreach(AeroButton *btn, bandBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + set->setHamBand(this, m_currentRx, true, (HamBand) btn); + + QString str = button->text(); + + if (str == "2200m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m2200)); + else + if (str == "630 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m630)); + else + if (str == "160 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m160)); + else + if (str == "80 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m80)); + else + if (str == "60 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m60)); + else + if (str == "40 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m40)); + else + if (str == "30 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m30)); + else + if (str == "20 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m20)); + else + if (str == "17 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m17)); + else + if (str == "15 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m15)); + else + if (str == "12 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m12)); + else + if (str == "10 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m10)); + else + if (str == "6 m") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(m6)); + else + if (str == "Gen") + set->setVFOFrequency(this, 2, m_currentRx, m_lastVfoFrequencyList.at(gen)); + +} + +void RadioWidget::bandChanged(QObject *sender, int rx, bool byButton, HamBand band) { + + Q_UNUSED (byButton) + + if (sender == this) return; + + if (m_currentRx != rx) return; + m_hamBand = band; + + foreach(AeroButton *btn, bandBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + //m_lastFrequencyList[(int) band] = m_frequency; + bandBtnList.at(band)->setBtnState(AeroButton::ON); + bandBtnList.at(band)->update(); +} + +void RadioWidget::dspModeChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + int btn = dspModeBtnList.indexOf(button); + + foreach(AeroButton *btn, dspModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + set->setDSPMode(this, m_currentRx, (DSPMode) btn); + m_dspModeList[m_hamBand] = (DSPMode) btn; + filterChanged(this, m_currentRx, m_filterLo, m_filterHi); + filterGroupChanged((DSPMode) btn); + + button->setBtnState(AeroButton::ON); + button->update(); +} + +void RadioWidget::dspModeChanged(QObject *sender, int rx, DSPMode mode) { + + Q_UNUSED(sender) + + if (m_currentRx != rx) return; + m_dspModeList[m_hamBand] = mode; + + foreach(AeroButton *btn, dspModeBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + dspModeBtnList.at(mode)->setBtnState(AeroButton::ON); + dspModeBtnList.at(mode)->update(); +} + +void RadioWidget::filterGroupChanged(DSPMode mode) { + + if (mode == 0 || mode == 1 || mode == 7 || mode == 9) { + + filterGroupBBox->hide(); + filterGroupCBox->hide(); + filterGroupABox->show(); + } + else if (mode == 2 || mode == 5 || mode == 6 || mode == 10) { + + filterGroupABox->hide(); + filterGroupCBox->hide(); + filterGroupBBox->show(); + } + else if (mode == 3 || mode == 4) { + + filterGroupABox->hide(); + filterGroupBBox->hide(); + filterGroupCBox->show(); + } + /*else if (mode == 8 || mode == 11) + { + filterGroupA->hide(); + filterGroupB->hide(); + filterGroupC->hide(); + }*/ +} + +void RadioWidget::filterChangedByBtn() { + + AeroButton *button = qobject_cast(sender()); + + QList btnList; + int filterList = 0; + + if (filterBtnListA.contains(button)) { + + btnList = filterBtnListA; + filterList = 0; + } + else if (filterBtnListB.contains(button)) { + + btnList = filterBtnListB; + filterList = 1; + } + else if (filterBtnListC.contains(button)) { + + btnList = filterBtnListC; + filterList = 2; + } + + foreach(AeroButton *btn, btnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + button->setBtnState(AeroButton::ON); + button->update(); + + QString str = button->text(); + + DSPMode mode = m_dspModeList.at(m_hamBand); + switch (filterList) { + + case 0: // filterBtnList A + + if (str == "1k") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -1150.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 1150.0f; + break; + + default: + break; + + } + } + else + if (str == "1k8") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -1950.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 1950.0f; + break; + + default: + break; + } + } + else + if (str == "2k1") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -2250.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 2250.0f; + break; + + default: + break; + + } + } + else + if (str == "2k4") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -2550.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 2550.0f; + break; + + default: + break; + + } + } + else + if (str == "2k7") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -2850.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 2850.0f; + break; + + default: + break; + + } + } + else + if (str == "2k9") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -3050.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 3050.0f; + break; + + default: + break; + + } + } + else + if (str == "3k3") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -3450.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 3450.0f; + break; + + default: + break; + + } + } + else + if (str == "3k8") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -3950.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 3950.0f; + break; + + default: + break; + } + } + else + if (str == "4k4") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -4550.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 4550.0f; + break; + + default: + break; + } + } + else + if (str == "5k") { + + switch (mode) { + + case (DSPMode) LSB: + m_filterLo = -5150.0f; + m_filterHi = -150.0f; + break; + + case (DSPMode) USB: + m_filterLo = 150.0f; + m_filterHi = 5150.0f; + break; + + default: + break; + } + } + break; + + case 1: // filterBtnList B + + if (str == "2k4") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -1200.0f; + m_filterHi = 1200.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + default: + break; + } + } + else + if (str == "2k9") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -1450.0f; + m_filterHi = 1450.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "3k1") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -1550.0f; + m_filterHi = 1550.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "4k") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "5k2") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -2600.0f; + m_filterHi = 2600.0f; + break; + + case 5: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "6k6") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -3300.0f; + m_filterHi = 3300.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "8k") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "10k") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -5000.0f; + m_filterHi = 5000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "12k") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -6000.0f; + m_filterHi = 6000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + else + if (str == "16k") { + + switch (mode) { + + case (DSPMode) DSB: + case (DSPMode) AM: + case (DSPMode) SAM: + m_filterLo = -8000.0f; + m_filterHi = 8000.0f; + break; + + case (DSPMode) FMN: + m_filterLo = -2000.0f; + m_filterHi = 2000.0f; + break; + + /*case 6: + m_filterLo = -4000.0f; + m_filterHi = 4000.0f; + break;*/ + + default: + break; + } + } + break; + + case 2: // filterBtnList C + + if (str == "25") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -125.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 125.0f; + break; + + default: + break; + } + } + else + if (str == "50") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -150.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 150.0f; + break; + + default: + break; + } + } + else + if (str == "100") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -200.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 200.0f; + break; + + default: + break; + } + } + else + if (str == "250") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -350.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 350.0f; + break; + + default: + break; + } + } + else + if (str == "400") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -500.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 500.0f; + break; + + default: + break; + } + } + else + if (str == "500") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -600.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 600.0f; + break; + + default: + break; + } + } + else + if (str == "600") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -700.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 700.0f; + break; + + default: + break; + } + } + else + if (str == "750") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -850.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 850.0f; + break; + + default: + break; + } + } + else + if (str == "800") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -900.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 900.0f; + break; + + default: + break; + } + } + else + if (str == "1k") { + + switch (mode) { + + case (DSPMode) CWL: + m_filterLo = -1100.0f; + m_filterHi = -100.0f; + break; + + case (DSPMode) CWU: + m_filterLo = 100.0f; + m_filterHi = 1100.0f; + break; + + default: + break; + } + } + break; + } + + set->setRXFilter(this, m_currentRx, m_filterLo, m_filterHi); +} + +void RadioWidget::filterChanged(QObject *sender, int rx, qreal low, qreal high) { + + Q_UNUSED(sender) + + if (m_currentRx != rx) return; + m_filterLo = low; + m_filterHi = high; + + DSPMode mode = m_dspModeList.at(m_hamBand); + if (mode == (DSPMode ) LSB || mode == (DSPMode ) USB || mode == (DSPMode ) DIGU || mode == (DSPMode ) DIGL) { + + foreach(AeroButton *btn, filterBtnListA) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + if ((m_filterLo == -5150.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 5150.0)) { + filter5kBtnA->setBtnState(AeroButton::ON); + filter5kBtnA->update(); + } + else + if ((m_filterLo == -4550.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 4550.0)) { + filter4k4BtnA->setBtnState(AeroButton::ON); + filter4k4BtnA->update(); + } + else + if ((m_filterLo == -3950.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 3950.0)) { + filter3k8BtnA->setBtnState(AeroButton::ON); + filter3k8BtnA->update(); + } + else + if ((m_filterLo == -3450.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 3450.0)) { + filter3k3BtnA->setBtnState(AeroButton::ON); + filter3k3BtnA->update(); + } + else + if ((m_filterLo == -3050.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 3050.0)) { + filter2k9BtnA->setBtnState(AeroButton::ON); + filter2k9BtnA->update(); + } + else + if ((m_filterLo == -2850.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 2850.0)) { + filter2k7BtnA->setBtnState(AeroButton::ON); + filter2k7BtnA->update(); + } + else + if ((m_filterLo == -2550.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 2550.0)) { + filter2k4BtnA->setBtnState(AeroButton::ON); + filter2k4BtnA->update(); + } + else + if ((m_filterLo == -2250.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 2250.0)) { + filter2k1BtnA->setBtnState(AeroButton::ON); + filter2k1BtnA->update(); + } + else + if ((m_filterLo == -1950.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 1950.0)) { + filter1k8BtnA->setBtnState(AeroButton::ON); + filter1k8BtnA->update(); + } + else + if ((m_filterLo == -1150.0 && m_filterHi == -150.0) || (m_filterLo == 150.0 && m_filterHi == 1150.0)) { + filter1kBtnA->setBtnState(AeroButton::ON); + filter1kBtnA->update(); + } + } + else if (mode == (DSPMode ) DSB || mode == (DSPMode ) FMN || mode == (DSPMode ) AM || mode == (DSPMode ) SAM) { + + // filterGroupBBox + foreach(AeroButton *btn, filterBtnListB) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + if (m_filterLo == -8000.0 && m_filterHi == 8000.0) { + filter16kBtnB->setBtnState(AeroButton::ON); + filter16kBtnB->update(); + } + else + if (m_filterLo == -6000.0 && m_filterHi == 6000.0) { + filter12kBtnB->setBtnState(AeroButton::ON); + filter12kBtnB->update(); + } + else + if (m_filterLo == -5000.0 && m_filterHi == 5000.0) { + filter10kBtnB->setBtnState(AeroButton::ON); + filter10kBtnB->update(); + } + else + if (m_filterLo == -4000.0 && m_filterHi == 4000.0) { + filter8kBtnB->setBtnState(AeroButton::ON); + filter8kBtnB->update(); + } + else + if (m_filterLo == -3300.0 && m_filterHi == 3300.0) { + filter6k6BtnB->setBtnState(AeroButton::ON); + filter6k6BtnB->update(); + } + else + if (m_filterLo == -2600.0 && m_filterHi == 2600.0) { + filter5k2BtnB->setBtnState(AeroButton::ON); + filter5k2BtnB->update(); + } + else + if (m_filterLo == -2000.0 && m_filterHi == 2000.0) { + filter4kBtnB->setBtnState(AeroButton::ON); + filter4kBtnB->update(); + } + else + if (m_filterLo == -1550.0 && m_filterHi == 1550.0) { + filter3k1BtnB->setBtnState(AeroButton::ON); + filter3k1BtnB->update(); + } + else + if (m_filterLo == -1450.0 && m_filterHi == 1450.0) { + filter2k9BtnB->setBtnState(AeroButton::ON); + filter2k9BtnB->update(); + } + else + if (m_filterLo == -1200.0 && m_filterHi == 1200.0) { + filter2k4BtnB->setBtnState(AeroButton::ON); + filter2k4BtnB->update(); + } + } + else if (mode == (DSPMode ) CWL || mode == (DSPMode ) CWU) { + + // filterGroupCBox + foreach(AeroButton *btn, filterBtnListC) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + + if ((m_filterLo == -1100.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 1100.0)) { + filter1kBtnC->setBtnState(AeroButton::ON); + filter1kBtnC->update(); + } + else + if ((m_filterLo == -900.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 900.0)) { + filter800BtnC->setBtnState(AeroButton::ON); + filter800BtnC->update(); + } + else + if ((m_filterLo == -850.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 850.0)) { + filter750BtnC->setBtnState(AeroButton::ON); + filter750BtnC->update(); + } + else + if ((m_filterLo == -700.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 700.0)) { + filter600BtnC->setBtnState(AeroButton::ON); + filter600BtnC->update(); + } + else + if ((m_filterLo == -600.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 600.0)) { + filter500BtnC->setBtnState(AeroButton::ON); + filter500BtnC->update(); + } + else + if ((m_filterLo == -500.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 500.0)) { + filter400BtnC->setBtnState(AeroButton::ON); + filter400BtnC->update(); + } + else + if ((m_filterLo == -350.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 350.0)) { + filter250BtnC->setBtnState(AeroButton::ON); + filter250BtnC->update(); + } + else + if ((m_filterLo == -200.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 200.0)) { + filter100BtnC->setBtnState(AeroButton::ON); + filter100BtnC->update(); + } + else + if ((m_filterLo == -150.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 150.0)) { + filter50BtnC->setBtnState(AeroButton::ON); + filter50BtnC->update(); + } + else + if ((m_filterLo == -125.0 && m_filterHi == -100.0) || (m_filterLo == 100.0 && m_filterHi == 125.0)) { + filter25BtnC->setBtnState(AeroButton::ON); + filter25BtnC->update(); + } + } +} + +void RadioWidget::attenuatorChanged() { + + if (attenuatorBtn->btnState() == AeroButton::OFF) { + + set->setMercuryAttenuator(this, 0); + attenuatorBtn->setBtnState(AeroButton::ON); + attenuatorBtn->setText("Att -20dB"); + emit newMessage("[hpsdr]: attenuator -20 dB."); + } + else { + + set->setMercuryAttenuator(this, 1); + attenuatorBtn->setBtnState(AeroButton::OFF); + attenuatorBtn->setText("Att 0dB"); + emit newMessage("[hpsdr]: attenuator 0 dB."); + } +} + +void RadioWidget::setMercuryAttenuator(QObject *sender, HamBand band, int value) { + + Q_UNUSED(sender) + Q_UNUSED(band) + + if (value) { + + attenuatorBtn->setBtnState(AeroButton::OFF); + attenuatorBtn->setText("Att 0dB"); + emit newMessage("[hpsdr]: attenuator 0 dB."); + } + else { + + attenuatorBtn->setBtnState(AeroButton::ON); + attenuatorBtn->setText("Att -20dB"); + emit newMessage("[hpsdr]: attenuator -20 dB."); + } +} + +void RadioWidget::ditherChanged() { + + if (ditherBtn->btnState() == AeroButton::OFF) { + + set->setDither(this, true); + ditherBtn->setBtnState(AeroButton::ON); + emit newMessage("[hpsdr]: dither on."); + + } else { + + set->setDither(this, false); + ditherBtn->setBtnState(AeroButton::OFF); + emit newMessage("[hpsdr]: dither off."); + } +} + +void RadioWidget::randomChanged() { + + if (randomBtn->btnState() == AeroButton::OFF) { + + set->setRandom(this, true); + randomBtn->setBtnState(AeroButton::ON); + emit newMessage("[hpsdr]: random on."); + + } else { + + set->setRandom(this, false); + randomBtn->setBtnState(AeroButton::OFF); + emit newMessage("[hpsdr]: random off."); + } +} + +void RadioWidget::setCurrentReceiver(QObject *sender, int value) { + + Q_UNUSED(sender) + + if (m_currentRx == value) return; + m_currentRx = value; + + TReceiver rxData = set->getReceiverDataList().at(m_currentRx); + + if (m_hamBand != rxData.hamBand) { + m_hamBand = rxData.hamBand; + + foreach(AeroButton *btn, bandBtnList) { + + btn->setBtnState(AeroButton::OFF); + btn->update(); + } + AeroButton *button = bandBtnList.at(m_hamBand); + button->setBtnState(AeroButton::ON); + button->update(); + + } + +// DSPMode mode = m_dspModeList.at(m_hamBand); +// if (mode != rxData.dspModeList.at(m_hamBand)) { +// +// m_dspModeList[m_hamBand] = rxData.dspModeList.at(m_hamBand); +// +// foreach(AeroButton *btn, dspModeBtnList) { +// +// btn->setBtnState(AeroButton::OFF); +// btn->update(); +// } +// qDebug() << "*********************** RadioWidget: DSPmode changed by changed receiver!"; +// AeroButton *button = dspModeBtnList.at(mode); +// button->setBtnState(AeroButton::ON); +// button->update(); +// +// filterGroupChanged(mode); +// filterChanged(this, m_currentRx, m_filterLo, m_filterHi); +// } + +// if (m_agcMode != rxData.agcMode) { +// m_agcMode = rxData.agcMode; +// } + + if (m_filterLo != rxData.filterLo || m_filterHi != rxData.filterHi) { + + m_filterLo = rxData.filterLo; + m_filterHi = rxData.filterHi; + filterChanged(this, m_currentRx, m_filterLo, m_filterHi); + } +} + +// ********************** + +void RadioWidget::systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state +) { + Q_UNUSED(sender) + Q_UNUSED(err) + Q_UNUSED(hwmode) + Q_UNUSED(mode) + Q_UNUSED(state) + + +} + +void RadioWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void RadioWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + + diff --git a/Source/src/cusdr_radioWidget.h b/Source/src/cusdr_radioWidget.h new file mode 100644 index 0000000..5d30008 --- /dev/null +++ b/Source/src/cusdr_radioWidget.h @@ -0,0 +1,209 @@ +/** +* @file cusdr_radioWidget.h +* @brief Radio control widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2011-02-10 +*/ + +/* + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_RADIO_WIDGET_H +#define _CUSDR_RADIO_WIDGET_H + +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + + +class RadioWidget : public QWidget { + + Q_OBJECT + +public: + RadioWidget(QWidget *parent = 0); + ~RadioWidget(); + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + +private: + Settings *set; + + QGroupBox *bandGroupBox; + QGroupBox *modeGroupBox; + QGroupBox *filterGroupABox; + QGroupBox *filterGroupBBox; + QGroupBox *filterGroupCBox; + QGroupBox *mercuryBtnGroup(); + + QList filterBtnListA; + QList filterBtnListB; + QList filterBtnListC; + + AeroButton *band2200mBtn; + AeroButton *band630mBtn; + AeroButton *band160mBtn; + AeroButton *band80mBtn; + AeroButton *band60mBtn; + AeroButton *band40mBtn; + AeroButton *band30mBtn; + AeroButton *band20mBtn; + AeroButton *band17mBtn; + AeroButton *band15mBtn; + AeroButton *band12mBtn; + AeroButton *band10mBtn; + AeroButton *band6mBtn; + AeroButton *bandGenBtn; + //AeroButton *bandxxBtn; + + QList bandBtnList; + QList dspModeBtnList; + + AeroButton *lsbBtn; + AeroButton *usbBtn; + AeroButton *dsbBtn; + AeroButton *cwlBtn; + AeroButton *cwuBtn; + AeroButton *fmnBtn; + AeroButton *amBtn; + AeroButton *diguBtn; + AeroButton *specBtn; + AeroButton *diglBtn; + AeroButton *samBtn; + AeroButton *drmBtn; + + AeroButton *filter1kBtnA; + AeroButton *filter1k8BtnA; + AeroButton *filter2k1BtnA; + AeroButton *filter2k4BtnA; + AeroButton *filter2k7BtnA; + AeroButton *filter2k9BtnA; + AeroButton *filter3k3BtnA; + AeroButton *filter3k8BtnA; + AeroButton *filter4k4BtnA; + AeroButton *filter5kBtnA; + AeroButton *filterVar1BtnA; + AeroButton *filterVar2BtnA; + + AeroButton *filter2k4BtnB; + AeroButton *filter2k9BtnB; + AeroButton *filter3k1BtnB; + AeroButton *filter4kBtnB; + AeroButton *filter5k2BtnB; + AeroButton *filter6k6BtnB; + AeroButton *filter8kBtnB; + AeroButton *filter10kBtnB; + AeroButton *filter12kBtnB; + AeroButton *filter16kBtnB; + AeroButton *filterVar1BtnB; + AeroButton *filterVar2BtnB; + + AeroButton *filter25BtnC; + AeroButton *filter50BtnC; + AeroButton *filter100BtnC; + AeroButton *filter250BtnC; + AeroButton *filter400BtnC; + AeroButton *filter500BtnC; + AeroButton *filter600BtnC; + AeroButton *filter750BtnC; + AeroButton *filter800BtnC; + AeroButton *filter1kBtnC; + AeroButton *filterVar1BtnC; + AeroButton *filterVar2BtnC; + + AeroButton *attenuatorBtn; + AeroButton *ditherBtn; + AeroButton *randomBtn; + + QIcon agc_left; + QIcon agc_right; + + QList m_receiverDataList; + QList m_dspModeList; + HamBand m_hamBand; + //DSPMode m_dspMode; + AGCMode m_agcMode; + TDefaultFilterMode m_filterMode; + + //QList m_lastFrequencyList; + QList m_lastCtrFrequencyList; + QList m_lastVfoFrequencyList; + + long m_ctrFrequency; + long m_vfoFrequency; + + qreal m_filterLo; + qreal m_filterHi; + + int m_currentRx; + int current_band; + int current_dsp_mode; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + +private slots: + void createBandBtnGroup(); + void createModeBtnGroup(); + void createFilterBtnGroupA(); + void createFilterBtnGroupB(); + void createFilterBtnGroupC(); + + QLabel *createLabel(const QString &text); + + void setCurrentReceiver(QObject *sender, int value); + void ctrFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + void vfoFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + void bandChangedByBtn(); + void bandChanged(QObject *sender, int rx, bool byButton, HamBand band); + void dspModeChangedByBtn(); + void dspModeChanged(QObject *sender, int rx, DSPMode mode); + void filterChangedByBtn(); + void filterChanged(QObject *sender, int rx, qreal low, qreal high); + void filterGroupChanged(DSPMode mode); + + void attenuatorChanged(); + void setMercuryAttenuator(QObject *sender, HamBand band, int value); + void ditherChanged(); + void randomChanged(); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void newMessage(QString msg); +}; + +#endif // _CUSDR_RADIO_WIDGET_H diff --git a/Source/src/cusdr_receiverWidget.cpp b/Source/src/cusdr_receiverWidget.cpp new file mode 100644 index 0000000..f8ca464 --- /dev/null +++ b/Source/src/cusdr_receiverWidget.cpp @@ -0,0 +1,125 @@ +/** +* @file cusdr_receiverWidget.cpp +* @brief receiver widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-22 +*/ + +/* + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#include +//#include +#include + +#include "cusdr_receiverWidget.h" +#include "cusdr_settings.h" + +#define btn_height 15 +#define btn_width 60 +#define btn_widths 40 + + +ReceiverWidget::ReceiverWidget() + : QWidget() +{ + setObjectName("ReceiverWidget"); + + setMouseTracking(true); + //mouse_over = false; + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(1); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + //mainLayout->addWidget(dspBtnGroup()); + //mainLayout->addSpacing(5); + //mainLayout->addWidget(fftwExtGroup()); + mainLayout->addStretch(); + + setLayout(mainLayout); + + setContentsMargins(5, 5, 5, 5); +} + +ReceiverWidget::~ReceiverWidget() { + + disconnect(Settings::instance(), 0, this, 0); + disconnect(this, 0, 0, 0); +} + + + +// ********************** + +void ReceiverWidget::closeEvent(QCloseEvent *event) { + + //settings::instance()->serverFormRect = QRect(pos(), size()); + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void ReceiverWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +//*************************************************** + +MiniReceiverWidget::MiniReceiverWidget() + : QWidget() +{ + setObjectName("MiniReceiverWidget"); + + setMouseTracking(true); + //mouse_over = false; + + QFont titleFont; + titleFont.setStyleStrategy(QFont::PreferQuality); + titleFont.setPointSizeF(8); + titleFont.setFamily("Arial"); + + setContentsMargins(5, 5, 5, 5); +} + +MiniReceiverWidget::~MiniReceiverWidget() { + + disconnect(Settings::instance(), 0, this, 0); + disconnect(this, 0, 0, 0); +} + + + +// ********************** + +void MiniReceiverWidget::closeEvent(QCloseEvent *event) { + + //settings::instance()->serverFormRect = QRect(pos(), size()); + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void MiniReceiverWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} diff --git a/Source/src/cusdr_receiverWidget.h b/Source/src/cusdr_receiverWidget.h new file mode 100644 index 0000000..87309d5 --- /dev/null +++ b/Source/src/cusdr_receiverWidget.h @@ -0,0 +1,98 @@ +/** +* @file cusdr_receiverWidget.h +* @brief receiver widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-22 +*/ + +/* + * Copyright 2010, 2011 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_RECEIVER_WIDGET_H +#define CUSDR_RECEIVER_WIDGET_H + +//#include +//#include +//#include + +#include "cusdr_settings.h" +#include "Util/cusdr_buttons.h" + +class MiniReceiverWidget; + + +class ReceiverWidget : public QWidget { + + Q_OBJECT + +public: + ReceiverWidget(); + ~ReceiverWidget(); + +public slots: + //void dspServerChanged(); + //void setClientConnected(QObject *sender, bool value); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + +private: + QList miniRxList; + MiniReceiverWidget *miniRx; + + //QGroupBox *dspBtnGroup(); + //QGroupBox *fftwIntGroup(); + //QGroupBox *fftwExtGroup(); + + //QHButton *cudaBtn; + //QHButton *fftwIntBtn; + //QHButton *fftwExtBtn; + //QHButton *launchDSPBtn; + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); +}; + + +class MiniReceiverWidget : public QWidget { + + Q_OBJECT + +public: + MiniReceiverWidget(); + ~MiniReceiverWidget(); + +public slots: + //void dspServerChanged(); + //void setClientConnected(QObject *sender, bool value); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + +private: + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); +}; + +#endif // CUSDR_RECEIVER_WIDGET_H diff --git a/Source/src/cusdr_server.cpp b/Source/src/cusdr_server.cpp new file mode 100644 index 0000000..d1945ec --- /dev/null +++ b/Source/src/cusdr_server.cpp @@ -0,0 +1,495 @@ +/** +* @file cusdr_server.cpp +* @brief Server implementation class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-10-28 +*/ + +/* + * Copyright (C) John Melton, G0ORX/N6LYT and Dave McMcQuate, WA8YWQ + * + * Copyright 2010 adaptation for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +//#define LOG_SERVER + +#include "cusdr_server.h" +#include "cusdr_settings.h" + + + +HPSDRServer::HPSDRServer(QObject *parent) + : QTcpServer(parent) + , set(Settings::instance()) + , m_hwInterface(set->getHWInterface()) + , m_serverMode(set->getCurrentServerMode()) + , m_dataEngineState(QSDR::DataEngineDown) +{ + setupConnections(); + + for (int i = 0; i < MAX_RECEIVERS; i++) + m_receivers[i] = -1; + + m_separators = " ,\r\n"; +} + +HPSDRServer::~HPSDRServer() { + + serverStop(); + m_rxList.clear(); + //m_ipList.clear(); + //m_niList.clear(); + qDeleteAll(m_clientConnections); +} + +void HPSDRServer::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(masterSwitchChanged(QObject *, bool)), + this, + SLOT(masterSwitchChanged(QObject *, bool))); + + CHECKED_CONNECT( + set, + SIGNAL(systemStateChanged( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState)), + this, + SLOT(setSystemState( + QObject *, + QSDR::_Error, + QSDR::_HWInterfaceMode, + QSDR::_ServerMode, + QSDR::_DataEngineState))); + + CHECKED_CONNECT( + set, + SIGNAL(rxListChanged(QList)), + this, + SLOT(rxListChanged(QList))); + + CHECKED_CONNECT( + this, + SIGNAL(clientDisconnectedEvent(int)), + set, + SLOT(clientDisconnected(int))); + + CHECKED_CONNECT( + this, + SIGNAL(newConnection()), + this, + SLOT(handleNewConnection())); +} + +void HPSDRServer::setSystemState( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + Q_UNUSED (err) + + if (m_hwInterface != hwmode) m_hwInterface = hwmode; + + if (m_serverMode != mode) m_serverMode = mode; + + if (m_dataEngineState == state) return; + m_dataEngineState = state; +} + +bool HPSDRServer::startServer() { + + // listen for new connections + if (!listen(QHostAddress::Any, set->getListenPort())) { + + m_message = tr("[server]: unable to start the listening service: '%1'."); + emit messageEvent(m_message.arg(errorString())); + + return false; + } + + m_message = tr("[server]: is running on '%1:%2'."); + emit messageEvent(m_message.arg(set->getServerAddr()).arg(serverPort())); + + return true; +} + +void HPSDRServer::stopServer() { + + if (isListening()) { // was the listener started? + + // shut down output_thread(s) + emit messageEvent("[server]: shutting down the server..."); + + // clear TCP/IP connections list + foreach(QTcpSocket *socket, m_clientConnections) { + + socket->close(); + } + m_clientConnections.clear(); + SERVER_DEBUG << "masterSwitchChanged TCP client socket(s) closed."; + + // shutdown TCP/IP command server + serverStop(); + SERVER_DEBUG <<"masterSwitchChanged TCP server closed."; + } +} + +void HPSDRServer::rxListChanged(QList rxList) { + + QMutexLocker locker(&m_serverMutex); + m_rxList = rxList; + locker.unlock(); +} + +void HPSDRServer::masterSwitchChanged(QObject *sender, bool power) { + + Q_UNUSED(sender) + Q_UNUSED(power) +} + +void HPSDRServer::serverStop() { + + //disconnect(this, 0, 0, 0); + close(); +} + +void HPSDRServer::handleNewConnection() { + + while (hasPendingConnections()) { + + QTcpSocket *socket = nextPendingConnection(); + + CHECKED_CONNECT( + socket, + SIGNAL(disconnected()), + this, + SLOT(clientDisconnected())); + + CHECKED_CONNECT( + socket, + SIGNAL(readyRead()), + this, + SLOT(readCommand())); + + QString message = tr("[server]: client connected from %1 on port %2."); + emit messageEvent(message.arg(socket->peerAddress().toString()).arg(socket->peerPort())); + + m_clientConnections.append(socket); + } +} + +void HPSDRServer::clientDisconnected() { + + QTcpSocket *socket = qobject_cast(sender()); + + if (!socket) return; + + int client = m_clientConnections.indexOf(socket); + + m_clientConnections.removeAll(socket); + socket->deleteLater(); + + detachReceiver(client, client); + + m_message = tr("[server]: client %1 disconnected."); + emit messageEvent(m_message.arg(client)); + + emit clientDisconnectedEvent(client); +} + +void HPSDRServer::sendMessageToAllClients() { + + m_message = QString("This is the cudaSDR server!"); + + foreach(QTcpSocket *client, m_clientConnections) { + + client->write(m_message.toLatin1()); + } +} + +void HPSDRServer::readCommand() { + + QTcpSocket *socket = qobject_cast(sender()); + + m_bytesRead = socket->read(command, sizeof(command)); + + command[m_bytesRead] = 0; + + int client = m_clientConnections.indexOf(socket); + + response = parseCommand(command, client); + socket->write(response); + + //QString message = tr("[server]: response(rx %1): '%2'."); + //emit messageEvent(message.arg(receivers[client]).arg(response)); +} + +char *HPSDRServer::attachReceiver(int rx, int client) { + + if (m_rxList[rx]->property("socketState") == Receiver::RECEIVER_ATTACHED) + return CLIENT_ATTACHED; + + if (rx >= m_rxList.size()) + return RECEIVER_INVALID; + + if (m_rxList[rx]->getConnectedStatus()) + return RECEIVER_IN_USE; + + m_rxList[rx]->setProperty("socketState", "RECEIVER_ATTACHED"); + m_rxList[rx]->setReceiver(rx); + m_rxList[rx]->setClient(client); + m_rxList[rx]->setPeerAddress(m_clientConnections[client]->peerAddress()); + + m_rxList[rx]->setIQPort(-1); + set->setIQPort(this, rx, -1); + + SERVER_DEBUG << "attachReceiver client" + << m_rxList[rx]->getClient() + << "connected to receiver" + << m_rxList[rx]->getReceiver(); + + m_receivers[client] = rx; + + set->setClientConnected(this, true); + set->setClientNoConnected(this, client); + + static char resp[80]; + //sprintf_s(resp, "%s %d", "OK", set->getSampleRate()); + + set->setRxList(m_rxList); + + return resp; +} + +char *HPSDRServer::detachReceiver(int rx, int client) { + + //if (m_rxList[rx]->property("socketState") == HPSDRReceiver::RECEIVER_ATTACHED) + // return CLIENT_DETACHED; + + if (rx >= set->getNumberOfReceivers()) + return RECEIVER_INVALID; + + //if (m_rxList[rx]->client != (HPSDRClient *) NULL) + // return RECEIVER_NOT_OWNER; + + m_serverMutex.lock(); + m_rxList[rx]->setProperty("socketState", "RECEIVER_DETACHED"); + m_rxList[rx]->setConnectedStatus(false); + m_serverMutex.unlock(); + + SleeperThread::msleep(200); + + set->setRcveIQ(0); + set->setSendIQ(0); + + m_receivers[client] = -1; + + set->setRxList(m_rxList); + + return OK; +} + +char *HPSDRServer::setFrequency(long frequency, int rx) { + + if (m_rxList[rx]->property("socketState") == Receiver::RECEIVER_DETACHED) + return CLIENT_DETACHED; + + if (m_rxList[rx]->getReceiver() < 0) + return RECEIVER_INVALID; + + //emit frequencyChangedEvent(true, rx, frequency); + + set->setFrequency(this, true, rx, frequency); + + return OK; +} + +char *HPSDRServer::parseCommand(char *command, int client) { + + m_message = tr("[client %1]: command '%2'."); + + //token = strtok_s(command, seps, &next_token); + + if (token != NULL) { + + if (strcmp(token, "attach") == 0) { + + // select receiver + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + //int rx = atoi(token); + emit messageEvent(m_message.arg(client).arg(command)); + return attachReceiver(atoi(token), client); + } + else + return INVALID_COMMAND; + + } else if (strcmp(token, "detach") == 0) { + + // select receiver + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + //int rx = atoi(token); + emit messageEvent(m_message.arg(client).arg(command)); + return detachReceiver(atoi(token), client); + + } + else + return INVALID_COMMAND; + + } else if (strcmp(token, "frequency") == 0) { + + // set frequency + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + //long f = atol(token); + return setFrequency(atol(token), m_receivers[client]); + } + else + return INVALID_COMMAND; + + } else if (strcmp(token, "start") == 0) { + + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + if (strcmp(token, "iq") == 0) { + + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + emit setIQPortEvent(m_receivers[client], atoi(token)); + //emit setConnectedStatusEvent(receivers[client], true); + set->setRxConnectedStatus(this, m_receivers[client], true); + + // Remember the last receiver started, so that one will send demodulated data back to Mercury. + audioReceiver = m_receivers[client]; + + //emit newClientEvent(receivers[client]); + set->setClientNoConnected(this, m_receivers[client]); + //emit audioReceiverEvent(audioReceiver); + set->setAudioRx(this, audioReceiver); + + return OK; + } + else + return INVALID_COMMAND; + + } else if (strcmp(token, "bandscope") == 0) { + + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + m_rxList[client]->setBSPort(atoi(token)); + emit messageEvent(m_message.arg(client).arg(command)); + set->setRxList(m_rxList); + return OK; + + } else { + // invalid command string + return INVALID_COMMAND; + } + } + else + return INVALID_COMMAND; + } + else + return INVALID_COMMAND; + + } else if (strcmp(token, "stop" ) == 0) { + + //token = strtok_s(NULL, seps, &next_token); + + if (token != NULL) { + + if (strcmp(token, "iq") == 0) { + + m_rxList[client]->setIQPort(-1); + set->setRxList(m_rxList); + return OK; + + } else if (strcmp(token, "bandscope") == 0) { + + m_rxList[client]->setBSPort(-1); + set->setRxList(m_rxList); + return OK; + + } + else + return INVALID_COMMAND; + } + else + return INVALID_COMMAND; + + } + else if (strcmp(token, "selectAudio") == 0) { + + // change selection of which receiver's audio goes to Mercury headphone output + //token = strtok_s(NULL, seps, &next_token); + if (token != NULL) { + + selectAudio = atoi(token); + if ( (selectAudio >= 0) + && (selectAudio < set->getNumberOfReceivers()) + && (m_rxList[selectAudio]->getConnectedStatus()) + ) { + //m_dataEngine->AudioReceiverChanged(selectAudio); + emit messageEvent(m_message.arg(client).arg(command)); + //emit audioReceiverEvent(selectAudio); + set->setAudioRx(this, selectAudio); + return OK; + + } + else + return RECEIVER_INVALID; + } + else + return RECEIVER_INVALID; + + } + else + return INVALID_COMMAND; + + } + else + return INVALID_COMMAND; + + return INVALID_COMMAND; +} + +void HPSDRServer::newMessage(QString message) { + + emit messageEvent(message); +} diff --git a/Source/src/cusdr_server.h b/Source/src/cusdr_server.h new file mode 100644 index 0000000..d074f4c --- /dev/null +++ b/Source/src/cusdr_server.h @@ -0,0 +1,134 @@ +/** +* @file cusdr_server.h +* @brief Server implementation header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-10-28 +*/ + +/* + * Copyright (C) John Melton, G0ORX/N6LYT and Dave McMcQuate, WA8YWQ + * + * Copyright 2010 adaptation for cuSDR by Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + */ + +#ifndef CUSDR_SERVER_H +#define CUSDR_SERVER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cusdr_receiver.h" + + +#ifdef LOG_SERVER +# define SERVER_DEBUG qDebug().nospace() << "Server::\t" +#else +# define SERVER_DEBUG nullDebug() +#endif + + +class HPSDRServer : public QTcpServer { + + Q_OBJECT + +public: + explicit HPSDRServer(QObject *parent = 0); + ~HPSDRServer(); + + +public slots: + bool startServer(); + void stopServer(); + void serverStop(); + + int getAudioReceiver() { return audioReceiver; } + +private: + Settings* set; + + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QList m_rxList; + QList m_clientConnections; + + int m_receivers[MAX_RECEIVERS]; + + QMutex m_serverMutex; + + QString m_message; + QString m_separators; + + qint64 m_bytesRead; + + char command[80]; + //char* seps; + char* token; + char* next_token; + char* response; + + int socketDescriptor; + int audioReceiver; + int selectAudio; + +private slots: + void setSystemState( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void masterSwitchChanged(QObject *sender, bool power); + void rxListChanged(QList rxList); + void setupConnections(); + void handleNewConnection(); + void clientDisconnected(); + void newMessage(QString message); + void sendMessageToAllClients(); + void readCommand(); + + char* attachReceiver(int rx, int client); + char* detachReceiver(int rx, int client); + char* parseCommand(char *command, int client); + char* setFrequency(long frequency, int client); + +signals: + void masterSwitchEvent(); + void messageEvent(QString message); + + void setIQPortEvent(int rx, int port); + void socketErrorEvent(int socketErrorCode, QString socketErrorString, QString addr, quint16 port); + void setPeerAddressEvent(int rx, QHostAddress address); + void clientConnectedEvent(int rx); + void clientDisconnectedEvent(int client); + void frequencyChangedEvent(bool value, int rx, long frequency); + void newClientEvent(int rx); + void audioReceiverEvent(int rx); +}; + + +#endif // CUSDR_SERVER_H diff --git a/Source/src/cusdr_serverWidget.cpp b/Source/src/cusdr_serverWidget.cpp new file mode 100644 index 0000000..bc2bcce --- /dev/null +++ b/Source/src/cusdr_serverWidget.cpp @@ -0,0 +1,334 @@ +/** +* @file cusdr_serverWidget.cpp +* @brief hpsdr server settings widget +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#define LOG_SERVER_WIDGET + +//#include +//#include +//#include +#include +#include +#include + +#include "cusdr_serverWidget.h" + +#define btn_height 15 +#define btn_width 80 +#define btn_width2 52 + +ServerWidget::ServerWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_serverMode(Settings::instance()->getCurrentServerMode()) + , m_minimumWidgetWidth(Settings::instance()->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(Settings::instance()->getMinimumGroupBoxWidth()) + , m_btnSpacing(5) +{ + //setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 0, 4, 0); + setMouseTracking(true); + + createServerNIGroup(); + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(0); + hbox1->setMargin(0); + hbox1->addStretch(); + hbox1->addWidget(serverNIGroupBox); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(0); + hbox2->setMargin(0); + hbox2->addStretch(); + hbox2->addWidget(portAddressesGroup()); + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addStretch(); + + setLayout(mainLayout); + + setupConnections(); + setPorts(); +} + +ServerWidget::~ServerWidget() { + + // disconnect all signals + disconnect(Settings::instance(), 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize ServerWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize ServerWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void ServerWidget::setupConnections() { + + CHECKED_CONNECT( + set, + SIGNAL(newServerNetworkInterface(QString, QString)), + this, + SLOT(addServerNIEntry(QString, QString))); + + CHECKED_CONNECT( + set, + SIGNAL(serverNICChanged(int)), + this, + SLOT(setServerNIC(int))); +} + +void ServerWidget::addNICChangedConnection() { + + CHECKED_CONNECT( + serverNetworkInterfaces, + SIGNAL(currentIndexChanged(int)), + set, + SLOT(setServerNetworkInterface(int))); +} + +void ServerWidget::createServerNIGroup() { + + serverNetworkInterfaces = new QComboBox(); + + serverNetworkInterfaces->setStyleSheet(Settings::instance()->getComboBoxStyle()); + serverNetworkInterfaces->setMinimumContentsLength(22); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(1); + hbox1->addWidget(serverNetworkInterfaces); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(5); + vbox->addSpacing(5); + vbox->addLayout(hbox1); + vbox->addSpacing(5); + //vbox->addLayout(hbox2); + + serverNIGroupBox = new QGroupBox(tr("Server network interface")); + serverNIGroupBox->setMinimumWidth(m_minimumGroupBoxWidth); + serverNIGroupBox->setLayout(vbox); + serverNIGroupBox->setStyleSheet(Settings::instance()->getWidgetStyle()); + serverNIGroupBox->setFont(QFont("Arial", 8)); +} + +void ServerWidget::addServerNIEntry(QString niName, QString ipAddress) { + + //QString item = niName; + QString item = ipAddress; + //item.append(" ("); + //item.append(ipAddress); + //item.append(")"); + serverNetworkInterfaces->addItem(item); +} + +QGroupBox *ServerWidget::portAddressesGroup() { + + portGridBox = new QGridLayout; + portGridBox->setVerticalSpacing(3); + //portGridBox->setHorizontalSpacing(43); + + labelServerPortLabel = new QLabel("Command Server Port:"); + labelServerPortLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + labelServerPortLabel->setStyleSheet(Settings::instance()->getLabelStyle()); + portGridBox->addWidget(labelServerPortLabel, 0, 0); + + labelServerPortText = new QLabel(""); + labelServerPortText->setFrameStyle(QFrame::Box | QFrame::Raised); + labelServerPortText->setStyleSheet(Settings::instance()->getLabelStyle()); + portGridBox->addWidget(labelServerPortText, 0, 1); + + labelListenerPortLabel = new QLabel("Listener Port:"); + labelListenerPortLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + labelListenerPortLabel->setStyleSheet(Settings::instance()->getLabelStyle()); + portGridBox->addWidget(labelListenerPortLabel, 1, 0); + + labelListenerPortText = new QLabel(""); + labelListenerPortText->setFrameStyle(QFrame::Box | QFrame::Raised); + labelListenerPortText->setStyleSheet(Settings::instance()->getLabelStyle()); + portGridBox->addWidget(labelListenerPortText, 1, 1); + + labelAudioPortLabel = new QLabel("Audio Port:"); + labelAudioPortLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + labelAudioPortLabel->setStyleSheet(Settings::instance()->getLabelStyle()); + portGridBox->addWidget(labelAudioPortLabel, 2, 0); + + labelAudioPortText = new QLabel(""); + labelAudioPortText->setFrameStyle(QFrame::Box | QFrame::Raised); + labelAudioPortText->setStyleSheet(Settings::instance()->getLabelStyle()); + portGridBox->addWidget(labelAudioPortText, 2, 1); + + /*le_server_port = new QLineEdit(QString::number(Settings::instance()->serverPort()), this); + le_server_port->setFont(font()); + le_server_port->setFixedSize(50, QFontMetrics(le_server_port->font()).height() + 4); + le_server_port->setInputMask("00000;"); + le_server_port->setMaxLength(7); + le_server_port->setStyleSheet(lineedit_style);*/ + + /*QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(1); + hbox1->addWidget(le_server_port); + hbox1->addStretch();*/ + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(portGridBox); + + QGroupBox *groupBox = new QGroupBox(tr("Port Addresses")); + groupBox->setMinimumWidth(m_minimumGroupBoxWidth); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(Settings::instance()->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +QGroupBox *ServerWidget::serverPortAddressGroup() { + + le_server_port = new QLineEdit(QString::number(Settings::instance()->getServerPort()), this); + le_server_port->setFont(font()); + le_server_port->setFixedSize(50, QFontMetrics(le_server_port->font()).height() + 4); + le_server_port->setInputMask("00000;"); + le_server_port->setMaxLength(7); + le_server_port->setStyleSheet(lineedit_style); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(1); + hbox1->addWidget(le_server_port); + hbox1->addStretch(); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + QGroupBox *groupBox = new QGroupBox(tr("Command Server port")); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(Settings::instance()->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +QGroupBox *ServerWidget::listenerPortAddressGroup() { + + le_listener_port = new QLineEdit(QString::number(Settings::instance()->getListenPort()), this); + le_listener_port->setFont(font()); + le_listener_port->setFixedSize(50, le_server_port->height()); + le_listener_port->setInputMask("00000;"); + le_listener_port->setMaxLength(7); + le_listener_port->setStyleSheet(lineedit_style); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(1); + hbox1->addWidget(le_listener_port); + hbox1->addStretch(); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + QGroupBox *groupBox = new QGroupBox(tr("Listener port")); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(Settings::instance()->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + +QGroupBox *ServerWidget::audioPortAddressGroup() { + + le_audio_port = new QLineEdit(QString::number(Settings::instance()->getAudioPort()), this); + le_audio_port->setFont(font()); + le_audio_port->setFixedSize(50, le_server_port->height()); + le_audio_port->setInputMask("00000;"); + le_audio_port->setMaxLength(7); + le_audio_port->setStyleSheet(lineedit_style); + + QHBoxLayout *hbox1 = new QHBoxLayout; + hbox1->setSpacing(1); + hbox1->addWidget(le_audio_port); + hbox1->addStretch(); + + QVBoxLayout *vbox = new QVBoxLayout; + vbox->setSpacing(1); + vbox->addLayout(hbox1); + + QGroupBox *groupBox = new QGroupBox(tr("Audio port")); + groupBox->setLayout(vbox); + groupBox->setStyleSheet(Settings::instance()->getWidgetStyle()); + groupBox->setFont(QFont("Arial", 8)); + + return groupBox; +} + + + +// *************************************************************** + +void ServerWidget::setServerNIC(int index) { + + serverNetworkInterfaces->setCurrentIndex(index); +} + +void ServerWidget::setPorts() { + + labelServerPortText->setText(QString::number(Settings::instance()->getServerPort())); + labelListenerPortText->setText(QString::number(Settings::instance()->getListenPort())); + labelAudioPortText->setText(QString::number(Settings::instance()->getAudioPort())); +} + +void ServerWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void ServerWidget::showEvent(QShowEvent *event) { + + //emit showEvent(this); + + QWidget::showEvent(event); +} + +void ServerWidget::portChanged(const QString &text) { + + bool ok = false; + int port = text.toInt(&ok); + if (!ok || port < 0 || port >= 65536) return; + //Settings::instance()->setServerPort(port_le, port); +} + diff --git a/Source/src/cusdr_serverWidget.h b/Source/src/cusdr_serverWidget.h new file mode 100644 index 0000000..e587572 --- /dev/null +++ b/Source/src/cusdr_serverWidget.h @@ -0,0 +1,118 @@ +/** +* @file cusdr_serverWidget.h +* @brief header file for hpsdr server settings widget +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-21 +*/ + +/* + * + * Copyright 2010 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_SERVER_WIDGET_H +#define _CUSDR_SERVER_WIDGET_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + +#ifdef LOG_SERVER_WIDGET +# define SERVER_WIDGET_DEBUG qDebug().nospace() << "ServerWidget::\t" +#else +# define SERVER_WIDGET_DEBUG nullDebug() +#endif + + +class ServerWidget : public QWidget { + + Q_OBJECT + +public: + ServerWidget(QWidget *parent = 0); + ~ServerWidget(); + + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + void addServerNIEntry(QString niName, QString ipAddress); + void addNICChangedConnection(); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + +private: + Settings *set; + + QStringList niList; + QTableWidget *serverNITable; + + QGroupBox *portAddressesGroup(); + QGroupBox *serverPortAddressGroup(); + QGroupBox *listenerPortAddressGroup(); + QGroupBox *audioPortAddressGroup(); + QGroupBox *serverNIGroupBox; + + QGridLayout *portGridBox; + QComboBox *serverNetworkInterfaces; + + QLabel *labelServerPortLabel; + QLabel *labelServerPortText; + QLabel *labelListenerPortLabel; + QLabel *labelListenerPortText; + QLabel *labelAudioPortLabel; + QLabel *labelAudioPortText; + + QLineEdit *le_server_address; + QLineEdit *le_server_port; + QLineEdit *le_listener_port; + QLineEdit *le_audio_port; + + QString lineedit_style; + + QSDR::_ServerMode m_serverMode; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + int m_btnSpacing; + + void createServerNIGroup(); + +private slots: + void setPorts(); + void setupConnections(); + void portChanged(const QString &text); + void setServerNIC(int index); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString ); +}; + +#endif // _CUSDR_SERVER_WIDGET_H diff --git a/Source/src/cusdr_settings.cpp b/Source/src/cusdr_settings.cpp new file mode 100644 index 0000000..2180c0c --- /dev/null +++ b/Source/src/cusdr_settings.cpp @@ -0,0 +1,4627 @@ +/** +* @file cusdr_settings.cpp +* @brief settings class for cuSDR +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-18 +*/ + +/* + * Copyright 2010, 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + + +#define LOG_SETTINGS + +#include "cusdr_settings.h" +#include "Util/cusdr_styles.h" + +Settings *Settings::m_instance = NULL; /*!< set m_instance to NULL. */ + +/*! + \class Settings + \brief Settings class implements application specific and user defined variables for the application. +*/ + +Settings::Settings(QObject *parent) + :QObject(parent) + , m_dataEngineState(QSDR::DataEngineDown) + , setLoaded(false) + , m_mainPower(false) + , m_manualSocketBufferSize(false) + , m_peakHold(false) + , m_packetsToggle(true) + , m_radioPopupVisible(false) + , m_hpsdrNetworkDevices(0) + , m_mercuryReceivers(1) + , m_currentReceiver(0) +{ + m_devices.mercuryFWVersion = 0; + + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType(); + qRegisterMetaType >(); + qRegisterMetaType("qVectorFloat"); + + startTime = QDateTime::currentDateTime(); + + qDebug() << "************************************************************************"; + SETTINGS_DEBUG << "start at: " << qPrintable(startTime.toString()); + + settingsFilename = "settings.ini"; + settings = new QSettings(QCoreApplication::applicationDirPath() + "/" + settingsFilename, QSettings::IniFormat); + + m_titleString = "cudaSDR BETA "; + + #ifdef DEBUG + m_titleString = "cudaSDR Debug BETA "; + #endif + + m_versionString = "v0.3.2.13"; + + qDebug() << qPrintable(m_titleString); + + // receiver data + for (int i = 0; i < MAX_RECEIVERS; i++) { + + TReceiver receiverData; + m_receiverDataList.append(receiverData); + + QString str = "receiver"; + QString num; + num.setNum(i); + str.append(num); + + m_rxStringList << str; + + m_receiverDataList[i].agcHangThreshold = 0.0; + m_receiverDataList[i].peakHold = false; + + for (int j = 0; j < MAX_BANDS; j++) { + + m_receiverDataList[i].mercuryAttenuators << 0; + m_receiverDataList[i].dBmPanScaleMinList << 0.0; + m_receiverDataList[i].dBmPanScaleMaxList << 0.0; + m_receiverDataList[i].dspModeList << (DSPMode) LSB; + } + } + + // Alex parameter configurations + m_alexConfig = 0; + + for (int i = 0; i < 6; i++) { + + m_HPFLoFrequencyList.append((long)0); + m_HPFHiFrequencyList.append((long)0); + } + + for (int i = 0; i < 7; i++) { + + m_LPFLoFrequencyList.append((long)0); + m_LPFHiFrequencyList.append((long)0); + } + + // init alex states + for (int i = 0; i < MAX_BANDS; i++) { + + m_alexStates << 0; + } + + // Rx, Tx J6 pins list + // Bands: 160m, 80m, 60m, 40m, 30m, 20m, 17m, 15m, 12m, 10m, 6m + // Values: no pin, pins 1 to 7 (0..7) + // + // 0 0 0 0 0 0 0 0 + // | | | | | | | + // | | | | | | | + // | | | | | | +-------------- pin 1 (0 = deactivated, 1 = activated) + // | | | | | +---------------- pin 2 (0 = deactivated, 1 = activated) + // | | | | +------------------ pin 3 (0 = deactivated, 1 = activated) + // | | | +-------------------- pin 4 (0 = deactivated, 1 = activated) + // | | +---------------------- pin 5 (0 = deactivated, 1 = activated) + // | +------------------------ pin 6 (0 = deactivated, 1 = activated) + // +-------------------------- pin 7 (0 = deactivated, 1 = activated) + + for (int i = 0; i < MAX_BANDS-1; i++) { + + m_rxJ6pinList << 0; + m_txJ6pinList << 0; + } + + + m_bandList = getHamBandFrequencies(); + m_bandTextList = getHamBandText(); + m_defaultFilterList = getDefaultFilterFrequencies(); + + m_transmitter.txAllowed = false; + m_fft = 1; +} + +Settings::~Settings() { + + //m_clDevices.clear(); +} + +int Settings::loadSettings() { + + QString str; + int value; + + //QList bandList = HamBandStrings(); + + // user's call sign + str = settings->value("user/callSign", "Your Call sign").toString(); + //while (str.startsWith('\"')) str = str.right(str.count() - 1).trimmed(); + //while (str.endsWith('\"')) str = str.left(str.count() - 1).trimmed(); + + m_callsignString = str; + + // Window settings + value = settings->value("window/minimumWidgetWidth", 235).toInt(); + if (value < 235 || value > 300) m_minimumWidgetWidth = 235; + m_minimumWidgetWidth = value; + + value = settings->value("window/minimumGroupBoxWidth", 230).toInt(); + if (value < 230 || value > 295 || value > m_minimumWidgetWidth - 5) m_minimumGroupBoxWidth = 230; + m_minimumGroupBoxWidth = value; + + value = settings->value("window/multiRxView", 0).toInt(); + if (value < 0 || value > 2) m_multiRxView = 0; + m_multiRxView = value; + + + // network settings + str = settings->value("network/server_ipAddress", "127.0.0.1").toString(); + while (str.startsWith('\"')) str = str.right(str.count() - 1).trimmed(); + while (str.endsWith('\"')) str = str.left(str.count() - 1).trimmed(); + m_serverAddress = str; + + str = settings->value("network/hpsdr_local_ipAddress", "127.0.0.1").toString(); + while (str.startsWith('\"')) str = str.right(str.count() - 1).trimmed(); + while (str.endsWith('\"')) str = str.left(str.count() - 1).trimmed(); + m_hpsdrDeviceLocalAddr = str; + + value = settings->value("network/server_port", 52685).toInt(); + if (value < 0 || value > 65535) value = 52685; + m_serverPort = value; + + value = settings->value("network/listen_port", 11000).toInt(); + if (value < 0 || value > 65535) value = 11000; + m_listenerPort = value; + + value = settings->value("network/audio_port", 15000).toInt(); + if (value < 0 || value > 65535) value = 15000; + m_audioPort = value; + + value = settings->value("network/metis_port", 1024).toInt(); + if (value < 0 || value > 65535) value = 1024; + m_metisPort = value; + + value = settings->value("network/socketBufferSize", 32).toInt(); + if (value != 16 && value != 32 && value != 64 && value != 128 && value != 256) value = 32; + m_socketBufferSize = value; + + + // HPSDR hardware + value = settings->value("hpsdr/hardware", 0).toInt(); + if (value < 0 || value > 2) value = 0; + m_hpsdrHardware = value; + + str = settings->value("hpsdr/mercury", "true").toString(); + if (str == "true") + m_devices.mercuryPresence = true; + else + m_devices.mercuryPresence = false; + + str = settings->value("hpsdr/penelope", "false").toString(); + if (str == "true") + m_devices.penelopePresence = true; + else + m_devices.penelopePresence = false; + + str = settings->value("hpsdr/pennylane", "false").toString(); + if (str == "true") + m_devices.pennylanePresence = true; + else + m_devices.pennylanePresence = false; + + str = settings->value("hpsdr/excalibur", "false").toString(); + if (str == "true") + m_devices.excaliburPresence = true; + else + m_devices.excaliburPresence = false; + + str = settings->value("hpsdr/alex", "false").toString(); + if (str == "true") + m_devices.alexPresence = true; + else + m_devices.alexPresence = false; + + +// str = settings->value("hpsdr/hermes", "false").toString(); +// if (str == "true") +// m_devices.hermesPresence = true; +// else +// m_devices.hermesPresence = false; + + if (m_hpsdrHardware == 0) { + + str = settings->value("hpsdr/interface", "metis").toString(); + if (str == "metis") + m_hwInterface = QSDR::Metis; + else + m_hwInterface = QSDR::NoInterfaceMode; + } + else if (m_hpsdrHardware == 1) { + + m_hwInterface = QSDR::Hermes; + } + + str = settings->value("hpsdr/checkfw", "true").toString(); + if (str == "true") + m_checkFirmwareVersions = true; + else + m_checkFirmwareVersions = false; + + //checkHPSDRDevices(); + + value = settings->value("server/sample_rate", 48000).toInt(); + if ((value != 48000) & (value != 96000) & (value != 192000) & (value != 384000)) value = 48000; + setSampleRate(this, value); + + str = settings->value("server/dither", "off").toString(); + if (str.toLower() == "on") + m_mercuryDither = 1; + else + m_mercuryDither = 0; + + str = settings->value("server/random", "off").toString(); + if (str.toLower() == "on") + m_mercuryRandom = 1; + else + m_mercuryRandom = 0; + + str = settings->value("server/10mhzsource", "mercury").toString(); + if (str == "atlas") + m_10MHzSource = 0; + else if (str == "penelope") + m_10MHzSource = 1; + else if (str == "mercury") + m_10MHzSource = 2; + else if (str == "none") + m_10MHzSource = 3; + else + m_10MHzSource = 2; + + str = settings->value("server/122_88mhzsource", "mercury").toString(); + if (str == "penelope") + m_122_8MHzSource = 0; + else + m_122_8MHzSource = 1; + + str = settings->value("server/mic_source", "penelope").toString(); + if (str == "janus") + m_micSource = 0; + else + m_micSource = 1; + + str = settings->value("server/class", 0).toString(); + m_RxClass = (str.toLower() == "E"); + if (m_RxClass) + m_RxClass = 1; + else + m_RxClass = 0; + + value = settings->value("server/timing", 0).toInt(); + if (value < 0 || value > 1) value = 0; + m_RxTiming = value; + + /*value = settings->value("server/mainVolume", 10).toInt(); + if (value < 0) value = 0; + if (value > 100) value = 100; + m_mainVolume = value / 100.0f;*/ + + str = settings->value("server/mode", "sdr").toString(); + if (str == "sdr") { + + m_serverMode = QSDR::SDRMode; + setSpectrumSize(this, 4096); + } + else if (str == "chirpWSPR") { + + m_serverMode = QSDR::ChirpWSPR; + setSpectrumSize(this, 4096); + } + else if (str == "chirpWSPRFile") { + + m_serverMode = QSDR::ChirpWSPRFile; + setSpectrumSize(this, 4096); + } + else { + + m_serverMode = QSDR::SDRMode; + setSpectrumSize(this, 4096); + } + + +// value = settings->value("server/mouseWheelFreqStep", 1000).toInt(); +// if ((value != 1) & (value != 10) & (value != 100) & (value != 1000) & (value != 10000) & (value != 100000) & +// (value != 5) & (value != 50) & (value != 500) & (value != 5000) & (value != 50000) & (value != 500000)) +// value = 100; +// m_mouseWheelFreqStep = (double)value; + + //****************************************************************** + // Alexiares data settings + // m_alexConfig (qint16): + // + // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + // | | | | | | | | | | | | | | | + // | | | | | | | | | | | | | | +-----Alex - manual HPF/LPF filter select (0 = disable, 1 = enable) + // | | | | | | | | | | | | | +------ Alex - Bypass all HPFs (0 = disable, 1 = enable)* + // | | | | | | | | | | | | +-------- Alex - 6M low noise amplifier (0 = disable, 1 = enable)* + // | | | | | | | | | | | +---------- Alex - select 1.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | | +------------ Alex - select 6.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | +-------------- Alex - select 9.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | +---------------- Alex - select 13MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | +------------------ Alex - select 20MHz HPF (0 = disable, 1 = enable)* + // | | | | | | +-------------------- Alex - select 160m LPF (0 = disable, 1 = enable)* + // | | | | | +---------------------- Alex - select 80m LPF (0 = disable, 1 = enable)* + // | | | | +------------------------ Alex - select 60/40m LPF (0 = disable, 1 = enable)* + // | | | +-------------------------- Alex - select 30/20m LPF (0 = disable, 1 = enable)* + // | | +---------------------------- Alex - select 17/15m LPF (0 = disable, 1 = enable)* + // | +------------------------------ Alex - select 12/10m LPF (0 = disable, 1 = enable)* + // +-------------------------------- Alex - select 6m LPF (0 = disable, 1 = enable)* + + m_alexConfig = 0; + double fLo; + double fHi; + + str = settings->value("alex/manual", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x01; + + str = settings->value("alex/bypassAll", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x02; + + str = settings->value("alex/amp6m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x04; + + fLo = settings->value("alex/amp6mLo", 50000000).toDouble(); + if ((fLo < 49000000) || (fLo > 52500000)) fLo = 50000000; + + fHi = settings->value("alex/amp6mHi", 54000000).toDouble(); + if ((fHi < 52500000) || (fHi > 55000000)) fHi = 54000000; + + m_HPFLoFrequencyList[5] = (long)fLo; + m_HPFHiFrequencyList[5] = (long)fHi; + + + str = settings->value("alex/hpf1_5MHz", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x08; + + fLo = settings->value("alex/hpf1_5MHzLo", 1500000).toDouble(); + if ((fLo < 0) || (fLo > 2000000)) fLo = 1500000; + + fHi = settings->value("alex/hpf1_5MHzHi", 5500000).toDouble(); + if ((fHi < 1600000) || (fHi > 6000000)) fHi = 5500000; + + m_HPFLoFrequencyList[0] = (long)fLo; + m_HPFHiFrequencyList[0] = (long)fHi; + + + str = settings->value("alex/hpf6_5MHz", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x10; + + fLo = settings->value("alex/hpf6_5MHzLo", 7000000).toDouble(); + if ((fLo < 6000000) || (fLo > 8000000)) fLo = 7000000; + + fHi = settings->value("alex/hpf6_5MHzHi", 7300000).toDouble(); + if ((fHi < 7000000) || (fHi > 9500000)) fHi = 7300000; + + m_HPFLoFrequencyList[1] = (long)fLo; + m_HPFHiFrequencyList[1] = (long)fHi; + + + str = settings->value("alex/hpf9_5MHz", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x20; + + fLo = settings->value("alex/hpf9_5MHzLo", 10100000).toDouble(); + if ((fLo < 9000000) || (fLo > 11000000)) fLo = 10100000; + + fHi = settings->value("alex/hpf9_5MHzHi", 10150000).toDouble(); + if ((fHi < 10000000) || (fHi > 13000000)) fHi = 10150000; + + m_HPFLoFrequencyList[2] = (long)fLo; + m_HPFHiFrequencyList[2] = (long)fHi; + + + str = settings->value("alex/hpf13MHz", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x40; + + fLo = settings->value("alex/hpf13MHzLo", 14000000).toDouble(); + if ((fLo < 12000000) || (fLo > 15000000)) fLo = 14000000; + + fHi = settings->value("alex/hpf13MHzHi", 18168000).toDouble(); + if ((fHi < 13700000) || (fHi > 19000000)) fHi = 18168000; + + m_HPFLoFrequencyList[3] = (long)fLo; + m_HPFHiFrequencyList[3] = (long)fHi; + + + str = settings->value("alex/hpf20MHz", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x80; + + fLo = settings->value("alex/hpf20MHzLo", 21000000).toDouble(); + if ((fLo < 18000000) || (fLo > 25000000)) fLo = 21000000; + + fHi = settings->value("alex/hpf20MHzHi", 29700000).toDouble(); + if ((fHi < 25000000) || (fHi > 32000000)) fHi = 29700000; + + m_HPFLoFrequencyList[4] = (long)fLo; + m_HPFHiFrequencyList[4] = (long)fHi; + + + str = settings->value("alex/lpf160m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x100; + + fLo = settings->value("alex/lpf160mLo", 1800000).toDouble(); + if ((fLo < 0) || (fLo > 1900000)) fLo = 1800000; + + fHi = settings->value("alex/lpf160mHi", 2000000).toDouble(); + if ((fHi < 1000000) || (fHi > 3000000)) fHi = 2000000; + + m_LPFLoFrequencyList[0] = (long)fLo; + m_LPFHiFrequencyList[0] = (long)fHi; + + + str = settings->value("alex/lpf80m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x200; + + fLo = settings->value("alex/lpf80mLo", 3500000).toDouble(); + if ((fLo < 2000000) || (fLo > 4000000)) fLo = 3500000; + + fHi = settings->value("alex/lpf80mHi", 4000000).toDouble(); + if ((fHi < 2000000) || (fHi > 5000000)) fHi = 4000000; + + m_LPFLoFrequencyList[1] = (long)fLo; + m_LPFHiFrequencyList[1] = (long)fHi; + + + str = settings->value("alex/lpf60_40m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x400; + + fLo = settings->value("alex/lpf60_40mLo", 5330000).toDouble(); + if ((fLo < 5000000) || (fLo > 11000000)) fLo = 5330000; + + fHi = settings->value("alex/lpf60_40mHi", 7300000).toDouble(); + if ((fHi < 5000000) || (fHi > 8000000)) fHi = 7300000; + + m_LPFLoFrequencyList[2] = (long)fLo; + m_LPFHiFrequencyList[2] = (long)fHi; + + + str = settings->value("alex/lpf30_20m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x800; + + fLo = settings->value("alex/lpf30_20mLo", 10100000).toDouble(); + if ((fLo < 9000000) || (fLo > 15000000)) fLo = 10100000; + + fHi = settings->value("alex/lpf30_20mHi", 14350000).toDouble(); + if ((fHi < 9000000) || (fHi > 15000000)) fHi = 14350000; + + m_LPFLoFrequencyList[3] = (long)fLo; + m_LPFHiFrequencyList[3] = (long)fHi; + + + str = settings->value("alex/lpf17_15m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x1000; + + fLo = settings->value("alex/lpf17_15mLo", 18068000).toDouble(); + if ((fLo < 17000000) || (fLo > 22000000)) fLo = 18068000; + + fHi = settings->value("alex/lpf17_15mHi", 21450000).toDouble(); + if ((fHi < 17000000) || (fHi > 22000000)) fHi = 21450000; + + m_LPFLoFrequencyList[4] = (long)fLo; + m_LPFHiFrequencyList[4] = (long)fHi; + + + str = settings->value("alex/lpf12_10m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x2000; + + fLo = settings->value("alex/lpf12_10mLo", 24890000).toDouble(); + if ((fLo < 23000000) || (fLo > 30000000)) fLo = 24890000; + + fHi = settings->value("alex/lpf12_10mHi", 29700000).toDouble(); + if ((fHi < 23000000) || (fHi > 30000000)) fHi = 29700000; + + m_LPFLoFrequencyList[5] = (long)fLo; + m_LPFHiFrequencyList[5] = (long)fHi; + + + str = settings->value("alex/lpf6m", "off").toString(); + if (str.toLower() == "on") + m_alexConfig |= 0x4000; + + fLo = settings->value("alex/lpf6mLo", 50000000).toDouble(); + if ((fLo < 30000000) || (fLo > 52000000)) fLo = 50000000; + + fHi = settings->value("alex/lpf6mHi", 54000000).toDouble(); + if ((fHi < 52000000) || (fHi > 66000000)) fHi = 54000000; + + m_LPFLoFrequencyList[6] = (long)fLo; + m_LPFHiFrequencyList[6] = (long)fHi; + + + SETTINGS_DEBUG << "Alex config: " << m_alexConfig; + + if (m_alexStates.length() == MAX_BANDS && m_bandList.length() == MAX_BANDS) { + + for (int i = 0; i < MAX_BANDS; i++) { + + str = "alex/state"; + str.append(m_bandList.at(i).bandString); + + value = settings->value(str, 33).toInt(); + setAlexState(this, i, value); + } + } + + //****************************************************************** + // Penny open collector settings + + str = settings->value("penny/OCenabled", "off").toString(); + if (str.toLower() == "on") + m_pennyOCEnabled = true; + else + m_pennyOCEnabled = false; + + if (m_rxJ6pinList.length() == MAX_BANDS-1 && m_txJ6pinList.length() == MAX_BANDS-1 && m_bandList.length() == MAX_BANDS) { + + for (int i = 0; i < MAX_BANDS-1; i++) { + + str = "penny/rxState"; + str.append(m_bandList.at(i).bandString); + + value = settings->value(str, 0).toInt(); + if (value < 0 || value > 255) value = 0; + setRxJ6Pin(this, (HamBand) i, value); + } + + for (int i = 0; i < MAX_BANDS-1; i++) { + + str = "penny/txState"; + str.append(m_bandList.at(i).bandString); + + value = settings->value(str, 0).toInt(); + if (value < 0 || value > 255) value = 0; + setTxJ6Pin(this, (HamBand) i, value); + } + } + else { + + qWarning() << "rxJ6pinList or txJ6pinList or bandList have wrong length!"; + } + + //****************************************************************** + // wideband settings + + str = settings->value("wideband/widebandData", "on").toString(); + if (str.toLower() == "on") + m_widebandOptions.wideBandData = true; + else if (str.toLower() == "off") + m_widebandOptions.wideBandData = false; + else + m_widebandOptions.wideBandData = true; + + str = settings->value("wideband/widebandDisplay", "off").toString(); + if (str.toLower() == "on") + m_widebandOptions.wideBandDisplayStatus = true; + else if (str.toLower() == "off") + m_widebandOptions.wideBandDisplayStatus = false; + else + m_widebandOptions.wideBandDisplayStatus = false; + + if (!m_widebandOptions.wideBandData) m_widebandOptions.wideBandDisplayStatus = false; + + str = settings->value("wideband/averaging", "on").toString(); + if (str.toLower() == "on") + m_widebandOptions.averaging = true; + else if (str.toLower() == "off") + m_widebandOptions.averaging = false; + else + m_widebandOptions.averaging = true; + + value = settings->value("wideband/averagingCnt", 5).toInt(); + if ((value < 1) || (value > 100)) value = 5; + m_widebandOptions.averagingCnt = value; + + value = settings->value("wideband/dBmWideBandScaleMin", -140).toInt(); + if ((value < -200) || (value > 0)) value = -140; + m_widebandOptions.dBmWBScaleMin = (qreal)(1.0 * value); + + value = settings->value("wideband/dBmWideBandScaleMax", -10).toInt(); + if ((value < -100) || (value > 0)) value = -10; + m_widebandOptions.dBmWBScaleMax = (qreal)(1.0 * value); + + str = settings->value("wideband/panMode", "LINE").toString(); + if (str == "LINE") + m_widebandOptions.panMode = Line; + else if (str == "FILLEDLINE") + m_widebandOptions.panMode = FilledLine; + else if (str == "SOLID") + m_widebandOptions.panMode = Solid; + + //****************************************************************** + // receiver data settings + + for (int i = 0; i < MAX_RECEIVERS; i++) { + + QString cstr = m_rxStringList.at(i); + cstr.append("/dspCore"); + + str = settings->value(cstr, "qtdsp").toString(); + if (str == "qtdsp") { + + m_receiverDataList[i].dspCore = QSDR::QtDSP; + setSpectrumSize(this, 4096); + //SETTINGS_DEBUG << "DSP core for rx " << i << " is QtDSP."; + } + + cstr = m_rxStringList.at(i); + cstr.append("/freqRulerPosition"); + + value = settings->value(cstr, 5).toInt(); + if (value < 0) value = 0; + if (value > 10) value = 10; + m_receiverDataList[i].freqRulerPosition = value/10.0f; + + cstr = m_rxStringList.at(i); + cstr.append("/audioVolume"); + + value = settings->value(cstr, 10).toInt(); + if (value < 0) value = 0; + if (value > 100) value = 100; + m_receiverDataList[i].audioVolume = value/100.0f; + + cstr = m_rxStringList.at(i); + cstr.append("/mouseWheelFreqStep"); + + value = settings->value(cstr, 100).toInt(); + if ((value != 1) & (value != 10) & (value != 100) & (value != 1000) & (value != 10000) & (value != 100000) & + (value != 5) & (value != 50) & (value != 500) & (value != 5000) & (value != 50000) & (value != 500000)) + value = 100; + m_receiverDataList[i].mouseWheelFreqStep = (qreal)value; + + cstr = m_rxStringList.at(i); + cstr.append("/agcGain"); + + value = settings->value(cstr, 100).toInt(); + if (value < -20) value = -20; + if (value > 120) value = 120; + m_receiverDataList[i].acgGain = value; + + cstr = m_rxStringList.at(i); + cstr.append("/agcFixedGain"); + + value = settings->value(cstr, 30).toInt(); + if (value < -20) value = -20; + if (value > 50) value = 50; + m_receiverDataList[i].agcFixedGain_dB = value; + + cstr = m_rxStringList.at(i); + cstr.append("/agcMaximumGain"); + + value = settings->value(cstr, 30).toInt(); + if (value < -20) value = -20; + if (value > 150) value = 150; + m_receiverDataList[i].agcMaximumGain_dB = value - 0; + + cstr = m_rxStringList.at(i); + cstr.append("/agcSlope"); + + value = settings->value(cstr, 0).toInt(); + if (value < 0) value = 0; + if (value > 20) value = 20; + m_receiverDataList[i].agcVariableGain = (qreal)value; + + cstr = m_rxStringList.at(i); + cstr.append("/agcAttacktime"); + + value = settings->value(cstr, 1).toInt(); + if (value < 1) value = 1; + if (value > 10) value = 10; + m_receiverDataList[i].agcAttackTime = value/1000.0; + + cstr = m_rxStringList.at(i); + cstr.append("/agcDecaytime"); + + value = settings->value(cstr, 250).toInt(); + if (value < 10) value = 10; + if (value > 5000) value = 5000; + m_receiverDataList[i].agcDecayTime = value/1000.0; + + cstr = m_rxStringList.at(i); + cstr.append("/agcHangtime"); + + value = settings->value(cstr, 100).toInt(); + if (value < 10) value = 10; + if (value > 5000) value = 5000; + m_receiverDataList[i].agcHangTime = value/1000.0; + + cstr = m_rxStringList.at(i); + cstr.append("/agcLines"); + + str = settings->value(cstr, "on").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].agcLines = true; + else + m_receiverDataList[i].agcLines = false; + + cstr = m_rxStringList.at(i); + cstr.append("/agcMode"); + + str = settings->value(cstr, "MED").toString(); + if (str == "LONG") + m_receiverDataList[i].agcMode = agcLONG; + else if (str == "SLOW") + m_receiverDataList[i].agcMode = agcSLOW; + else if (str == "MED") + m_receiverDataList[i].agcMode = agcMED; + else if (str == "FAST") + m_receiverDataList[i].agcMode = agcFAST; + else + m_receiverDataList[i].agcMode = agcOFF; + + if (str == "MED" || str == "FAST") + m_receiverDataList[i].hangEnabled = false; + else + m_receiverDataList[i].hangEnabled = true; + + cstr = m_rxStringList.at(i); + cstr.append("/panMode"); + + str = settings->value(cstr, "LINE").toString(); + if (str == "LINE") + m_receiverDataList[i].panMode = Line; + else if (str == "FILLEDLINE") + m_receiverDataList[i].panMode = FilledLine; + else if (str == "SOLID") + m_receiverDataList[i].panMode = Solid; + + cstr = m_rxStringList.at(i); + cstr.append("/waterfallMode"); + + str = settings->value(cstr, "ENHANCED").toString(); + if (str == "SIMPLE") + m_receiverDataList[i].waterfallMode = Simple; + else if (str == "ENHANCED") + m_receiverDataList[i].waterfallMode = Enhanced; + + cstr = m_rxStringList.at(i); + cstr.append("/framesPerSecond"); + value = settings->value(cstr, 25).toInt(); + if (value < 0 || value > 200) value = 25; + m_receiverDataList[i].framesPerSecond = value; + + cstr = m_rxStringList.at(i); + cstr.append("/waterfallOffsetLo"); + value = settings->value(cstr, -5).toInt(); + if ((value < -50) || (value > 50)) value = -5; + m_receiverDataList[i].waterfallOffsetLo = value; + + cstr = m_rxStringList.at(i); + cstr.append("/waterfallOffsetHi"); + value = settings->value(cstr, 20).toInt(); + if ((value < -50) || (value > 50)) value = 20; + m_receiverDataList[i].waterfallOffsetHi = value; + + cstr = m_rxStringList.at(i); + cstr.append("/filterHi"); + value = settings->value(cstr, -150).toInt(); + if (value < -20000 || value > 20000) value = -150; + m_receiverDataList[i].filterHi = (qreal)(1.0f * value); + + cstr = m_rxStringList.at(i); + cstr.append("/filterLo"); + value = settings->value(cstr, -3050).toInt(); + if (value < -20000 || value > 20000) value = -3050; + m_receiverDataList[i].filterLo = (qreal)(1.0f * value); + + cstr = m_rxStringList.at(i); + cstr.append("/averaging"); + str = settings->value(cstr, "on").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].spectrumAveraging = true; + else + m_receiverDataList[i].spectrumAveraging = false; + + cstr = m_rxStringList.at(i); + cstr.append("/averagingCnt"); + value = settings->value(cstr, 5).toInt(); + if ((value < 1) || (value > 100)) value = 5; + m_receiverDataList[i].averagingCnt = value; + + cstr = m_rxStringList.at(i); + cstr.append("/grid"); + str = settings->value(cstr, "on").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].panGrid = true; + else + m_receiverDataList[i].panGrid = false; + + cstr = m_rxStringList.at(i); + cstr.append("/hairCross"); + str = settings->value(cstr, "off").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].hairCross = true; + else + m_receiverDataList[i].hairCross = false; + + cstr = m_rxStringList.at(i); + cstr.append("/panLocked"); + str = settings->value(cstr, "off").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].panLocked = true; + else + m_receiverDataList[i].panLocked = false; + + cstr = m_rxStringList.at(i); + cstr.append("/clickVFO"); + str = settings->value(cstr, "off").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].clickVFO = true; + else + m_receiverDataList[i].clickVFO = false; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency2200m"); + value = settings->value(cstr, 135700).toDouble(); + if ((value < 135700) || (value > 137800)) value = 135700; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency2200m"); + value = settings->value(cstr, 135700).toDouble(); + if ((value < 135700) || (value > 137800)) value = 135700; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency630m"); + value = settings->value(cstr, 472000).toDouble(); + if ((value < 472000) || (value > 479000)) value = 472000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency630m"); + value = settings->value(cstr, 472000).toDouble(); + if ((value < 472000) || (value > 479000)) value = 472000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency160m"); + value = settings->value(cstr, 1810000).toDouble(); + if ((value < 1810000) || (value > 2000000)) value = 1810000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency160m"); + value = settings->value(cstr, 1800000).toDouble(); + if ((value < 1810000) || (value > 2000000)) value = 1810000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency80m"); + value = settings->value(cstr, 3500000).toDouble(); + if ((value < 3500000) || (value > 3800000)) value = 3500000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency80m"); + value = settings->value(cstr, 3500000).toDouble(); + if ((value < 3500000) || (value > 3800000)) value = 3500000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency60m"); + value = settings->value(cstr, 5260000).toDouble(); + if ((value < 5260000) || (value > 5410000)) value = 5260000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency60m"); + value = settings->value(cstr, 5260000).toDouble(); + if ((value < 5260000) || (value > 5410000)) value = 5260000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency40m"); + value = settings->value(cstr, 7000000).toDouble(); + if ((value < 7000000) || (value > 7200000)) value = 7000000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency40m"); + value = settings->value(cstr, 7000000).toDouble(); + if ((value < 7000000) || (value > 7200000)) value = 7000000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency30m"); + value = settings->value(cstr, 10100000).toDouble(); + if ((value < 10100000) || (value > 10150000)) value = 10100000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency30m"); + value = settings->value(cstr, 10100000).toDouble(); + if ((value < 10100000) || (value > 10150000)) value = 10100000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency20m"); + value = settings->value(cstr, 14000000).toDouble(); + if ((value < 14000000) || (value > 14350000)) value = 14000000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency20m"); + value = settings->value(cstr, 14000000).toDouble(); + if ((value < 14000000) || (value > 14350000)) value = 14000000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency17m"); + value = settings->value(cstr, 18068000).toDouble(); + if ((value < 18068000) || (value > 18168000)) value = 18068000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency17m"); + value = settings->value(cstr, 18068000).toDouble(); + if ((value < 18068000) || (value > 18168000)) value = 18068000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency15m"); + value = settings->value(cstr, 21000000).toDouble(); + if ((value < 21000000) || (value > 21450000)) value = 21000000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency15m"); + value = settings->value(cstr, 21000000).toDouble(); + if ((value < 21000000) || (value > 21450000)) value = 21000000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency12m"); + value = settings->value(cstr, 24890000).toDouble(); + if ((value < 24890000) || (value > 24990000)) value = 24890000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency12m"); + value = settings->value(cstr, 24890000).toDouble(); + if ((value < 24890000) || (value > 24990000)) value = 24890000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency10m"); + value = settings->value(cstr, 28000000).toDouble(); + if ((value < 28000000) || (value > 29700000)) value = 28000000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency10m"); + value = settings->value(cstr, 28000000).toDouble(); + if ((value < 28000000) || (value > 29700000)) value = 28000000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequency6m"); + value = settings->value(cstr, 50000000).toDouble(); + if ((value < 50000000) || (value > 54000000)) value = 50000000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequency6m"); + value = settings->value(cstr, 50000000).toDouble(); + if ((value < 50000000) || (value > 54000000)) value = 50000000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastCenterFrequencyGen"); + value = settings->value(cstr, 1800000).toDouble(); + if ((value < 0) || (value > 50000000)) value = 3500000; + m_receiverDataList[i].lastCenterFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/lastVfoFrequencyGen"); + value = settings->value(cstr, 1800000).toDouble(); + if ((value < 0) || (value > MAXFREQUENCY)) value = 1800000; + m_receiverDataList[i].lastVfoFrequencyList << value; + + cstr = m_rxStringList.at(i); + cstr.append("/centerFrequency"); + value = settings->value(cstr, 3672000).toDouble(); + if ((value < 0) || (value > MAXFREQUENCY)) value = 1800000; + m_receiverDataList[i].ctrFrequency = value; + + setCtrFrequency(i, value); + + cstr = m_rxStringList.at(i); + cstr.append("/vfoFrequency"); + value = settings->value(cstr, 3672000).toDouble(); + if ((value < 0) || (value > 50000000)) value = 3600000; + m_receiverDataList[i].vfoFrequency = value; + + setVfoFrequency(i, value); + + + if (m_receiverDataList[i].dspModeList.length() == MAX_BANDS && m_bandList.length() == MAX_BANDS) { + + for (int j = 0; j < MAX_BANDS; j++) { + + cstr = m_rxStringList.at(i); + cstr.append("/dspMode"); + cstr.append(m_bandList.at(j).bandString); + + str = settings->value(cstr, "").toString(); + + if (str == "USB") + m_receiverDataList[i].dspModeList[j] = USB; + else if (str == "DSB") + m_receiverDataList[i].dspModeList[j] = DSB; + else if (str == "CWL") + m_receiverDataList[i].dspModeList[j] = CWL; + else if (str == "CWU") + m_receiverDataList[i].dspModeList[j] = CWU; + else if (str == "FMN") + m_receiverDataList[i].dspModeList[j] = FMN; + else if (str == "AM") + m_receiverDataList[i].dspModeList[j] = AM; + else if (str == "DIGU") + m_receiverDataList[i].dspModeList[j] = DIGU; + else if (str == "SPEC") + m_receiverDataList[i].dspModeList[j] = SPEC; + else if (str == "DIGL") + m_receiverDataList[i].dspModeList[j] = DIGL; + else if (str == "SAM") + m_receiverDataList[i].dspModeList[j] = SAM; + else if (str == "DRM") + m_receiverDataList[i].dspModeList[j] = DRM; + else + m_receiverDataList[i].dspModeList[j] = LSB; + + //SETTINGS_DEBUG << cstr << ": " << getDSPModeString(m_receiverDataList[i].dspModeList[j]); + } + } + + if (m_receiverDataList[i].mercuryAttenuators.length() == MAX_BANDS && m_bandList.length() == MAX_BANDS) { + + for (int j = 0; j < MAX_BANDS; j++) { + + cstr = m_rxStringList.at(i); + cstr.append("/attenuator"); + cstr.append(m_bandList.at(j).bandString); + + str = settings->value(cstr, "off").toString(); + if (str.toLower() == "on") + m_receiverDataList[i].mercuryAttenuators[j] = 0; // which is 'Preamp' off + else + m_receiverDataList[i].mercuryAttenuators[j] = 1; // which is 'Preamp' on + } + } + + int valueMin, valueMax; + if (m_receiverDataList[i].dBmPanScaleMinList.length() == MAX_BANDS && + m_receiverDataList[i].dBmPanScaleMaxList.length() == MAX_BANDS && + m_bandList.length() == MAX_BANDS + ) { + for (int j = 0; j < MAX_BANDS; j++) { + + cstr = m_rxStringList.at(i); + cstr.append("/dBmPanScaleMin"); + cstr.append(m_bandList.at(j).bandString); + + valueMin = settings->value(cstr, -120).toInt(); + if ((valueMin < -200) || (valueMin > 0)) valueMin = -120; + + cstr = m_rxStringList.at(i); + cstr.append("/dBmPanScaleMax"); + cstr.append(m_bandList.at(j).bandString); + + valueMax = settings->value(cstr, -10).toInt(); + if ((valueMax < -200) || (valueMax > 0)) valueMax = -10; + + if (valueMax <= valueMin) { + + valueMin = -120; + valueMax = -10; + } + + m_receiverDataList[i].dBmPanScaleMinList[j] = (qreal)(1.0 * valueMin); + m_receiverDataList[i].dBmPanScaleMaxList[j] = (qreal)(1.0 * valueMax); + } + } + } + + //****************************************************************** + // Chirp WSPR settings + value = settings->value("ChirpWSPR/lowerChirpFrequency", 500).toInt(); + if (value < 1 || value > 10000) value = 500; + m_lowerChirpFreq = value; + + value = settings->value("ChirpWSPR/upperChirpFrequency", 2500).toInt(); + if (value < 2 || value < m_lowerChirpFreq + 1 || value > 50000) value = 2500; + m_upperChirpFreq = value; + + value = settings->value("ChirpWSPR/chirpAmplitude", 75).toInt(); + if (value < 0 || value > 100) return -1; + m_chirpAmplitude = qreal(value / 100.0); + + value = settings->value("ChirpWSPR/chirpSamplingFrequency", 48000).toInt(); + if ((value != 8000) & (value != 48000) & (value != 96000)) value = 48000; + m_chirpSamplingFreq = value; + + value = settings->value("ChirpWSPR/chirpBufferDurationUs", 10000000).toInt(); + if (value < 0 || value > 100000000) value = 10000000; + m_chirpBufferDurationUs = (qint64)value; + + value = settings->value("ChirpWSPR/chirpChannels", 1).toInt(); + if ((value != 1) & (value != 2)) value = 1; + m_chirpChannels = value; + + value = settings->value("ChirpWSPR/chirpBufferLength", 4096).toInt(); + if ((value != 4096) & (value != 16384)) value = 4096; + m_chirpBufferLength = (qint64)value; + + value = settings->value("ChirpWSPR/chirpFilterLowerFrequency", 500).toInt(); + if (value < 10000 || value > 10000) value = 500; + m_chirpFilterLowerFrequency = value; + + value = settings->value("ChirpWSPR/chirpFilterUpperFrequency", 2500).toInt(); + if (value < 10000 || value > 10000) value = 2500; + m_chirpFilterUpperFrequency = value; + + //****************************************************************** + // graphics settings + + value = settings->value("graphics/dBmDistScaleMin", -20).toInt(); + if ((value < -200) || (value > 0)) value = -20; + m_dBmDistScaleMin = (qreal)(1.0 * value); + + value = settings->value("graphics/dBmDistScaleMax", 100).toInt(); + if ((value < -100) || (value > 200)) value = 100; + m_dBmDistScaleMax = (qreal)(1.0 * value); + + value = settings->value("graphics/sMeterHoldTime", 2000).toInt(); + if ((value < 0) || (value > 10000)) value = 2000; + m_sMeterHoldTime = value; + + + //****************************************************************** + // color settings + QColor color; + + color = settings->value("colors/panBackground", QColor(102, 69, 8)).value(); + if (!color.isValid()) color = QColor(102, 69, 8); + m_panadapterColors.panBackgroundColor = color; + + color = settings->value("colors/waterfall", QColor(246, 146, 6)).value(); + if (!color.isValid()) color = QColor(246, 146, 6); + m_panadapterColors.waterfallColor = color; + + color = settings->value("colors/panLine", QColor(246, 164, 76)).value(); + if (!color.isValid()) color = QColor(246, 164, 76); + m_panadapterColors.panLineColor = color; + + color = settings->value("colors/panLineFilled", QColor(246, 159, 7)).value(); + if (!color.isValid()) color = QColor(246, 159, 7); + m_panadapterColors.panLineFilledColor = color; + + color = settings->value("colors/panSolidTop", QColor(230, 246, 204)).value(); + if (!color.isValid()) color = QColor(230, 246, 204); + m_panadapterColors.panSolidTopColor = color; + + color = settings->value("colors/panSolidBottom", QColor(102, 96, 8)).value(); + if (!color.isValid()) color = QColor(102, 96, 8); + m_panadapterColors.panSolidBottomColor = color; + + color = settings->value("colors/panWideBandLine", QColor(73, 111, 7)).value(); + if (!color.isValid()) color = QColor(73, 111, 7); + m_panadapterColors.wideBandLineColor = color; + + color = settings->value("colors/panWideBandFilled", QColor(137, 172, 62)).value(); + if (!color.isValid()) color = QColor(137, 172, 62); + m_panadapterColors.wideBandFilledColor = color; + + color = settings->value("colors/panWideBandSolidTop", QColor(236, 38, 16)).value(); + if (!color.isValid()) color = QColor(236, 38, 16); + m_panadapterColors.wideBandSolidTopColor = color; + + color = settings->value("colors/panWideBandSolidBottom", QColor(232, 134, 29)).value(); + if (!color.isValid()) color = QColor(232, 134, 29); + m_panadapterColors.wideBandSolidBottomColor = color; + + color = settings->value("colors/distanceLine", QColor(246, 27, 45)).value(); + if (!color.isValid()) color = QColor(246, 27, 45); + m_panadapterColors.distanceLineColor = color; + + color = settings->value("colors/distanceLineFilled", QColor(232, 29, 86)).value(); + if (!color.isValid()) color = QColor(232, 29, 86); + m_panadapterColors.distanceLineFilledColor = color; + + color = settings->value("colors/panCenterLine", QColor(246, 7, 19)).value(); + if (!color.isValid()) color = QColor(246, 7, 19); + m_panadapterColors.panCenterLineColor = color; + + color = settings->value("colors/gridLine", QColor(7, 96, 96)).value(); + if (!color.isValid()) color = QColor(7, 96, 96); + m_panadapterColors.gridLineColor = color; + + SETTINGS_DEBUG << "reading done."; + + return 0; +} + +int Settings::saveSettings() { + + QString str; + //QList bandList = HamBandStrings(); + + settings->setValue(getTitleStr(), getVersionStr()); + settings->setValue("saved", QDateTime::currentDateTime().toString("dddd dd MMMM yyyy hh:mm:ss"));// << " local time\n\n"); + settings->setValue("user/callSign", m_callsignString); + + // window settings + settings->setValue("window/minimumWidgetWidth", m_minimumWidgetWidth); + settings->setValue("window/minimumGroupBoxWidth", m_minimumGroupBoxWidth); + settings->setValue("window/multiRxView", m_multiRxView); + + // network settings + settings->setValue("network/server_ipAddress", m_serverAddress); + settings->setValue("network/hpsdr_local_ipAddress", m_hpsdrDeviceLocalAddr); + settings->setValue("network/server_port", m_serverPort); + settings->setValue("network/listen_port", m_listenerPort); + settings->setValue("network/audio_port", m_audioPort); + settings->setValue("network/metis_port", m_metisPort); + settings->setValue("network/socketBufferSize", m_socketBufferSize); + + + // HPSDR hardware + settings->setValue("hpsdr/hardware", m_hpsdrHardware); + + switch (m_hpsdrHardware) { + + // Mercury/Penelope, PennyLane + case 0: + + if (m_devices.mercuryPresence) + settings->setValue("hpsdr/mercury", "true"); + else + settings->setValue("hpsdr/mercury", "false"); + + if (m_devices.penelopePresence) + settings->setValue("hpsdr/penelope", "true"); + else + settings->setValue("hpsdr/penelope", "false"); + + if (m_devices.pennylanePresence) + settings->setValue("hpsdr/pennylane", "true"); + else + settings->setValue("hpsdr/pennylane", "false"); + + if (m_devices.excaliburPresence) + settings->setValue("hpsdr/excalibur", "true"); + else + settings->setValue("hpsdr/excalibur", "false"); + break; + + // Hermes + case 1: + + if (m_devices.mercuryPresence) + settings->setValue("hpsdr/mercury", "true"); + else + settings->setValue("hpsdr/mercury", "false"); + + if (m_devices.penelopePresence) + settings->setValue("hpsdr/penelope", "true"); + else + settings->setValue("hpsdr/penelope", "false"); + + if (m_devices.pennylanePresence) + settings->setValue("hpsdr/pennylane", "true"); + else + settings->setValue("hpsdr/pennylane", "false"); + + if (m_devices.excaliburPresence) + settings->setValue("hpsdr/excalibur", "true"); + else + settings->setValue("hpsdr/excalibur", "false"); + break; + + // Cyclops + case 2: + break; + } + + if (m_devices.alexPresence) + settings->setValue("hpsdr/alex", "true"); + else + settings->setValue("hpsdr/alex", "false"); + + +// if (m_devices.hermesPresence) +// settings->setValue("hpsdr/hermes", "true"); +// else +// settings->setValue("hpsdr/hermes", "false"); + + switch (m_hpsdrHardware) { + + // Mercury/Penelope + case 0: + + if (m_hwInterface == QSDR::Metis) + settings->setValue("hpsdr/interface", "metis"); + else if (m_hwInterface == QSDR::NoInterfaceMode) + settings->setValue("hpsdr/interface", "noInterface"); + break; + + // Hermes + case 1: + + if (m_hwInterface == QSDR::Hermes) + settings->setValue("hpsdr/interface", "hermes"); + break; + + // Cyclops + case 2: + break; + } + + if (m_checkFirmwareVersions) + settings->setValue("hpsdr/checkfw", "true"); + else + settings->setValue("hpsdr/checkfw", "false"); + + + // server settings + settings->setValue("server/sample_rate", getSampleRate()); + + if (m_mercuryDither == 1) + settings->setValue("server/dither", "on"); + else + settings->setValue("server/dither", "off"); + + if (m_mercuryRandom == 1) + settings->setValue("server/random", "on"); + else + settings->setValue("server/random", "off"); + + if (m_10MHzSource == 0) + settings->setValue("server/10mhzsource", "atlas"); + else if (m_10MHzSource == 1) + settings->setValue("server/10mhzsource", "penelope"); + else if (m_10MHzSource == 2) + settings->setValue("server/10mhzsource", "mercury"); + else if (m_10MHzSource == 3) + settings->setValue("server/10mhzsource", "none"); + else + settings->setValue("server/10mhzsource", "mercury"); + + if (m_122_8MHzSource == 0) + settings->setValue("server/122_88mhzsource", "penelope"); + else if (m_122_8MHzSource == 1) + settings->setValue("server/122_88mhzsource", "mercury"); + + if (m_micSource == 0) + settings->setValue("server/mic_source", "janus"); + else if (m_micSource == 1) + settings->setValue("server/mic_source", "penelope"); + + settings->setValue("server/class", m_RxClass); + settings->setValue("server/timing", m_RxTiming); + //settings->setValue("server/mainVolume", (int)(m_mainVolume * 100)); + + //if (m_serverMode == QSDR::SDRMode) + settings->setValue("server/mode", "sdr"); + + //settings->setValue("server/mouseWheelFreqStep", m_mouseWheelFreqStep); + + //****************************************************************** + // Alexiares data settings + + // m_alexConfig (qint16) + // + // 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + // | | | | | | | | | | | | | | | + // | | | | | | | | | | | | | | +-----Alex - manual HPF/LPF filter select (0 = disable, 1 = enable) + // | | | | | | | | | | | | | +------ Alex - Bypass all HPFs (0 = disable, 1 = enable)* + // | | | | | | | | | | | | +-------- Alex - 6M low noise amplifier (0 = disable, 1 = enable)* + // | | | | | | | | | | | +---------- Alex - select 1.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | | +------------ Alex - select 6.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | | +-------------- Alex - select 9.5MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | | +---------------- Alex - select 13MHz HPF (0 = disable, 1 = enable)* + // | | | | | | | +------------------ Alex - select 20MHz HPF (0 = disable, 1 = enable)* + // | | | | | | +-------------------- Alex - select 160m LPF (0 = disable, 1 = enable)* + // | | | | | +---------------------- Alex - select 80m LPF (0 = disable, 1 = enable)* + // | | | | +------------------------ Alex - select 60/40m LPF (0 = disable, 1 = enable)* + // | | | +-------------------------- Alex - select 30/20m LPF (0 = disable, 1 = enable)* + // | | +---------------------------- Alex - select 17/15m LPF (0 = disable, 1 = enable)* + // | +------------------------------ Alex - select 12/10m LPF (0 = disable, 1 = enable)* + // +-------------------------------- Alex - select 6m LPF (0 = disable, 1 = enable)* + + if (m_alexConfig & 0x01) + settings->setValue("alex/manual", "on"); + else + settings->setValue("alex/manual", "off"); + + if (m_alexConfig & 0x02) + settings->setValue("alex/bypassAll", "on"); + else + settings->setValue("alex/bypassAll", "off"); + + if (m_alexConfig & 0x04) + settings->setValue("alex/amp6m", "on"); + else + settings->setValue("alex/amp6m", "off"); + + settings->setValue("alex/amp6mLo", (int)m_HPFLoFrequencyList.at(5)); + settings->setValue("alex/amp6mHi", (int)m_HPFHiFrequencyList.at(5)); + + if (m_alexConfig & 0x08) + settings->setValue("alex/hpf1_5MHz", "on"); + else + settings->setValue("alex/hpf1_5MHz", "off"); + + settings->setValue("alex/hpf1_5MHzLo", (int)m_HPFLoFrequencyList.at(0)); + settings->setValue("alex/hpf1_5MHzHi", (int)m_HPFHiFrequencyList.at(0)); + + if (m_alexConfig & 0x10) + settings->setValue("alex/hpf6_5MHz", "on"); + else + settings->setValue("alex/hpf6_5MHz", "off"); + + settings->setValue("alex/hpf6_5MHzLo", (int)m_HPFLoFrequencyList.at(1)); + settings->setValue("alex/hpf6_5MHzHi", (int)m_HPFHiFrequencyList.at(1)); + + if (m_alexConfig & 0x20) + settings->setValue("alex/hpf9_5MHz", "on"); + else + settings->setValue("alex/hpf9_5MHz", "off"); + + settings->setValue("alex/hpf9_5MHzLo", (int)m_HPFLoFrequencyList.at(2)); + settings->setValue("alex/hpf9_5MHzHi", (int)m_HPFHiFrequencyList.at(2)); + + if (m_alexConfig & 0x40) + settings->setValue("alex/hpf13MHz", "on"); + else + settings->setValue("alex/hpf13MHz", "off"); + + settings->setValue("alex/hpf13MHzLo", (int)m_HPFLoFrequencyList.at(3)); + settings->setValue("alex/hpf13MHzHi", (int)m_HPFHiFrequencyList.at(3)); + + if (m_alexConfig & 0x80) + settings->setValue("alex/hpf20MHz", "on"); + else + settings->setValue("alex/hpf20MHz", "off"); + + settings->setValue("alex/hpf20MHzLo", (int)m_HPFLoFrequencyList.at(4)); + settings->setValue("alex/hpf20MHzHi", (int)m_HPFHiFrequencyList.at(4)); + + if (m_alexConfig & 0x100) + settings->setValue("alex/lpf160m", "on"); + else + settings->setValue("alex/lpf160m", "off"); + + settings->setValue("alex/lpf160mLo", (int)m_LPFLoFrequencyList.at(0)); + settings->setValue("alex/lpf160mHi", (int)m_LPFHiFrequencyList.at(0)); + + if (m_alexConfig & 0x200) + settings->setValue("alex/lpf80m", "on"); + else + settings->setValue("alex/lpf80m", "off"); + + settings->setValue("alex/lpf80mLo", (int)m_LPFLoFrequencyList.at(1)); + settings->setValue("alex/lpf80mHi", (int)m_LPFHiFrequencyList.at(1)); + + if (m_alexConfig & 0x400) + settings->setValue("alex/lpf60_40m", "on"); + else + settings->setValue("alex/lpf60_40m", "off"); + + settings->setValue("alex/lpf60_40mLo", (int)m_LPFLoFrequencyList.at(2)); + settings->setValue("alex/lpf60_40mHi", (int)m_LPFHiFrequencyList.at(2)); + + if (m_alexConfig & 0x800) + settings->setValue("alex/lpf30_20m", "on"); + else + settings->setValue("alex/lpf30_20m", "off"); + + settings->setValue("alex/lpf30_20mLo", (int)m_LPFLoFrequencyList.at(3)); + settings->setValue("alex/lpf30_20mHi", (int)m_LPFHiFrequencyList.at(3)); + + if (m_alexConfig & 0x1000) + settings->setValue("alex/lpf17_15m", "on"); + else + settings->setValue("alex/lpf17_15m", "off"); + + settings->setValue("alex/lpf17_15mLo", (int)m_LPFLoFrequencyList.at(4)); + settings->setValue("alex/lpf17_15mHi", (int)m_LPFHiFrequencyList.at(4)); + + if (m_alexConfig & 0x2000) + settings->setValue("alex/lpf12_10m", "on"); + else + settings->setValue("alex/lpf12_10m", "off"); + + settings->setValue("alex/lpf12_10mLo", (int)m_LPFLoFrequencyList.at(5)); + settings->setValue("alex/lpf12_10mHi", (int)m_LPFHiFrequencyList.at(5)); + + if (m_alexConfig & 0x4000) + settings->setValue("alex/lpf6m", "on"); + else + settings->setValue("alex/lpf6m", "off"); + + settings->setValue("alex/lpf6mLo", (int)m_LPFLoFrequencyList.at(6)); + settings->setValue("alex/lpf6mHi", (int)m_LPFHiFrequencyList.at(6)); + + + //*********************************************************************** + for (int i = 0; i < MAX_BANDS; i++) { + + str = "alex/state"; + str.append(m_bandList.at(i).bandString); + + settings->setValue(str, m_alexStates.at(i)); + } + + if (m_alexStates.length() == MAX_BANDS && m_bandList.length() == MAX_BANDS) { + + for (int i = 0; i < MAX_BANDS-1; i++) { + + str = "alex/state"; + str.append(m_bandList.at(i).bandString); + + settings->setValue(str, m_alexStates.at(i)); + } + } + + + //****************************************************************** + // Penny open collector settings + + if (m_pennyOCEnabled) + settings->setValue("penny/OCenabled", "on"); + else + settings->setValue("penny/OCenabled", "off"); + + if (m_rxJ6pinList.length() == MAX_BANDS-1 && m_txJ6pinList.length() == MAX_BANDS-1 && m_bandList.length() == MAX_BANDS) { + + for (int i = 0; i < MAX_BANDS-1; i++) { + + str = "penny/rxState"; + str.append(m_bandList.at(i).bandString); + + settings->setValue(str, m_rxJ6pinList.at(i)); + } + + for (int i = 0; i < MAX_BANDS-1; i++) { + + str = "penny/txState"; + str.append(m_bandList.at(i).bandString); + + settings->setValue(str, m_txJ6pinList.at(i)); + } + } + + //****************************************************************** + // wideband settings + + if (m_widebandOptions.wideBandData) + settings->setValue("wideband/widebandData", "on"); + else + settings->setValue("wideband/widebandData", "off"); + + if (!m_widebandOptions.wideBandData) m_widebandOptions.wideBandDisplayStatus = false; + + if (m_widebandOptions.wideBandDisplayStatus) + settings->setValue("wideband/widebandDisplay", "on"); + else + settings->setValue("wideband/widebandDisplay", "off"); + + if (m_widebandOptions.averaging) + settings->setValue("wideband/averaging", "on"); + else + settings->setValue("wideband/averaging", "off"); + + settings->setValue("wideband/averagingCnt", m_widebandOptions.averagingCnt); + settings->setValue("wideband/dBmWideBandScaleMin", (int)m_widebandOptions.dBmWBScaleMin); + settings->setValue("wideband/dBmWideBandScaleMax", (int)m_widebandOptions.dBmWBScaleMax); + + if (m_widebandOptions.panMode == Line) + settings->setValue("wideband/panMode", "LINE"); + else if (m_widebandOptions.panMode == FilledLine) + settings->setValue("wideband/panMode", "FILLEDLINE"); + else if (m_widebandOptions.panMode == Solid) + settings->setValue("wideband/panMode", "SOLID"); + + + //****************************************************************** + // receiver data settings + + for (int i = 0; i < MAX_RECEIVERS; i++) { + + QString str = m_rxStringList.at(i); + str.append("/dspCore"); + + if (m_receiverDataList[i].dspCore == QSDR::QtDSP) + settings->setValue(str, "qtdsp"); + //else + // settings->setValue(str, "dttsp"); + + str = m_rxStringList.at(i); + str.append("/freqRulerPosition"); + settings->setValue(str, (int)(m_receiverDataList[i].freqRulerPosition * 10)); + + str = m_rxStringList.at(i); + str.append("/audioVolume"); + settings->setValue(str, (int)(m_receiverDataList[i].audioVolume * 100)); + + str = m_rxStringList.at(i); + str.append("/mouseWheelFreqStep"); + settings->setValue(str, (int)(m_receiverDataList[i].mouseWheelFreqStep)); + + str = m_rxStringList.at(i); + str.append("/agcGain"); + settings->setValue(str, m_receiverDataList[i].acgGain); + + str = m_rxStringList.at(i); + str.append("/agcFixedGain"); + settings->setValue(str, (int) m_receiverDataList[i].agcFixedGain_dB); + + str = m_rxStringList.at(i); + str.append("/agcMaximumGain"); + settings->setValue(str, (int) m_receiverDataList[i].agcMaximumGain_dB); + + str = m_rxStringList.at(i); + str.append("/agcSlope"); + settings->setValue(str, (int)m_receiverDataList[i].agcVariableGain); + + str = m_rxStringList.at(i); + str.append("/agcAttacktime"); + settings->setValue(str, (int)(m_receiverDataList[i].agcAttackTime * 1000)); + + str = m_rxStringList.at(i); + str.append("/agcDecaytime"); + settings->setValue(str, (int)(m_receiverDataList[i].agcDecayTime * 1000)); + + str = m_rxStringList.at(i); + str.append("/agcHangTime"); + settings->setValue(str, (int)(m_receiverDataList[i].agcHangTime * 1000)); + + str = m_rxStringList.at(i); + str.append("/agcLines"); + + if (m_receiverDataList[i].agcLines) + settings->setValue(str, "on"); + else + settings->setValue(str, "off"); + +// str = m_rxStringList.at(i); +// str.append("/attenuator"); +// str.append(m_bandList.at(j).bandString); +// +// if (m_receiverDataList.at(i).mercuryAttenuators.at(j)) +// settings->setValue(str, "off"); +// else +// settings->setValue(str, "on"); + + str = m_rxStringList.at(i); + str.append("/agcMode"); + + if (m_receiverDataList[i].agcMode == agcOFF) + settings->setValue(str, "OFF"); + else if (m_receiverDataList[i].agcMode == agcLONG) + settings->setValue(str, "LONG"); + else if (m_receiverDataList[i].agcMode == agcSLOW) + settings->setValue(str, "SLOW"); + else if (m_receiverDataList[i].agcMode == agcMED) + settings->setValue(str, "MED"); + else if (m_receiverDataList[i].agcMode == agcFAST) + settings->setValue(str, "FAST"); + + str = m_rxStringList.at(i); + str.append("/panMode"); + + if (m_receiverDataList[i].panMode == Line) + settings->setValue(str, "LINE"); + else if (m_receiverDataList[i].panMode == FilledLine) + settings->setValue(str, "FILLEDLINE"); + else if (m_receiverDataList[i].panMode == Solid) + settings->setValue(str, "SOLID"); + + str = m_rxStringList.at(i); + str.append("/waterfallMode"); + + if (m_receiverDataList[i].waterfallMode == Simple) + settings->setValue(str, "SIMPLE"); + else if (m_receiverDataList[i].waterfallMode == Enhanced) + settings->setValue(str, "ENHANCED"); + + str = m_rxStringList.at(i); + str.append("/framesPerSecond"); + settings->setValue(str, m_receiverDataList[i].framesPerSecond); + + str = m_rxStringList.at(i); + str.append("/waterfallOffsetLo"); + settings->setValue(str, m_receiverDataList[i].waterfallOffsetLo); + + str = m_rxStringList.at(i); + str.append("/waterfallOffsetHi"); + settings->setValue(str, m_receiverDataList[i].waterfallOffsetHi); + + str = m_rxStringList.at(i); + str.append("/filterHi"); + settings->setValue(str, m_receiverDataList[i].filterHi); + + str = m_rxStringList.at(i); + str.append("/filterLo"); + settings->setValue(str, m_receiverDataList[i].filterLo); + + str = m_rxStringList.at(i); + str.append("/averaging"); + if (m_receiverDataList[i].spectrumAveraging) + settings->setValue(str, "on"); + else + settings->setValue(str, "off"); + + str = m_rxStringList.at(i); + str.append("/averagingCnt"); + settings->setValue(str, m_receiverDataList[i].averagingCnt); + + str = m_rxStringList.at(i); + str.append("/grid"); + if (m_receiverDataList[i].panGrid) + settings->setValue(str, "on"); + else + settings->setValue(str, "off"); + + str = m_rxStringList.at(i); + str.append("/hairCross"); + if (m_receiverDataList[i].hairCross) + settings->setValue(str, "on"); + else + settings->setValue(str, "off"); + + str = m_rxStringList.at(i); + str.append("/panLocked"); + if (m_receiverDataList[i].panLocked) + settings->setValue(str, "on"); + else + settings->setValue(str, "off"); + + str = m_rxStringList.at(i); + str.append("/clickVFO"); + if (m_receiverDataList[i].clickVFO) + settings->setValue(str, "on"); + else + settings->setValue(str, "off"); + + // center frequencies + for (int j = 0; j < MAX_BANDS; j++) { + + str = m_rxStringList.at(i); + str.append("/lastCenterFrequency"); + str.append(m_bandList.at(j).bandString); + + settings->setValue(str, (int)m_receiverDataList[i].lastCenterFrequencyList.at(j)); + } + + // vfo frequencies + for (int j = 0; j < MAX_BANDS; j++) { + + str = m_rxStringList.at(i); + str.append("/lastVfoFrequency"); + str.append(m_bandList.at(j).bandString); + + settings->setValue(str, (int)m_receiverDataList[i].lastVfoFrequencyList.at(j)); + } + + str = m_rxStringList.at(i); + str.append("/centerFrequency"); + settings->setValue(str, (int)m_receiverDataList[i].ctrFrequency); + + str = m_rxStringList.at(i); + str.append("/vfoFrequency"); + settings->setValue(str, (int)m_receiverDataList[i].vfoFrequency); + + for (int j = 0; j < MAX_BANDS; j++) { + + str = m_rxStringList.at(i); + str.append("/dspMode"); + str.append(m_bandList.at(j).bandString); + + DSPMode mode = m_receiverDataList.at(i).dspModeList.at(j); + if (mode == LSB) + settings->setValue(str, "LSB"); + else if (mode == USB) + settings->setValue(str, "USB"); + else if (mode == DSB) + settings->setValue(str, "DSB"); + else if (mode == CWL) + settings->setValue(str, "CWL"); + else if (mode == CWU) + settings->setValue(str, "CWU"); + else if (mode == FMN) + settings->setValue(str, "FMN"); + else if (mode == AM) + settings->setValue(str, "AM"); + else if (mode == DIGU) + settings->setValue(str, "DIGU"); + else if (mode == SPEC) + settings->setValue(str, "SPEC"); + else if (mode == DIGL) + settings->setValue(str, "DIGL"); + else if (mode == SAM) + settings->setValue(str, "SAM"); + else if (mode == DRM) + settings->setValue(str, "DRM"); + } + + for (int j = 0; j < MAX_BANDS; j++) { + + str = m_rxStringList.at(i); + str.append("/attenuator"); + str.append(m_bandList.at(j).bandString); + + if (m_receiverDataList.at(i).mercuryAttenuators.at(j)) + settings->setValue(str, "off"); + else + settings->setValue(str, "on"); + } + + for (int j = 0; j < MAX_BANDS; j++) { + + str = m_rxStringList.at(i); + str.append("/dBmPanScaleMin"); + str.append(m_bandList.at(j).bandString); + + settings->setValue(str, (int)m_receiverDataList[i].dBmPanScaleMinList[j]); + + str = m_rxStringList.at(i); + str.append("/dBmPanScaleMax"); + str.append(m_bandList.at(j).bandString); + + settings->setValue(str, (int)m_receiverDataList[i].dBmPanScaleMaxList[j]); + } + } + + + //****************************************************************** + // Cuda settings + //settings->setValue("Cuda/lastDevice", m_cudaLastDevice); + + + //****************************************************************** + // Chirp WSPR settings + settings->setValue("ChirpWSPR/lowerChirpFrequency", m_lowerChirpFreq); + settings->setValue("ChirpWSPR/upperChirpFrequency", m_upperChirpFreq); + settings->setValue("ChirpWSPR/chirpAmplitude", int(m_chirpAmplitude * 100)); + settings->setValue("ChirpWSPR/chirpSamplingFrequency", m_chirpSamplingFreq); + settings->setValue("ChirpWSPR/chirpBufferDurationUs", m_chirpBufferDurationUs); + settings->setValue("ChirpWSPR/chirpChannels", m_chirpChannels); + settings->setValue("ChirpWSPR/chirpBufferLength", m_chirpBufferLength); + settings->setValue("ChirpWSPR/chirpFilterLowerFrequency", m_chirpFilterLowerFrequency); + settings->setValue("ChirpWSPR/chirpFilterUpperFrequency", m_chirpFilterUpperFrequency); + + + //settings->setValue("ChirpWSPR/chirpDownSampleRate", m_chirpDownSampleRate); + + + //****************************************************************** + // Graphics settings + + /*if (m_specAveraging) + settings->setValue("graphics/averaging", "on"); + else + settings->setValue("graphics/averaging", "off");*/ + + /*if (m_panGrid) + settings->setValue("graphics/grid", "on"); + else + settings->setValue("graphics/grid", "off");*/ + + settings->setValue("graphics/dBmDistScaleMin", (int)m_dBmDistScaleMin); + settings->setValue("graphics/dBmDistScaleMax", (int)m_dBmDistScaleMax); + + /*if (m_waterfallColorScheme == QSDRGraphics::simple) + settings->setValue("graphics/waterfall", "simple"); + else + if (m_waterfallColorScheme == QSDRGraphics::enhanced) + settings->setValue("graphics/waterfall", "enhanced"); + else + if (m_waterfallColorScheme == QSDRGraphics::spectran) + settings->setValue("graphics/waterfall", "spectran");*/ + + settings->setValue("graphics/sMeterHoldTime", m_sMeterHoldTime); + + + // Colors + settings->setValue("colors/panBackground", QVariant(m_panadapterColors.panBackgroundColor).toString()); + settings->setValue("colors/waterfall", QVariant(m_panadapterColors.waterfallColor).toString()); + settings->setValue("colors/panLine", QVariant(m_panadapterColors.panLineColor).toString()); + settings->setValue("colors/panLineFilled", QVariant(m_panadapterColors.panLineFilledColor).toString()); + settings->setValue("colors/panSolidTop", QVariant(m_panadapterColors.panSolidTopColor).toString()); + settings->setValue("colors/panSolidBottom", QVariant(m_panadapterColors.panSolidBottomColor).toString()); + settings->setValue("colors/panWideBandLine", QVariant(m_panadapterColors.wideBandLineColor).toString()); + settings->setValue("colors/panWideBandFilled", QVariant(m_panadapterColors.wideBandFilledColor).toString()); + settings->setValue("colors/panWideBandSolidTop", QVariant(m_panadapterColors.wideBandSolidTopColor).toString()); + settings->setValue("colors/panWideBandSolidBottom", QVariant(m_panadapterColors.wideBandSolidBottomColor).toString()); + settings->setValue("colors/distanceLine", QVariant(m_panadapterColors.distanceLineColor).toString()); + settings->setValue("colors/distanceLineFilled", QVariant(m_panadapterColors.distanceLineFilledColor).toString()); + settings->setValue("colors/panCenterLine", QVariant(m_panadapterColors.panCenterLineColor).toString()); + settings->setValue("colors/gridLine", QVariant(m_panadapterColors.gridLineColor).toString()); + + SETTINGS_DEBUG << "save settings done."; + return 0; +} + +//void Settings::setMainWindowsState(QObject* sender) { +// +// settings->setValue("geometry", sender.saveGeometry()); +// settings->setValue("windowState", saveState()); +//} + +//******************************************************* + +QList Settings::getCtrFrequencies() { + + QList frequencies; + + for (int i = 0; i < MAX_RECEIVERS; i++) + frequencies << m_receiverDataList[i].ctrFrequency; + + return frequencies; +} + +QList Settings::getVfoFrequencies() { + + QList frequencies; + + for (int i = 0; i < MAX_RECEIVERS; i++) + frequencies << m_receiverDataList[i].vfoFrequency; + + return frequencies; +} + +QString Settings::getDSPModeString(int mode) { + + switch (mode) { + + case 0: + return QString("LSB"); + + case 1: + return QString("USB"); + + case 2: + return QString("DSB"); + + case 3: + return QString("CWL"); + + case 4: + return QString("CWU"); + + case 5: + return QString("FMN"); + + case 6: + return QString("AM"); + + case 7: + return QString("DIGU"); + + case 8: + return QString("SPEC"); + + case 9: + return QString("DIGL"); + + case 10: + return QString("SAM"); + + case 11: + return QString("DRM"); + + default: + return QString("unknown mode"); + } +} + +//******************************************************* + +QString Settings::getTitleStr() { + + return m_titleString; +} + +QString Settings::getVersionStr() { + + return m_versionString; +} + +QString Settings::getSettingsFilename() { + + return settingsFilename; +} + +QString Settings::getCallsign() { + + return m_callsignString; +} + +QString Settings::getValue1000( + + double value, /*!<[in] Value to print. */ + int valuePrefix, /*!<[in] Value current prefix. */ + QString unitBase) /*!<[in] Unit base string. */ +{ + const int prefixBase = 1000; + int resPrefix = valuePrefix; + + static const char *prefixTab[prefixSiMax + 1] = { + "", /* prefixNothing */ + "k", /* prefixKilo */ + "M", /* prefixMega */ + "G", /* prefixGiga */ + "T", /* prefixTera */ + "P", /* prefixPeta */ + "E", /* prefixExa */ + "Z", /* prefixZetta */ + "Y", /* prefixYotta */ + }; + + /*while((value > (10 * prefixBase)) && (resPrefix < prefixSiMax)) { + value /= prefixBase; + resPrefix++; + }*/ + while((value > (prefixBase/10)) && (resPrefix < prefixSiMax)) { + value /= prefixBase; + resPrefix++; + } + + return QString("%1 %2%3").arg(value).arg(prefixTab[resPrefix]).arg(unitBase); +} + +QString Settings::getValue1024( + + double value, /*!<[in] Value to print. */ + int valuePrefix, /*!<[in] Value current prefix. */ + QString unitBase) /*!<[in] Unit base string. */ +{ + const int prefixBase = 1024; + int resPrefix = valuePrefix; + + static const char *prefixTab[prefixIecMax + 1] = { + "", /* prefixNothing */ + "Ki", /* prefixKibi */ + "Mi", /* prefixMebi */ + "Gi", /* prefixGibi */ + "Ti", /* prefixTebi */ + "Pi", /* prefixPebi */ + "Ei", /* prefixExbi */ + "Zi", /* prefixZebi */ + "Yi", /* prefixYobi */ + }; + + while((value > (10 * prefixBase)) && (resPrefix < prefixIecMax)) { + value /= prefixBase; + resPrefix++; + } + + return QString("%1 %2%3").arg(value).arg(prefixTab[resPrefix]).arg(unitBase); +} + +int Settings::getMinimumWidgetWidth() { + + return m_minimumWidgetWidth; +} + +int Settings::getMinimumGroupBoxWidth() { + + return m_minimumGroupBoxWidth; +} + +void Settings::debugSystemState() { + + qDebug() << " "; + SETTINGS_DEBUG << "**********************************************************"; + SETTINGS_DEBUG << "Error:\t\t\t" << qPrintable(getErrorString(m_systemError)); + SETTINGS_DEBUG << "HW Interface:\t\t" << qPrintable(getHWInterfaceModeString(m_hwInterface)); + SETTINGS_DEBUG << "Server Mode:\t\t" << qPrintable(getServerModeString(m_serverMode)); + SETTINGS_DEBUG << "DataEngine State:\t" << qPrintable(getHDataEngineStateString(m_dataEngineState)); + qDebug() << " "; +} + +QString Settings::getSDRStyle() { + + return sdrStyle; +} + +QString Settings::getWidgetStyle() { + + return widgetStyle; +} + +QString Settings::getMainWindowStyle() { + + return mainWindowStyle; +} + +QString Settings::getDockStyle() { + + return dockStyle; +} + +QString Settings::getDisplayToolbarStyle() { + + return displayToolbarStyle; +} + +QString Settings::getMainBtnToolbarStyle() { + + return mainBtnToolbarStyle; +} + +QString Settings::getStatusbarStyle() { + + return statusbarStyle; +} + +QString Settings::getMessageBoxStyle() { + + return messageBoxStyle; +} + +QString Settings::getLineEditStyle() { + + return lineEditStyle; +} + +QString Settings::getDialogStyle() { + + return dialogStyle; +} + +QString Settings::getColorDialogStyle() { + + return colorDialogStyle; +} + +QString Settings::getItemStyle() { + + return itemStyle; +} + +QString Settings::getLabelStyle() { + + return labelStyle; +} + +QString Settings::getSliderLabelStyle() { + + return sliderLabelStyle; +} + +QString Settings::getTableStyle() { + + return tableStyle; +} + +QString Settings::getComboBoxStyle() { + + return comboBoxStyle; +} + +QString Settings::getSpinBoxStyle() { + + return spinBoxStyle; +} + +QString Settings::getDoubleSpinBoxStyle() { + + return dSpinBoxStyle; +} + +QString Settings::getMenuStyle() { + + return menuStyle; +} + +QString Settings::getMiniButtonStyle() { + + return miniButtonStyle; +} + +QString Settings::getVolSliderStyle() { + + return volSliderStyle; +} + +QString Settings::getSplitterStyle() { + + return splitterStyle; +} + +QString Settings::getFrameStyle() { + + return frameStyle; +} + +QString Settings::getTabWidgetStyle() { + + return tabWidgetStyle; +} + +//QString Settings::getNewSliderStyle() { +// +// return m_newSliderStyle; +//} + + +//******************************************************* + +void Settings::setMainPower(QObject *sender, bool power) { + + if (m_mainPower == power) return; + + m_mainPower = power; + if (power) + m_mainPower = true; + else + m_mainPower = false; + + emit masterSwitchChanged(sender, m_mainPower); +} + +bool Settings::getMainPower() { + + return m_mainPower; +} + +void Settings::setSystemMessage(const QString &msg, int time) { + + emit systemMessageEvent(msg, time); +} + +void Settings::setSystemState( + + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state) +{ + Q_UNUSED (sender) + + //QMutexLocker locker(&settingsMutex); + + if (m_systemError != err) + m_systemError = err; + + if (m_hwInterface != hwmode) + m_hwInterface = hwmode; + + if (m_serverMode != mode) { + + m_serverMode = mode; + + if (m_serverMode == QSDR::ChirpWSPR) + setWidebandStatus(this, false); + } + + if (m_dataEngineState != state) + m_dataEngineState = state; + + if (m_dataEngineState == QSDR::DataEngineDown) + setCurrentReceiver(this, 0); + //m_currentReceiver = 0; + + //locker.unlock(); + + debugSystemState(); + emit systemStateChanged(this, m_systemError, m_hwInterface, m_serverMode, m_dataEngineState); +} + +QSDR::_ServerMode Settings::getCurrentServerMode() { + + return m_serverMode; +} + +QSDR::_HWInterfaceMode Settings::getHWInterface() { + + return m_hwInterface; +} + +QSDR::_DataEngineState Settings::getDataEngineState() { + + return m_dataEngineState; +} + +QString Settings::getErrorString(QSDR::_Error err) { + + QString str; + switch (err) { + + case 0: + str = "No error"; + break; + + case 1: + str = "Not implemented"; + break; + + case 2: + str = "Hardware IO error"; + break; + + case 3: + str = "Server mode error"; + break; + + case 4: + str = "open device error"; + break; + + case 5: + str = "dataReceiverThread error"; + break; + + case 6: + str = "dataProcessThread error"; + break; + + case 7: + str = "widebandDataProcessThread error"; + break; + + case 8: + str = "audioThread error"; + break; + + case 9: + str = "ChirpDataProcessThread error"; + break; + + case 10: + str = "underrun error"; + break; + + case 11: + str = "firmware error"; + break; + + case 12: + str = "fatal error"; + break; + } + return str; +} + +QString Settings::getHDataEngineStateString(QSDR::_DataEngineState mode) { + + QString str; + switch (mode) { + + case 0: + str = "down"; + break; + + case 1: + str = "up"; + break; + } + return str; +} + +QString Settings::getServerModeString(QSDR::_ServerMode mode) { + + QString str; + switch (mode) { + + case 0: + str = "no server mode"; + break; + + case 1: + str = "SDR mode"; + break; + + case 2: + str = "ChirpWSPR"; + break; + + case 3: + str = "ChirpWSPRFile"; + break; + + case 4: + str = "demo"; + break; + } + return str; +} + +QString Settings::getHWInterfaceModeString(QSDR::_HWInterfaceMode mode) { + + QString str; + switch (mode) { + + case 0: + str = "no interface"; + break; + + case 1: + str = "Metis"; + break; + + case 2: + str = "Hermes"; + break; + } + return str; +} + +void Settings::setTxAllowed(QObject *sender, bool value) { + + if (m_devices.penelopePresence || m_devices.pennylanePresence || (m_hwInterface == QSDR::Hermes)) + m_transmitter.txAllowed = value; + else + m_transmitter.txAllowed = false; + + emit txAllowedChanged(sender, m_transmitter.txAllowed); +} + +bool Settings::getTxAllowed() { + + return m_transmitter.txAllowed; +} + +void Settings::setGraphicsState( + + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode) +{ + Q_UNUSED (sender) + + //QMutexLocker locker(&settingsMutex); + + if (rx == -1) { + + m_widebandOptions.panMode = panMode; + } + else { + + m_receiverDataList[rx].panMode = panMode; + m_receiverDataList[rx].waterfallMode = waterfallColorMode; + } + + //locker.unlock(); + + //SETTINGS_DEBUG << "graphics mode:" << panMode << waterfallColorMode; + emit graphicModeChanged(this, rx, panMode, waterfallColorMode); +} + +PanGraphicsMode Settings::getPanadapterMode(int rx) { + + return m_receiverDataList[rx].panMode; +} + +WaterfallColorMode Settings::getWaterfallColorMode(int rx) { + + return m_receiverDataList.at(rx).waterfallMode; +} + +//QSDRGraphics::_Colors Settings::getColorItem() { +// +// return m_colorItem; +//} + +void Settings::setDefaultSkin(QObject *sender, bool value) { + + Q_UNUSED (sender) + + m_defaultSkin = value; +} + +bool Settings::getDefaultSkin() { + + return m_defaultSkin; +} + +void Settings::setSettingsFilename(QString filename) { + + filename = filename.trimmed(); + + //QMutexLocker locker(&settingsMutex); + + settingsFilename = filename; + //locker.unlock(); + + emit settingsFilenameChanged(filename); +} + +void Settings::setSettingsLoaded(bool value) { + + QMutexLocker locker(&settingsMutex); + + setLoaded = value; + + locker.unlock(); + + emit settingsLoadedChanged(setLoaded); +} + +bool Settings::getSettingsLoaded() { + + return setLoaded; +} + +void Settings::setCPULoad(short load) { + + emit cpuLoadChanged(load); +} + +void Settings::setCallsign(const QString &callsign) { + + QString cs = callsign.trimmed(); + + QMutexLocker locker(&settingsMutex); + + if (m_callsignString == cs) return; + + m_callsignString = cs; + + locker.unlock(); + emit callsignChanged(); +} + +void Settings::setRxList(QList rxList) { + + emit rxListChanged(rxList); +} + +void Settings::setMultiRxView(int view) { + + QMutexLocker locker(&settingsMutex); + + if (m_multiRxView == view) return; + m_multiRxView = view; + + locker.unlock(); + emit multiRxViewChanged(m_multiRxView); +} + +int Settings::getMultiRxView() { + + return m_multiRxView; +} + +void Settings::setMetisCardList(QList list) { + + QMutexLocker locker(&settingsMutex); + + m_metisCards = list; + + locker.unlock(); + emit metisCardListChanged(m_metisCards); +} + +void Settings::searchHpsdrNetworkDevices() { + + emit searchMetisSignal(); +} + +void Settings::clearMetisCardList() { + + m_metisCards.clear(); + + //emit metisCardListChanged(m_metisCards); +} + +void Settings::setCurrentHPSDRDevice(TNetworkDevicecard card) { + + m_currentHPSDRDevice = card; + + emit hpsdrNetworkDeviceChanged(m_currentHPSDRDevice); +} + +void Settings::setHPSDRDeviceNumber(int value) { + + m_hpsdrNetworkDevices = value; + emit networkDeviceNumberChanged(value); +} + +void Settings::showNetworkIODialog() { + + emit showNetworkIO(); +} + +void Settings::showWarningDialog(const QString &msg) { + + emit showWarning(msg); +} + +void Settings::addNetworkIOComboBoxEntry(QString str) { + + emit networkIOComboBoxEntryAdded(str); +} + +void Settings::clearNetworkIOComboBoxEntry() { + + emit clearNetworkIOComboBoxEntrySignal(); +} + +void Settings::setPBOPresence(bool value) { + + m_pboFound = value; +} + +bool Settings::getPBOPresence() { + + return m_pboFound; +} + +void Settings::setFBOPresence(bool value) { + + m_fboFound = value; +} + +bool Settings::getFBOPresence() { + + return m_fboFound; +} + +//******************************* +// Network settings + +void Settings::setNumberOfNetworkInterfaces(int value) { + + m_NetworkInterfacesNo = value; +} + +void Settings::addServerNetworkInterface(QString nicName, QString ipAddress) { + + emit newServerNetworkInterface(nicName, ipAddress); +} + +void Settings::addHPSDRDeviceNIC(QString nicName, QString ipAddress) { + + emit newHPSDRDeviceNIC(nicName, ipAddress); +} + +void Settings::setServerNetworkInterface(int index) { + + setServerAddr(this, this->m_ipAddressesList.at(index).toString()); + + //qDebug() << "m_networkInterfaces.at(index).humanReadableName():" << m_networkInterfaces.at(index).humanReadableName(); + //qDebug() << "m_ipAddressesList.at(index).toString():" << m_ipAddressesList.at(index).toString(); + + QString message = "[settings]: network interface set to: %1 (%2)."; + /*emit messageEvent( + message.arg( + m_networkInterfaces.at(index).humanReadableName(), + m_ipAddressesList.at(index).toString() ));*/ + +} + +void Settings::setHPSDRDeviceNIC(int index) { + + setHPSDRDeviceLocalAddr(this, this->m_ipAddressesList.at(index).toString()); + + QString message = "[settings]: HPSDR device network interface set to: %1 (%2)."; + /*emit messageEvent( + message.arg( + m_networkInterfaces.at(index).humanReadableName(), + m_ipAddressesList.at(index).toString() ));*/ + +} + +void Settings::setServerWidgetNIC(int index) { + + /*QString message = "[server]: network interface set to: %1 (%2)."; + emit messageEvent( + message.arg( + m_networkInterfaces.at(index).humanReadableName(), + m_ipAddressesList.at(index).toString() ));*/ + + emit serverNICChanged(index); +} + +void Settings::setHPSDRWidgetNIC(int index) { + + /*QString message = "[server]: HPSDR device network interface set to: %1 (%2)."; + emit messageEvent( + message.arg( + m_networkInterfaces.at(index).humanReadableName(), + m_ipAddressesList.at(index).toString() ));*/ + + emit hpsdrDeviceNICChanged(index); +} + +void Settings::setServerAddr(QObject *sender, QString addr) { + + QMutexLocker locker(&settingsMutex); + + m_serverAddress = addr; + + locker.unlock(); + emit serverAddrChanged(sender, m_serverAddress); +} + +QString Settings::getServerAddr() { + + return m_serverAddress; +} + +void Settings::setHPSDRDeviceLocalAddr(QObject *sender, QString addr) { + + QMutexLocker locker(&settingsMutex); + + m_hpsdrDeviceLocalAddr = addr; + + locker.unlock(); + emit hpsdrDeviceLocalAddrChanged(sender, m_hpsdrDeviceLocalAddr); +} + +QString Settings::getHPSDRDeviceLocalAddr() { + + return m_hpsdrDeviceLocalAddr; +} + +void Settings::setServerPort(QObject *sender, quint16 port) { + + QMutexLocker locker(&settingsMutex); + + m_serverPort = port; + + locker.unlock(); + emit serverPortChanged(sender, m_serverPort); +} + +quint16 Settings::getServerPort() { + + return m_serverPort; +} + +void Settings::setListenPort(QObject *sender, quint16 port) { + + QMutexLocker locker(&settingsMutex); + + m_listenerPort = port; + + locker.unlock(); + emit listenPortChanged(sender, m_listenerPort); +} + +quint16 Settings::getListenPort() { + + return m_listenerPort; +} + +void Settings::setAudioPort(QObject *sender, quint16 port) { + + QMutexLocker locker(&settingsMutex); + m_audioPort = port; + locker.unlock(); + + emit audioPortChanged(sender, m_audioPort); +} + +quint16 Settings::getAudioPort() { + + return m_audioPort; +} + +void Settings::setMetisPort(QObject *sender, quint16 port) { + + QMutexLocker locker(&settingsMutex); + m_metisPort = port; + locker.unlock(); + + emit metisPortChanged(sender, m_metisPort); +} + +quint16 Settings::getMetisPort() { + + return m_metisPort; +} + +void Settings::setClientConnected(QObject *sender, bool value) { + + QMutexLocker locker(&settingsMutex); + m_clientConnected = value; + locker.unlock(); + + emit clientConnectedChanged(sender, m_clientConnected); +} + +bool Settings::getClientConnected() { + + return m_clientConnected; +} + +void Settings::setClientNoConnected(QObject* sender, int client) { + + QMutexLocker locker(&settingsMutex); + m_clientNoConnected = client; + locker.unlock(); + + emit clientNoConnectedChanged(sender, m_clientNoConnected); +} + +void Settings::setAudioRx(QObject* sender, int rx) { + + emit audioRxChanged(sender, rx); +} + +void Settings::setConnected(QObject *sender, bool value) { + + QMutexLocker locker(&settingsMutex); + m_connected = value; + locker.unlock(); + + emit connectedChanged(sender, m_connected); +} + +bool Settings::getConnected() { + + return m_connected; +} + +void Settings::clientDisconnected(int client) { + + emit clientDisconnectedEvent(client); +} + +void Settings::setRxConnectedStatus(QObject* sender, int rx, bool value) { + + emit rxConnectedStatusChanged(sender, rx, value); +} + +void Settings::setSocketBufferSize(QObject *sender, int value) { + + m_socketBufferSize = value; + //SETTINGS_DEBUG << "m_socketBufferSize = " << value; + emit socketBufferSizeChanged(sender, value); +} + +void Settings::setManualSocketBufferSize(QObject *sender, bool value) { + + m_manualSocketBufferSize = value; + //SETTINGS_DEBUG << "m_manualSocketBufferSize = " << value; + emit manualSocketBufferChanged(sender, m_manualSocketBufferSize); +} + + +//******************************* +// HPSDR hardware presence and firmware versions + +THPSDRDevices Settings::getHPSDRDevices() { + + return m_devices; +} + +void Settings::setHPSDRDevices(QObject *sender, THPSDRDevices devices) { + + Q_UNUSED(sender) + Q_UNUSED(devices) +} + +void Settings::checkHPSDRDevices() { + + SETTINGS_DEBUG << "mercuryPresence: " << m_devices.mercuryPresence; + SETTINGS_DEBUG << "penelopePresence: " << m_devices.penelopePresence; + SETTINGS_DEBUG << "pennylanePresence: " << m_devices.pennylanePresence; + SETTINGS_DEBUG << "excaliburPresence: " << m_devices.excaliburPresence; + SETTINGS_DEBUG << "alexPresence: " << m_devices.alexPresence; + SETTINGS_DEBUG << "hermesPresence: " << m_devices.hermesPresence; + + if (m_hpsdrHardware == 0) { // 0 = Mercury/Penelope + + if (m_devices.penelopePresence && m_devices.pennylanePresence) { + + m_devices.pennylanePresence = false; + m_devices.penelopePresence = true; + SETTINGS_DEBUG << "settings specifies both Penelope and Pennylane - choosing Penelope !"; + } + + if (m_devices.hermesPresence) { + + m_devices.hermesPresence = false; + SETTINGS_DEBUG << "settings specifies also Hermes - choosing Mercury/Penelope/Pennylane !"; + } + } + else if (m_hpsdrHardware == 1) { // 1 = Hermes + + if (m_devices.mercuryPresence || + m_devices.penelopePresence || + m_devices.pennylanePresence || + m_devices.excaliburPresence) + { + m_devices.mercuryPresence = false; + m_devices.penelopePresence = false; + m_devices.pennylanePresence = false; + m_devices.excaliburPresence = false; + SETTINGS_DEBUG << "settings specifies HPSDR Modules - choosing Hermes !"; + } + } +} + + +void Settings::setHPSDRHardware(int value) { + + m_hpsdrHardware = value; // 0 = Mercury/Penelope, 1 = Hermes, 2 = Cyclops + + emit hpsdrHardwareChanged(m_hpsdrHardware); +} + +void Settings::setHermesVersion(int value) { + + QMutexLocker locker(&settingsMutex); + m_devices.hermesFWVersion = value; + locker.unlock(); + + emit hermesVersionChanged(m_devices.hermesFWVersion); +} + +void Settings::setMercuryPresence(bool value) { + + m_devices.mercuryPresence = value; + + emit mercuryPresenceChanged(m_devices.mercuryPresence); +} + +void Settings::setMercuryVersion(int value) { + + QMutexLocker locker(&settingsMutex); + m_devices.mercuryFWVersion = value; + locker.unlock(); + + emit mercuryVersionChanged(m_devices.mercuryFWVersion); +} + +void Settings::setPenelopePresence(bool value) { + + m_devices.penelopePresence = value; + setTxAllowed(this, value); + + emit penelopePresenceChanged(m_devices.penelopePresence); +} + +void Settings::setPenelopeVersion(int value) { + + QMutexLocker locker(&settingsMutex); + m_devices.penelopeFWVersion = value; + locker.unlock(); + + emit penelopeVersionChanged(m_devices.penelopeFWVersion); +} + +void Settings::setPennyLanePresence(bool value) { + + m_devices.pennylanePresence = value; + setTxAllowed(this, value); + + emit pennyLanePresenceChanged(m_devices.pennylanePresence); +} + +void Settings::setPennyLaneVersion(int value) { + + QMutexLocker locker(&settingsMutex); + m_devices.pennylaneFWVersion = value; + locker.unlock(); + + emit pennyLaneVersionChanged(m_devices.pennylaneFWVersion); +} + +void Settings::setAlexPresence(bool value) { + + m_devices.alexPresence = value; + + emit alexPresenceChanged(m_devices.alexPresence); +} + +void Settings::setExcaliburPresence(bool value) { + + m_devices.excaliburPresence = value; + + emit excaliburPresenceChanged(m_devices.excaliburPresence); +} + +void Settings::setMetisVersion(int value) { + + QMutexLocker locker(&settingsMutex); + m_devices.metisFWVersion = value; + locker.unlock(); + + emit metisVersionChanged(m_devices.metisFWVersion); +} + +void Settings::setCheckFirmwareVersion(QObject *sender, bool value) { + + m_checkFirmwareVersions = value; + + emit checkFirmwareVersionChanged(sender, value); +} + +void Settings::setProtocolSync(int value) { + + emit protocolSyncChanged(value); +} + +void Settings::setADCOverflow(int value) { + + emit adcOverflowChanged(value); +} + +void Settings::setPacketLoss(int value) { + + emit packetLossChanged(value); +} + +void Settings::setSendIQ(int value) { + + emit sendIQSignalChanged(value); +} + +void Settings::setRcveIQ(int value) { + + emit rcveIQSignalChanged(value); +} + +/** + * Set the number of receivers to be supported by this server + * \param r The number of receivers: 0 to 6 + * This value is embedded into the command & control bytes that are sent to Mercury. + * Thus it determines how the I & Q samples read from EP6 are placed in the data stream to dspservers. + */ +void Settings::setReceivers(QObject *sender, int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_mercuryReceivers == value) return; + if (value > MAX_RECEIVERS) value = MAX_RECEIVERS; + + m_mercuryReceivers = value; + locker.unlock(); + + SETTINGS_DEBUG << "set number of receivers to: " << m_mercuryReceivers; + emit numberOfRXChanged(sender, value); +} + +//void Settings::setReceiver(QObject *sender, int value) { +// +// QMutexLocker locker(&settingsMutex); +// +// if (m_currentReceiver == value) return; +// if (value > MAX_RECEIVERS) value = MAX_RECEIVERS; +// +// m_currentReceiver = value; +// locker.unlock(); +// +// SETTINGS_DEBUG << "switch to receiver: " << m_currentReceiver; +// emit receiverChanged(value); +// emit frequencyChanged(this, true, value, m_receiverDataList[value].frequency); +//} + +void Settings::setCurrentReceiver(QObject *sender, int value) { + + //SETTINGS_DEBUG << "sender: " << sender; + QMutexLocker locker(&settingsMutex); + + if (value > MAX_RECEIVERS) { + + SETTINGS_DEBUG << "receiver number > MAX_RECEIVERS; setting to MAX_RECEIVERS."; + value = MAX_RECEIVERS; + } + + m_currentReceiver = value; + + HamBand band = m_receiverDataList.at(m_currentReceiver).hamBand; + DSPMode mode = m_receiverDataList.at(m_currentReceiver).dspModeList[band]; + locker.unlock(); + + setMercuryAttenuator(this, m_receiverDataList.at(m_currentReceiver).mercuryAttenuators.at(band)); + setFramesPerSecond(this, m_currentReceiver, m_receiverDataList.at(m_currentReceiver).framesPerSecond); + + SETTINGS_DEBUG << "switch to receiver: " << m_currentReceiver; + emit currentReceiverChanged(sender, value); + //emit frequencyChanged(sender, true, value, m_receiverDataList.at(m_currentReceiver).frequency); + long vfoF = m_receiverDataList.at(m_currentReceiver).vfoFrequency; + long ctrF = m_receiverDataList.at(m_currentReceiver).ctrFrequency; + + emit ctrFrequencyChanged(sender, true, value, ctrF); + emit vfoFrequencyChanged(sender, true, value, vfoF); + emit ncoFrequencyChanged(m_currentReceiver, vfoF - ctrF); + emit hamBandChanged(sender, m_currentReceiver, false, band); + emit dspModeChanged(sender, m_currentReceiver, mode); + emit mouseWheelFreqStepChanged(sender, m_currentReceiver, m_receiverDataList.at(m_currentReceiver).mouseWheelFreqStep); +} + +void Settings::setSampleRate(QObject *sender, int value) { + + QMutexLocker locker(&settingsMutex); + + switch (value) { + + case 48000: + m_sampleRate = value; + m_mercurySpeed = 0; + m_outputSampleIncrement = 1; + m_chirpDownSampleRate = 4; + break; + + case 96000: + m_sampleRate = value; + m_mercurySpeed = 1; + m_outputSampleIncrement = 2; + m_chirpDownSampleRate = 8; + break; + + case 192000: + m_sampleRate = value; + m_mercurySpeed = 2; + m_outputSampleIncrement = 4; + m_chirpDownSampleRate = 16; + break; + + case 384000: + m_sampleRate = value; + m_mercurySpeed = 3; + m_outputSampleIncrement = 8; + m_chirpDownSampleRate = 32; + break; + + default: + SETTINGS_DEBUG << "Invalid sample rate (must be 48, 96,192, or 384 kHz)!\n"; + break; + } + + for (int i = 0; i < MAX_RECEIVERS; i++) + m_receiverDataList[i].sampleRate = m_sampleRate; + + emit sampleRateChanged(sender, value); +} + +void Settings::setMercuryAttenuator(QObject *sender, int value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(m_currentReceiver).mercuryAttenuators.length() != MAX_BANDS) + return; + + HamBand band = m_receiverDataList[m_currentReceiver].hamBand; + m_receiverDataList[m_currentReceiver].mercuryAttenuators[band] = value; + + emit mercuryAttenuatorChanged(sender, band, value); +} + +QList Settings::getMercuryAttenuators(int rx) { + + return m_receiverDataList[rx].mercuryAttenuators; +} + +void Settings::setDither(QObject *sender, int value) { + + QMutexLocker locker(&settingsMutex); + m_mercuryDither = value; + + emit ditherChanged(sender, value); +} + +void Settings::setRandom(QObject *sender, int value) { + + QMutexLocker locker(&settingsMutex); + m_mercuryRandom = value; + + emit randomChanged(sender, value); +} + +void Settings::set10MhzSource(QObject *sender, int source) { + + QMutexLocker locker(&settingsMutex); + + m_10MHzSource = source; + emit src10MhzChanged(sender, source); +} + +void Settings::set122_88MhzSource(QObject *sender, int source) { + + QMutexLocker locker(&settingsMutex); + + m_122_8MHzSource = source; + emit src122_88MhzChanged(sender, source); +} + +void Settings::setMicSource(QObject *sender, int source) { + + QMutexLocker locker(&settingsMutex); + + m_micSource = source; + emit micSourceChanged(sender, source); +} + +void Settings::setClass(QObject *sender, int value) { + + QMutexLocker locker(&settingsMutex); + + m_RxClass = value; + emit classChanged(sender, value); +} + +void Settings::setTiming(QObject *sender, int value) { + + QMutexLocker locker(&settingsMutex); + + m_RxTiming = value; + emit timingChanged(sender, value); +} + +void Settings::setMouseWheelFreqStep(QObject *sender, int rx, qreal value) { + + QMutexLocker locker(&settingsMutex); + + //m_mouseWheelFreqStep = value; + m_receiverDataList[rx].mouseWheelFreqStep = value; + emit mouseWheelFreqStepChanged(sender, rx, value); +} + +double Settings::getMouseWheelFreqStep(int rx) { + + return m_receiverDataList[rx].mouseWheelFreqStep; +} + +qreal Settings::getMainVolume(int rx) { + + return m_receiverDataList[rx].audioVolume; +} + +void Settings::setMainVolume(QObject *sender, int rx, float volume) { + + if (volume < 0) volume = 0.0f; + if (volume > 1) volume = 1.0f; + + QMutexLocker locker(&settingsMutex); + + //if (m_receiverDataList[rx].audioVolume == volume) return; + m_receiverDataList[rx].audioVolume = volume; + + emit mainVolumeChanged(sender, rx, volume); +} + +void Settings::setMainVolumeMute(QObject *sender, int rx, bool value) { + + Q_UNUSED(sender) + Q_UNUSED(value) + + qreal vol = getMainVolume(rx); + if (value) + setMainVolume(this, rx, 0.0f); + else + setMainVolume(this, rx, vol); +} + +void Settings::setCtrFrequency(int rx, long frequency) { + + QMutexLocker locker(&settingsMutex); + + HamBand band = getBandFromFrequency(m_bandList, frequency); + + m_receiverDataList[rx].ctrFrequency = frequency; + //m_receiverDataList[rx].hamBand = band; + //m_receiverDataList[rx].lastHamBand = band; + m_receiverDataList[rx].lastCenterFrequencyList[(int) band] = frequency; +} + +void Settings::setVfoFrequency(int rx, long frequency) { + + QMutexLocker locker(&settingsMutex); + + HamBand band = getBandFromFrequency(m_bandList, frequency); + + m_receiverDataList[rx].vfoFrequency = frequency; + m_receiverDataList[rx].hamBand = band; + m_receiverDataList[rx].lastHamBand = band; + m_receiverDataList[rx].lastVfoFrequencyList[(int) band] = frequency; + + m_receiverDataList[rx].ncoFrequency = frequency - m_receiverDataList.at(rx).ctrFrequency; +} + +void Settings::setCtrFrequency(QObject *sender, int mode, int rx, long frequency) { + + QMutexLocker locker(&settingsMutex); + m_receiverDataList[rx].ctrFrequency = frequency; + + HamBand band = getBandFromFrequency(m_bandList, frequency); + m_receiverDataList[rx].lastCenterFrequencyList[(int) band] = frequency; + locker.unlock(); + + switch (mode) { + + case 0: + break; + + case 1: + + setVFOFrequency(this, 0, rx, frequency); + break; + } + + //SETTINGS_DEBUG << "ctr freq (Rx " << rx << ") " << m_receiverDataList[rx].ctrFrequency; + emit ctrFrequencyChanged(sender, mode, rx, frequency); +} + +long Settings::getCtrFrequency(int rx) { + + return m_receiverDataList.at(rx).ctrFrequency; +} + +void Settings::setVFOFrequency(QObject *sender, int mode, int rx, long frequency) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).vfoFrequency == frequency) return; + m_receiverDataList[rx].vfoFrequency = frequency; + //SETTINGS_DEBUG << "vfo freq (Rx " << rx << ") " << m_receiverDataList[rx].vfoFrequency; + + HamBand band = getBandFromFrequency(m_bandList, frequency); + m_receiverDataList[rx].lastVfoFrequencyList[(int) band] = frequency; + + locker.unlock(); + if (m_receiverDataList.at(rx).hamBand != band) { + + //m_receiverDataList[rx].ctrFrequency = m_receiverDataList[rx].vfoFrequency; + setHamBand(this, rx, false, band); + } + + switch (mode) { + + case 0: // change only VFO + + m_receiverDataList[rx].ncoFrequency = frequency - m_receiverDataList.at(rx).ctrFrequency; + //SETTINGS_DEBUG << "nco freq = " << m_receiverDataList[rx].ncoFrequency; + break; + + case 1: // change VFO and center freq; keep NCO frequency + + setCtrFrequency(this, 0, rx, frequency - m_receiverDataList.at(rx).ncoFrequency); + break; + + case 2: // change VFO, set center frequency from lastCenterFrequencyList + + setCtrFrequency(this, 0, rx, m_receiverDataList.at(rx).lastCenterFrequencyList.at((int) band)); + m_receiverDataList[rx].ncoFrequency = frequency - m_receiverDataList.at(rx).ctrFrequency; + break; + } + + emit vfoFrequencyChanged(sender, mode, rx, frequency); + + //SETTINGS_DEBUG << "nco freq (Rx " << rx << ") " << m_receiverDataList[rx].ncoFrequency; + emit ncoFrequencyChanged(rx, m_receiverDataList[rx].ncoFrequency); +} + +long Settings::getVfoFrequency(int rx) { + + return m_receiverDataList.at(rx).vfoFrequency; +} + +void Settings::setNCOFrequency(QObject *sender, bool value, int rx, long frequency) { + + Q_UNUSED(sender) + Q_UNUSED(value) + + //SETTINGS_DEBUG << "nco freq (Rx " << rx << ") " << m_receiverDataList[rx].ncoFrequency << "(direct)"; + m_receiverDataList[rx].ncoFrequency = frequency; + + emit ncoFrequencyChanged(rx, frequency); +} + +void Settings::setHamBand(QObject *sender, int rx, bool byButton, HamBand band) { + + //SETTINGS_DEBUG << "sender: " << sender; + QMutexLocker locker(&settingsMutex); + if (m_receiverDataList[rx].hamBand == band && sender != this) + return; + + m_receiverDataList[rx].lastHamBand = m_receiverDataList[rx].hamBand; + m_receiverDataList[rx].hamBand = band; + + //SETTINGS_DEBUG << "last Ham band: " << m_receiverDataList[rx].lastHamBand; + //SETTINGS_DEBUG << "Ham band: " << m_receiverDataList[rx].hamBand; + + if (m_receiverDataList[rx].hamBand == (HamBand) gen) + setTxAllowed(this, false); + else + setTxAllowed(this, true); + + locker.unlock(); + + setDSPMode(this, rx, m_receiverDataList.at(rx).dspModeList.at(band)); + setMercuryAttenuator(this, m_receiverDataList[rx].mercuryAttenuators[band]); + + emit hamBandChanged(sender, rx, byButton, band); +} + +HamBand Settings::getCurrentHamBand(int rx) { + + return m_receiverDataList[rx].hamBand; +} + +void Settings::setDSPMode(QObject *sender, int rx, DSPMode mode) { + + //SETTINGS_DEBUG << "sender: " << sender; + HamBand band = m_receiverDataList[m_currentReceiver].hamBand; + + m_receiverDataList[rx].dspModeList[band] = mode; + setRXFilter(this, rx, m_defaultFilterList.at((int) mode).filterLo, m_defaultFilterList.at((int) mode).filterHi); + + emit dspModeChanged(sender, rx, mode); +} + +AGCMode Settings::getAGCMode(int rx) { + + return m_receiverDataList.at(rx).agcMode; +} + +QString Settings::getAGCModeString(int rx) { + + AGCMode mode = getAGCMode(rx); + QString str; + switch (mode) { + + case (AGCMode) agcOFF: + str = "Off"; + break; + + case (AGCMode) agcLONG: + str = "Long"; + break; + + case (AGCMode) agcSLOW: + str = "Slow"; + break; + + case (AGCMode) agcMED: + str = "Med"; + break; + + case (AGCMode) agcFAST: + str = "Fast"; + break; + + case (AGCMode) agcUser: + str = "User"; + break; + } + return str; +} + +void Settings::setAGCMode(QObject *sender, int rx, AGCMode mode) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].agcMode == mode) return; + m_receiverDataList[rx].agcMode = mode; + + bool hang; + if (mode == (AGCMode) agcOFF || mode == (AGCMode) agcMED || mode == (AGCMode) agcFAST) { + + m_receiverDataList[rx].hangEnabled = false; + hang = false; + if (mode == (AGCMode) agcOFF) + emit agcFixedGainChanged_dB(sender, rx, m_receiverDataList[rx].agcFixedGain_dB); + } + else { + + m_receiverDataList[rx].hangEnabled = true; + hang = true; + } + + emit agcModeChanged(sender, rx, mode, hang); + emit agcHangEnabledChanged(sender, rx, hang); +} + +void Settings::setAGCShowLines(QObject *sender, int rx, bool value) { + + if (m_receiverDataList[rx].agcLines == value) return; + m_receiverDataList[rx].agcLines = value; + + emit showAGCLinesStatusChanged(sender, m_receiverDataList[rx].agcLines, rx); +} + +int Settings::getAGCGain(int rx) { + + return m_receiverDataList[rx].acgGain; +} + +void Settings::setAGCGain(QObject *sender, int rx, int value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].acgGain == value) return; + m_receiverDataList[rx].acgGain = value; + //SETTINGS_DEBUG << "acgGain " << value; + emit agcGainChanged(sender, rx, value); +} + +void Settings::setAGCMaximumGain_dB(QObject *sender, int rx, qreal value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].agcMaximumGain_dB == value) return; + m_receiverDataList[rx].agcMaximumGain_dB = value; + + //SETTINGS_DEBUG << "agcMaximumGain_dB = " << m_receiverDataList[rx].agcMaximumGain_dB << " (sender: " << sender << ")"; + emit agcMaximumGainChanged_dB(sender, rx, value); +} + +qreal Settings::getAGCMaximumGain_dB(int rx) { + + return m_receiverDataList[rx].agcMaximumGain_dB; +} + +void Settings::setAGCFixedGain_dB(QObject *sender, int rx, qreal value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].agcFixedGain_dB == value) return; + m_receiverDataList[rx].agcFixedGain_dB = value; + + //SETTINGS_DEBUG << "m_receiverDataList[rx].agcFixedGain_dB = " << m_receiverDataList[rx].agcFixedGain_dB; + emit agcFixedGainChanged_dB(sender, rx, value); +} + +qreal Settings::getAGCFixedGain_dB(int rx) { + + return m_receiverDataList[rx].agcFixedGain_dB; +} + +void Settings::setAGCThreshold_dB(QObject *sender, int rx, qreal value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].acgThreshold_dB == value) return; + m_receiverDataList[rx].acgThreshold_dB = value; + + //SETTINGS_DEBUG << "acgThreshold = " << m_receiverDataList[rx].acgThreshold; + emit agcThresholdChanged_dB(sender, rx, value); +} + +void Settings::setAGCHangThresholdSlider(QObject *sender, int rx, qreal value) { + + emit agcHangThresholdSliderChanged(sender, rx, value); +} + +int Settings::getAGCHangThreshold(int rx) { + + return m_receiverDataList[rx].agcHangThreshold; +} + +void Settings::setAGCHangThreshold(QObject *sender, int rx, int value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].agcHangThreshold == value) return; + m_receiverDataList[rx].agcHangThreshold = value; + + //SETTINGS_DEBUG << "agcHangThreshold = " << m_receiverDataList[rx].agcHangThreshold; + emit agcHangThresholdChanged(sender, rx, value); +} + +int Settings::getAGCHangLeveldB(int rx) { + + return m_receiverDataList[rx].agcHangThreshold; +} + +void Settings::setAGCHangLevel_dB(QObject *sender, int rx, qreal value) { + + //QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].agcHangLevel == value) return; + m_receiverDataList[rx].agcHangLevel = value; + + //SETTINGS_DEBUG << "agcHangLevel = " << m_receiverDataList[rx].agcHangLevel; + emit agcHangLevelChanged_dB(sender, rx, value); +} + +void Settings::setAGCLineLevels(QObject *sender, int rx, qreal thresh, qreal hang) { + + if (m_currentReceiver != rx) return; + + m_receiverDataList[rx].agcHangLevel = hang; + //SETTINGS_DEBUG << "agcHangLevel = " << m_receiverDataList[rx].agcHangLevel; + + emit agcLineLevelsChanged(sender, rx, thresh, hang); +} + +void Settings::setAGCVariableGain_dB(QObject *sender, int rx, qreal value) { + + if (m_currentReceiver != rx) return; + + if (m_receiverDataList[rx].agcVariableGain == value) return; + m_receiverDataList[rx].agcVariableGain = value; + + SETTINGS_DEBUG << "agcVariableGain = " << m_receiverDataList[rx].agcVariableGain; + emit agcVariableGainChanged_dB(sender, rx, value); +} + +void Settings::setAGCAttackTime(QObject *sender, int rx, qreal value) { + + if (m_currentReceiver != rx) return; + + if (m_receiverDataList[rx].agcAttackTime == value) return; + m_receiverDataList[rx].agcAttackTime = value; + + SETTINGS_DEBUG << "agcAttackTime = " << m_receiverDataList[rx].agcAttackTime; + emit agcAttackTimeChanged(sender, rx, value); +} + +void Settings::setAGCDecayTime(QObject *sender, int rx, qreal value) { + + if (m_currentReceiver != rx) return; + + if (m_receiverDataList[rx].agcDecayTime == value) return; + m_receiverDataList[rx].agcDecayTime = value; + + SETTINGS_DEBUG << "agcDecayTime = " << m_receiverDataList[rx].agcDecayTime; + emit agcDecayTimeChanged(sender, rx, value); +} + +void Settings::setAGCHangTime(QObject *sender, int rx, qreal value) { + + if (m_currentReceiver != rx) return; + + if (m_receiverDataList[rx].agcHangTime == value) return; + m_receiverDataList[rx].agcHangTime = value; + + SETTINGS_DEBUG << "agcHangTime = " << m_receiverDataList[rx].agcHangTime; + emit agcHangTimeChanged(sender, rx, value); +} + +void Settings::setRXFilter(QObject *sender, int rx, qreal low, qreal high) { + + QMutexLocker locker(&settingsMutex); + + if (m_filterFrequencyLow == low && m_filterFrequencyHigh == high) return; + + m_filterFrequencyLow = low; + m_filterFrequencyHigh = high; + m_receiverDataList[rx].filterLo = low; + m_receiverDataList[rx].filterHi = high; + + emit filterFrequenciesChanged(sender, rx, m_filterFrequencyLow, m_filterFrequencyHigh); +} + +void Settings::setIQPort(QObject *sender, int rx, int port) { + + emit iqPortChanged(sender, rx, port); +} + +void Settings::setSpectrumBuffer(int rx, const qVectorFloat& buffer) { + + emit spectrumBufferChanged(rx, buffer); +} + +void Settings::setPostSpectrumBuffer(int rx, const float* buffer) { + + emit postSpectrumBufferChanged(rx, buffer); +} + +void Settings::setSMeterValue(int rx, float value) { + + emit sMeterValueChanged(rx, value); +} + +void Settings::setReceiverDataReady() { + + emit receiverDataReady(); +} + +void Settings::setSampleSize(QObject* sender, int rx, int size) { + + Q_UNUSED (sender) + + if (rx == 0) { + + SETTINGS_DEBUG << "set sample size to: " << size; + switch (size) { + + case 4096: + m_fft = 1; + break; + + case 8192: + m_fft = 2; + break; + + case 16384: + m_fft = 4; + break; + + case 32768: + m_fft = 8; + break; + } + + emit sampleSizeChanged(0, size); + } +} + +// Alex configuration: +// +// manual 0 +// bypassAll 1 +// amp6m 2 +// hpf1_5MHz 3 +// hpf6_5MHz 4 +// hpf9_5MHz 5 +// hpf13MHz 6 +// hpf20MHz 7 +// lpf160m 8 +// lpf80m 9 +// lpf60_40m 10 +// lpf30_20m 11 +// lpf17_15m 12 +// lpf12_10m 13 +// lpf6m 14 + +// m_alexConfig (qint16) +// +// 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +// | | | | | | | | | | | | | | | +// | | | | | | | | | | | | | | +-----Alex - manual HPF/LPF filter select (0 = disable, 1 = enable) +// | | | | | | | | | | | | | +------ Alex - Bypass all HPFs (0 = disable, 1 = enable)* +// | | | | | | | | | | | | +-------- Alex - 6M low noise amplifier (0 = disable, 1 = enable)* +// | | | | | | | | | | | +---------- Alex - select 1.5MHz HPF (0 = disable, 1 = enable)* +// | | | | | | | | | | +------------ Alex - select 6.5MHz HPF (0 = disable, 1 = enable)* +// | | | | | | | | | +-------------- Alex - select 9.5MHz HPF (0 = disable, 1 = enable)* +// | | | | | | | | +---------------- Alex - select 13MHz HPF (0 = disable, 1 = enable)* +// | | | | | | | +------------------ Alex - select 20MHz HPF (0 = disable, 1 = enable)* +// | | | | | | +-------------------- Alex - select 160m LPF (0 = disable, 1 = enable)* +// | | | | | +---------------------- Alex - select 80m LPF (0 = disable, 1 = enable)* +// | | | | +------------------------ Alex - select 60/40m LPF (0 = disable, 1 = enable)* +// | | | +-------------------------- Alex - select 30/20m LPF (0 = disable, 1 = enable)* +// | | +---------------------------- Alex - select 17/15m LPF (0 = disable, 1 = enable)* +// | +------------------------------ Alex - select 12/10m LPF (0 = disable, 1 = enable)* +// +-------------------------------- Alex - select 6m LPF (0 = disable, 1 = enable)* + +void Settings::setAlexConfiguration(QObject *sender, quint16 conf) { + + Q_UNUSED (sender) + + QMutexLocker locker(&settingsMutex); + m_alexConfig = conf; + + emit alexConfigurationChanged(m_alexConfig); +} + +void Settings::setAlexHPFLoFrequencies(int filter, long value) { + + m_HPFLoFrequencyList[filter] = value; +} + +void Settings::setAlexHPFHiFrequencies(int filter, long value) { + + m_HPFHiFrequencyList[filter] = value; +} + +void Settings::setAlexLPFLoFrequencies(int filter, long value) { + + m_LPFLoFrequencyList[filter] = value; +} + +void Settings::setAlexLPFHiFrequencies(int filter, long value) { + + m_LPFHiFrequencyList[filter] = value; +} + +/* + * Alex state encoding + * We use the same encoding as in the KISS Konsole by George Byrkit, K9TRV + * AA.TT.BBB.RR + * AA is RX Attenuator + * TT is TX antenna selection (0 is NOT valid!) + * BBB is RX special selection + * RR is TX antenna to use for RX (0 is NOT valid!) + * + */ +void Settings::setAlexState(QObject *sender, int pos, int value) { + + Q_UNUSED (sender) + + if (m_alexStates.length() != MAX_BANDS) + return; + else { + + if (m_alexStates.at(pos) == value) + return; + + int state = checkAlexState(value); + //qDebug() << "alex state at pos: " << pos <<" = " << state; + + m_alexStates.replace(pos, state); + + emit alexStateChanged((HamBand) pos, m_alexStates); + } +} + +void Settings::setAlexState(QObject *sender, int value) { + + Q_UNUSED(sender) + + HamBand band = m_receiverDataList[m_currentReceiver].hamBand; + + setAlexState(this, band, value); +} + +void Settings::setAlexStates(QObject *sender, const QList &states) { + + Q_UNUSED (sender) + + if (m_alexStates == states) return; + + m_alexStates = states; + + emit alexStatesChanged(m_alexStates); +} + +// check Alex state - adapted from KISS Konsole, (c) George Byrkit, K9TRV +int Settings::checkAlexState(int state) { + + if ((state & 0x3) == 0) { + + // if rx antenna selector is 0, set it to 1 + state |= 1; + } + + if (((state >> 5) & 0x3) == 0) { + + // if tx antenna selector is 0, set it to 1 + state |= 33; + } + return state; +} + +void Settings::setAlexToManual(QObject *sender, bool value) { + + //QMutexLocker locker(&settingsMutex); + + emit alexManualStateChanged(sender, value); +} + +void Settings::setRxJ6Pin(QObject *sender, HamBand band, int value) { + + Q_UNUSED (sender) + + if (m_rxJ6pinList.length() != MAX_BANDS-1) return; + if (m_rxJ6pinList[band] == value) return; + + m_rxJ6pinList[band] = value; + + emit rxJ6PinsChanged(m_rxJ6pinList); +} + +void Settings::setRxJ6Pins(QObject * sender, const QList &states) { + + Q_UNUSED (sender) + + //if (m_rxJ6pinList == states) return; + + m_rxJ6pinList = states; + + emit rxJ6PinsChanged(m_rxJ6pinList); +} + +void Settings::setTxJ6Pin(QObject *sender, HamBand band, int value) { + + Q_UNUSED (sender) + + if (m_txJ6pinList.length() != MAX_BANDS-1) return; + if (m_txJ6pinList[band] == value) return; + + m_txJ6pinList[band] = value; + + emit txJ6PinsChanged(m_txJ6pinList); +} + +void Settings::setTxJ6Pins(QObject * sender, const QList &states) { + + Q_UNUSED (sender) + + //if (m_txJ6pinList == states) return; + + m_txJ6pinList = states; + + emit txJ6PinsChanged(m_txJ6pinList); +} + +void Settings::setPennyOCEnabled(QObject *sender, bool value) { + + Q_UNUSED (sender) + + if (m_pennyOCEnabled == value) return; + + m_pennyOCEnabled = value; + + emit pennyOCEnabledChanged(m_pennyOCEnabled); +} + +//************************************** +//************************************** +// OpenCL stuff + +//void Settings::setOpenCLDevices(QList devices) { +// +// m_clDevices = devices; +//} + +//void Settings::setCudaPresence(bool value) { +// +// m_cudaPresence = value; +//} +// +//void Settings::setCudaDevices(int value) { +// +// QMutexLocker locker(&mutex); +// if (m_cuda_devices == value) return; +// m_cuda_devices = value; +// locker.unlock(); +// +// emit cudaDevicesChanged(this, value); +//} +// +//void Settings::setCudaDriver(QObject *sender, int value) { +// +// QMutexLocker locker(&mutex); +// if (m_cuda_driver_version == value) return; +// m_cuda_driver_version = value; +// locker.unlock(); +// +// emit cudaDriverChanged(sender, value); +//} +// +//void Settings::setCudaRuntime(QObject *sender, int value) { +// +// QMutexLocker locker(&mutex); +// if (m_cuda_runtime_version == value) return; +// m_cuda_runtime_version = value; +// locker.unlock(); +// +// emit cudaRuntimeChanged(sender, value); +//} +// +//void Settings::setCurrentCudaDevice(QObject *sender, int value) { +// +// QMutexLocker locker(&mutex); +// if (m_current_cuda_device == value) return; +// m_current_cuda_device = value; +// locker.unlock(); +// +// emit cudaCurrentDeviceChanged(sender, value); +//} +// +//void Settings::setCudaLastDevice(QObject *sender, int value) { +// +// QMutexLocker locker(&mutex); +// if (m_cudaLastDevice == value) return; +// m_cudaLastDevice = value; +// locker.unlock(); +// +// emit cudaLastDeviceChanged(sender, value); +//} + +void Settings::setFreqRulerPosition(QObject *sender, int rx, float position) { + + Q_UNUSED (sender) + + if (position < 0) position = 0; + if (position > 1) position = 1; + + m_receiverDataList[rx].freqRulerPosition = position; + emit freqRulerPositionChanged(this, rx, position); +} + +//********************************************************************************** +// audio settings + +void Settings::setAudioFormat(QObject *sender, const QAudioFormat &format) { + + Q_UNUSED (sender) + + QMutexLocker locker(&settingsMutex); + + //if (m_format == format) return; + m_format = format; + + emit audioFormatChanged(sender, m_format); +} + +void Settings::setAudioPosition(QObject *sender, qint64 position) { + + emit audioPositionChanged(sender, position); +} + +void Settings::setAudioBuffer(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer) { + + emit audioBufferChanged(sender, position, length, buffer); +} + + +//********************************************************************************** +// wideband data & options + +void Settings::setWidebandSpectrumBuffer(const qVectorFloat &buffer) { + + emit widebandSpectrumBufferChanged(buffer); +} + +void Settings::resetWidebandSpectrumBuffer() { + + emit widebandSpectrumBufferReset(); +} + +void Settings::setWidebandOptions(QObject* sender, TWideband options) { + + QMutexLocker locker(&settingsMutex); + + m_widebandOptions = options; + + emit widebandOptionsChanged(sender, m_widebandOptions); +} + +void Settings::setWidebandStatus(QObject* sender, bool value) { + + QMutexLocker locker(&settingsMutex); + + if (m_widebandOptions.wideBandDisplayStatus == value) return; + m_widebandOptions.wideBandDisplayStatus = value; + + emit widebandStatusChanged(sender, m_widebandOptions.wideBandDisplayStatus); +} + +void Settings::setWidebandData(QObject* sender, bool value) { + + QMutexLocker locker(&settingsMutex); + + if (m_widebandOptions.wideBandData == value) return; + m_widebandOptions.wideBandData = value; + + emit widebandDataChanged(sender, m_widebandOptions.wideBandData); +} + +void Settings::setWidebandBuffers(QObject *sender, int value) { + + Q_UNUSED(sender) + + QMutexLocker locker(&settingsMutex); + m_widebandOptions.numberOfBuffers = value; +} + +void Settings::setWidebanddBmScaleMin(QObject *sender, qreal value) { + + QMutexLocker locker(&settingsMutex); + + if (m_widebandOptions.dBmWBScaleMin == value) return; + m_widebandOptions.dBmWBScaleMin = value; + + locker.unlock(); + emit widebanddBmScaleMinChanged(sender, m_widebandOptions.dBmWBScaleMin); +} + +void Settings::setWidebanddBmScaleMax(QObject *sender, qreal value) { + + QMutexLocker locker(&settingsMutex); + + if (m_widebandOptions.dBmWBScaleMax == value) return; + m_widebandOptions.dBmWBScaleMax = value; + + locker.unlock(); + emit widebanddBmScaleMaxChanged(sender, m_widebandOptions.dBmWBScaleMax); +} + +void Settings::setWideBandRulerPosition(QObject *sender, float position) { + + if (m_widebandOptions.scalePosition == position) return; + if (position < 0) position = 0; + if (position > 1) position = 1; + m_widebandOptions.scalePosition = position; + + emit wideBandScalePositionChanged(sender, m_widebandOptions.scalePosition); +} + + +//********************************************************************************** +// chirp signal settings + +void Settings::switchToChirpSignalMode(QObject *sender) { + + emit chirpSignalModeChanged(sender); +} + +void Settings::setLowerChirpFreq(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_lowerChirpFreq == value) return; + if (m_lowerChirpFreq >= m_upperChirpFreq) + m_lowerChirpFreq = m_upperChirpFreq; + else + m_lowerChirpFreq = value; + + emit lowerChirpFreqChanged(this, m_lowerChirpFreq); +} + +void Settings::setUpperChirpFreq(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_upperChirpFreq == value) return; + if (m_lowerChirpFreq >= m_upperChirpFreq) + m_upperChirpFreq = m_lowerChirpFreq; + else + m_upperChirpFreq = value; + + emit upperChirpFreqChanged(this, m_upperChirpFreq); +} + +void Settings::setChirpAmplitude(qreal value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpAmplitude == value) return; + m_chirpAmplitude = value; + + emit chirpAmplitudeChanged(this, m_chirpAmplitude); +} + +void Settings::setChirpSamplingFreq(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpSamplingFreq == value) return; + m_chirpSamplingFreq = value; + + emit chirpSamplingFreqChanged(this, m_chirpSamplingFreq); +} + +void Settings::setChirpBufferDurationUs(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpBufferDurationUs == (qint64)value) return; + m_chirpBufferDurationUs = (qint64)(1000 * value); + + emit chirpBufferDurationUsChanged(this, m_chirpBufferDurationUs); +} + +void Settings::setChirpRepetitionTimes(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpRepetitionTimes == value) return; + m_chirpRepetitionTimes = value; + + emit chirpRepetitionTimesChanged(this, m_chirpRepetitionTimes); +} + +void Settings::setChirpReceiver(bool value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpReceiverOn == value) return; + m_chirpReceiverOn = value; + + emit chirpReceiverChanged(this, m_chirpReceiverOn); +} + +void Settings::setChirpAvgLength(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpAvgLength == value) return; + m_chirpAvgLength = value; + + emit chirpAvgLengthChanged(m_chirpAvgLength); +} + +void Settings::setChirpFFTShow(bool value) { + + QMutexLocker locker(&settingsMutex); + + if (m_showChirpFFT == value) return; + m_showChirpFFT = value; + + emit chirpFFTShowChanged(m_showChirpFFT); +} + +void Settings::setChirpUSB(bool value) { + + QMutexLocker locker(&settingsMutex); + + if (m_chirpUSB == value) return; + m_chirpUSB = value; + + emit chirpSidebandChanged(m_chirpUSB); +} + +//void Settings::setChirpDownSampleRate(int value) { +// +// if (m_chirpDownSampleRate == value) return; +// m_chirpDownSampleRate = value; +//} + +void Settings::setChirpBuffer(qint64 length, const QList &buffer) { + + emit chirpBufferChanged(length, buffer); +} + +void Settings::setChirpSpectrumBuffer(int sampleRate, qint64 length, const float *buffer) { + + emit chirpSpectrumBufferChanged(sampleRate, length, buffer); +} + +void Settings::setChirpSpectrum(qint64 position, qint64 length, const FrequencySpectrum &spectrum) { + + emit chirpSpectrumChanged(position, length, spectrum); +} + +void Settings::setChirpSpectrumList(const QList &spectrumList) { + + emit chirpSpectrumListChanged(spectrumList); +} + +void Settings::setChirpFilterLowerFrequency(int value) { + + if (m_chirpFilterLowerFrequency == value) return; + m_chirpFilterLowerFrequency = value; + + emit chirpFilterLowerFrequencyChanged(m_chirpFilterLowerFrequency); +} + +void Settings::setChirpFilterUpperFrequency(int value) { + + if (m_chirpFilterUpperFrequency == value) return; + m_chirpFilterUpperFrequency = value; + + emit chirpFilterUpperFrequencyChanged(m_chirpFilterUpperFrequency); +} + +//******************************** + +void Settings::setSpectrumSize(QObject *sender, int value) { + + if (m_spectrumSize == value) return; + + m_spectrumSize = value; + emit spectrumSizeChanged(sender, m_spectrumSize); +} + +void Settings::moveDisplayWidget(int value) { + + emit displayWidgetHeightChanged(value); +} + + +//********************************* +// color stuff + +void Settings::setPanadapterColors(TPanadapterColors type) { + + if (type.panBackgroundColor != m_panadapterColors.panBackgroundColor) + m_panadapterColors.panBackgroundColor = type.panBackgroundColor; + + if (type.waterfallColor != m_panadapterColors.waterfallColor) + m_panadapterColors.waterfallColor = type.waterfallColor; + + if (type.panLineColor != m_panadapterColors.panLineColor) + m_panadapterColors.panLineColor = type.panLineColor; + + if (type.panLineFilledColor != m_panadapterColors.panLineFilledColor) + m_panadapterColors.panLineFilledColor = type.panLineFilledColor; + + if (type.panSolidTopColor != m_panadapterColors.panSolidTopColor) + m_panadapterColors.panSolidTopColor = type.panSolidTopColor; + + if (type.panSolidBottomColor != m_panadapterColors.panSolidBottomColor) + m_panadapterColors.panSolidBottomColor = type.panSolidBottomColor; + + if (type.wideBandLineColor != m_panadapterColors.wideBandLineColor) + m_panadapterColors.wideBandLineColor = type.wideBandLineColor; + + if (type.wideBandFilledColor != m_panadapterColors.wideBandFilledColor) + m_panadapterColors.wideBandFilledColor = type.wideBandFilledColor; + + if (type.wideBandSolidBottomColor != m_panadapterColors.wideBandSolidTopColor) + m_panadapterColors.wideBandSolidTopColor = type.wideBandSolidTopColor; + + if (type.wideBandSolidBottomColor != m_panadapterColors.wideBandSolidBottomColor) + m_panadapterColors.wideBandSolidBottomColor = type.wideBandSolidBottomColor; + + if (type.distanceLineColor != m_panadapterColors.distanceLineColor) + m_panadapterColors.distanceLineColor = type.distanceLineColor; + + if (type.distanceLineFilledColor != m_panadapterColors.distanceLineFilledColor) + m_panadapterColors.distanceLineFilledColor = type.distanceLineFilledColor; + + if (type.panCenterLineColor != m_panadapterColors.panCenterLineColor) + m_panadapterColors.panCenterLineColor = type.panCenterLineColor; + + if (type.gridLineColor != m_panadapterColors.gridLineColor) + m_panadapterColors.gridLineColor = type.gridLineColor; + + emit panadapterColorChanged(); +} + +void Settings::setFramesPerSecond(QObject* sender, int rx, int value) { + + Q_UNUSED(sender) + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).framesPerSecond != value) + m_receiverDataList[rx].framesPerSecond = value; + + emit framesPerSecondChanged(this, rx, m_receiverDataList[rx].framesPerSecond); +} + +int Settings::getFramesPerSecond(int rx) { + + return m_receiverDataList.at(rx).framesPerSecond; +} + +void Settings::setSpectrumAveraging(QObject* sender, int rx, bool value) { + + if (rx == -1) + { + m_widebandOptions.averagingCnt = value; + } + else + { + m_receiverDataList[rx].spectrumAveraging = value; + } + + //SETTINGS_DEBUG << "Averaging for Rx " << rx << " : " << value; + emit spectrumAveragingChanged(sender, rx, value); +} + +bool Settings::getSpectrumAveraging(int rx) { + + if (rx == -1) + return m_widebandOptions.averaging; + else + return m_receiverDataList[rx].spectrumAveraging; +} + +int Settings::getSpectrumAveragingCnt(int rx) { + + if (rx == -1) + return m_widebandOptions.averagingCnt; + else + return m_receiverDataList[rx].averagingCnt; +} + +void Settings::setSpectrumAveragingCnt(QObject *sender, int rx, int value) { + + QMutexLocker locker(&settingsMutex); + + //if (m_specAveragingCnt == value) return + if (rx == -1) + m_widebandOptions.averagingCnt = value; + else + m_receiverDataList[rx].averagingCnt = value; + + emit spectrumAveragingCntChanged(sender, rx, value); +} + + + +void Settings::setPanGrid(bool value, int rx) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).panGrid == value) return; + m_receiverDataList[rx].panGrid = value; + + emit panGridStatusChanged(m_receiverDataList.at(rx).panGrid, rx); +} + +bool Settings::getPanGridStatus(int rx) { + + return m_receiverDataList[rx].panGrid; +} + +void Settings::setPeakHold(bool value, int rx) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).peakHold == value) return; + m_receiverDataList[rx].peakHold = value; + + emit peakHoldStatusChanged(m_receiverDataList.at(rx).peakHold, rx); +} + +bool Settings::getPeakHoldStatus(int rx) { + + return m_receiverDataList.at(rx).peakHold; +} + +void Settings::setPanLocked(bool value, int rx) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).panLocked == value) return; + m_receiverDataList[rx].panLocked = value; + + emit panLockedStatusChanged(m_receiverDataList.at(rx).panLocked, rx); +} + +bool Settings::getPanLockedStatus(int rx) { + + return m_receiverDataList[rx].panLocked; +} + +void Settings::setClickVFO(bool value, int rx) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).clickVFO == value) return; + m_receiverDataList[rx].clickVFO = value; + + emit clickVFOStatusChanged(m_receiverDataList.at(rx).clickVFO, rx); +} + +bool Settings::getClickVFOStatus(int rx) { + + return m_receiverDataList[rx].clickVFO; +} + +void Settings::setHairCross(bool value, int rx) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList.at(rx).hairCross == value) return; + m_receiverDataList[rx].hairCross = value; + + emit hairCrossStatusChanged(m_receiverDataList.at(rx).hairCross, rx); +} + +bool Settings::getHairCrossStatus(int rx) { + + return m_receiverDataList[rx].hairCross; +} + +void Settings::setWaterfallTime(int rx, int value) { + + Q_UNUSED(rx) + Q_UNUSED(value) + + QMutexLocker locker(&settingsMutex); + + //if (m_receiverDataList[rx].waterfallTime == value) return; + //m_receiverDataList[rx].waterfallTime = value; + + //emit waterfallTimeChanged(rx, value); +} + +void Settings::setWaterfallOffesetLo(int rx, int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].waterfallOffsetLo == value) return; + m_receiverDataList[rx].waterfallOffsetLo = value; + + emit waterfallOffesetLoChanged(rx, value); +} + +void Settings::setWaterfallOffesetHi(int rx, int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_receiverDataList[rx].waterfallOffsetHi == value) return; + m_receiverDataList[rx].waterfallOffsetHi = value; + + emit waterfallOffesetHiChanged(rx, value); +} + +void Settings::setSMeterHoldTime(int value) { + + QMutexLocker locker(&settingsMutex); + + if (m_sMeterHoldTime == value) return; + m_sMeterHoldTime = value; + + emit sMeterHoldTimeChanged(m_sMeterHoldTime); +} + +void Settings::setdBmPanScaleMin(int rx, qreal value) { + + QMutexLocker locker(&settingsMutex); + + HamBand band = m_receiverDataList.at(m_currentReceiver).hamBand; + m_receiverDataList[rx].dBmPanScaleMinList[band] = value; + + emit dBmScaleMinChanged(rx, value); +} + +void Settings::setdBmPanScaleMax(int rx, qreal value) { + + QMutexLocker locker(&settingsMutex); + + HamBand band = m_receiverDataList.at(m_currentReceiver).hamBand; + m_receiverDataList[rx].dBmPanScaleMaxList[band] = value; + + emit dBmScaleMaxChanged(rx, value); +} + +void Settings::setdBmDistScaleMin(qreal value) { + + Q_UNUSED(value) +} + +void Settings::setdBmDistScaleMax(qreal value) { + + Q_UNUSED(value) +} + +// ********************************************************************** + +void Settings::showRadioPopupWidget() { + + if (m_radioPopupVisible) + m_radioPopupVisible = false; + else + m_radioPopupVisible = true; + + emit showRadioPopupChanged(m_radioPopupVisible); +} diff --git a/Source/src/cusdr_settings.h b/Source/src/cusdr_settings.h new file mode 100644 index 0000000..1787840 --- /dev/null +++ b/Source/src/cusdr_settings.h @@ -0,0 +1,1586 @@ +/** +* @file cusdr_settings.h +* @brief settings header file for cuSDR +* @author by Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-11-18 +*/ + +/* + * Copyright 2010, 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef CUSDR_SETTINGS_H +#define CUSDR_SETTINGS_H + +//#define DEBUG + + +#include +#include +#include +#include +#include +#include +#include + +#include "cusdr_hamDatabase.h" + +// test for OpenCL +//#include "CL/qclcontext.h" + + +// ************************************** +// messages + +#define BANDSCOPE_IN_USE "Error: bandscope in use" +#define BANDSCOPE_NOT_OWNER "Error: Not owner of bandscope" + +#define RECEIVER_INVALID "Error: Invalid Receiver" +#define RECEIVER_IN_USE "Error: Receiver in use" +#define RECEIVER_NOT_OWNER "Error: Not owner of receiver" + +#define CLIENT_ATTACHED "Error: Client is already attached to receiver" +#define CLIENT_DETACHED "Error: Client is not attached to receiver" + +#define INVALID_COMMAND "Error: Invalid Command" + +#define OK "OK" + +// ************************************** +// constants + +#define ONEPI 3.14159265358979323846264338328 +#define TWOPI 6.28318530717958647692528676656 +//#define AGCOFFSET 33.0 + +#define MAXFREQUENCY 961440000 +#define MAXHPFREQUENCY 61440000 +#define MINDBM -180 +#define MAXDBM 10 +#define MINDISTDBM -150 +#define MAXDISTDBM 150 +#define MAX_FFTSIZE 262144 + +// ************************************** +// receiver settings + +#define MAX_RECEIVERS 8 +#define MAX_BANDS 14 +#define BUFFER_SIZE 1024 +#define SAMPLE_BUFFER_SIZE 4096 +#define BANDSCOPE_BUFFER_SIZE 4096 + +#define SMALL_PACKETS +#define BIGWIDEBANDSIZE 16384 +//#define BIGWIDEBANDSIZE 32768 +#define SMALLWIDEBANDSIZE 4096 + + +// ************************************** +// IO buffer, command & control settings + +#define IO_BUFFERS 16 +#define IO_BUFFER_SIZE 512 +#define IO_HEADER_SIZE 8 +#define IO_AUDIOBUFFER_SIZE 8192 + +#define SYNC 0x7F + +#define IQ_DATAGRAM_BUFFERS 512 +#define AUDIO_DATAGRAM_BUFFERS 512 + +#define METIS_HEADER_SIZE 8 +#define METIS_DATA_SIZE 1032 + +#define ALEX_PARAMETERS 15 + +// uncomment to compile code that allows for SYNC error recovery +#define RESYNC + +#define MOX_DISABLED 0x00 +#define MOX_ENABLED 0x01 + +#define ATLAS_10MHZ_SOURCE 0x00 +#define PENELOPE_10MHZ_SOURCE 0x04 +#define MERCURY_10MHZ_SOURCE 0x08 +#define PENELOPE_122_88MHZ_SOURCE 0x00 +#define MERCURY_122_88MHZ_SOURCE 0x10 +#define PENELOPE_PRESENT 0x20 +#define MERCURY_PRESENT 0x40 +#define MIC_SOURCE_PENELOPE 0x80 + +//#define MIC_SOURCE_JANUS 0x00 +//#define CONFIG_NONE 0x00 +//#define CONFIG_BOTH 0x60 + + +//#define SPEED_48KHZ 0x00 +//#define SPEED_96KHZ 0x01 +//#define SPEED_192KHZ 0x02 + +#define MODE_CLASS_E 0x01 +#define MODE_OTHERS 0x00 + +#define ALEX_ATTENUATION_0DB 0x00 +#define ALEX_ATTENUATION_10DB 0x01 +#define ALEX_ATTENUATION_20DB 0x02 +#define ALEX_ATTENUATION_30DB 0x03 +#define LT2208_GAIN_OFF 0x00 +#define LT2208_GAIN_ON 0x04 +#define LT2208_DITHER_OFF 0x00 +#define LT2208_DITHER_ON 0x08 +#define LT2208_RANDOM_OFF 0x00 +#define LT2208_RANDOM_ON 0x10 + +//#define SIMPLEX 0x00 +//#define DUPLEX 0x04 + + +// ************************************** +// Metis definitions + +//#define MAX_METIS_CARDS 10 +//#define DISCOVER_IDLE 0 +//#define DISCOVER_SENT 1 +#define DEVICE_PORT 1024 +#define DATA_PORT 8886 + +// ************************************** +// Audio definitions + +#define WAVEFORM_WINDOW_DURATION 250000 +#define WAVEFORM_TILE_LENGTH 4096 + +//#include "cusdr_about.h" +#include "AudioEngine/cusdr_fspectrum.h" +#include "Util/cusdr_queue.h" + + +// ************************************** +// Server modes + +namespace QSDR { + + enum _Error { + + NoError, + NotImplemented, + HwIOError, + ServerModeError, + OpenError, + DataReceiverThreadError, + DataProcessThreadError, + WideBandDataProcessThreadError, + AudioThreadError, + ChirpDataProcessThreadError, + UnderrunError, + FirmwareError, + FatalError + }; + + enum _DataEngineState { + + DataEngineDown, + DataEngineUp + }; + + enum _DSPCore { + + QtDSP, + CudaDSP, + ExternalDSP + }; + + enum _ServerMode { + + NoServerMode, + SDRMode, + ChirpWSPR, + ChirpWSPRFile, + DemoMode + }; + + enum _HWInterfaceMode { + + NoInterfaceMode, + Metis, + Hermes + }; +} + +Q_DECLARE_METATYPE(QSDR::_Error) +Q_DECLARE_METATYPE(QSDR::_DataEngineState) +Q_DECLARE_METATYPE(QSDR::_ServerMode) +Q_DECLARE_METATYPE(QSDR::_HWInterfaceMode) + + +// ************************************** +enum { + prefixNothing = 0, /*!< No prefix. */ + + /* SI units. */ + prefixKilo = 1, /*!< Kilo prefix 1000^1 = 10^3. */ + prefixMega = 2, /*!< Mega prefix 1000^2 = 10^6. */ + prefixGiga = 3, /*!< Giga prefix 1000^3 = 10^9. */ + prefixTera = 4, /*!< Tera prefix 1000^4 = 10^12. */ + prefixPeta = 5, /*!< Peta prefix 1000^5 = 10^15. */ + prefixExa = 6, /*!< Exa prefix 1000^6 = 10^18. */ + prefixZetta = 7, /*!< Zetta prefix 1000^7 = 10^21. */ + prefixYotta = 8, /*!< Yotta prefix 1000^8 = 10^24. */ + prefixSiMax = prefixYotta, + + /* IEC 60027 units. */ + prefixKibi = 1, /*!< Kibi prefix 1024^1 = 2^10. */ + prefixMebi = 2, /*!< Mebi prefix 1024^2 = 2^20. */ + prefixGibi = 3, /*!< Gibi prefix 1024^3 = 2^30. */ + prefixTebi = 4, /*!< Tebi prefix 1024^4 = 2^40. */ + prefixPebi = 5, /*!< Pebi prefix 1024^5 = 2^50. */ + prefixExbi = 6, /*!< Exbi prefix 1024^6 = 2^60. */ + prefixZebi = 7, /*!< Zebi prefix 1024^7 = 2^70. */ + prefixYobi = 8, /*!< Yobi prefix 1024^8 = 2^80. */ + prefixIecMax = prefixYobi, +}; + + +// ************************************** +// type definitions + +typedef QVector qVectorFloat; + +typedef struct _frequency { + + int freqMHz; + int freqkHz; + + long frequency; + +} TFrequency; + +typedef struct _hpsdrDevices { + + bool mercuryPresence; + bool penelopePresence; + bool pennylanePresence; + bool excaliburPresence; + bool alexPresence; + bool hermesPresence; + bool metisPresence; + + int mercuryFWVersion; + int penelopeFWVersion; + int pennylaneFWVersion; + int excaliburFWVersion; + int alexFWVersion; + int hermesFWVersion; + int metisFWVersion; + +} THPSDRDevices; + +typedef struct _ccParameterRx { + + THPSDRDevices devices; + + uchar roundRobin; // roundRobin is varied in a round-robin fashion in order to decode + // all values which are sent in sequence. + + bool ptt; // PTT (1 = active, 0 = inactive), GPIO[23]= Ozy J8-8, Hermes J16-1 + bool dash; // DASH (1 = active, 0 = inactive), GPIO[21]= Ozy J8-6, Hermes J6-2 + bool dot; // DOT (1 = active, 0 = inactive), GPIO[22]= Ozy J8-7, Hermes J6-3 + bool lt2208; // LT2208 Overflow (1 = active, 0 = inactive) + bool hermesI01; // Hermes I01 (0 = active, 1 = inactive) + bool hermesI02; // Hermes I02 (0 = active, 1 = inactive) + bool hermesI03; // Hermes I03 (0 = active, 1 = inactive) + bool hermesI04; // Hermes I04 (0 = active, 1 = inactive) + bool cyclopsPLL; // Cyclops PLL locked (0 = unlocked, 1 = locked) + bool cyclops; // Cyclops - Mercury frequency changed, bit toggles + + //int mercuryFirmwareVersion; // Mercury firmware version + //int penelopeFirmwareVersion; // Penelope firmware version + //int networkDeviceFirmwareVersion; // Metis/Hermes firmware version + + quint16 ain1; // Forward Power from Alex or Apollo + quint16 ain2; // Reverse Power from Alex or Apollo + quint16 ain3; // AIN3 from Penny or Hermes + quint16 ain4; // AIN4 from Penny or Hermes + quint16 ain5; // Forward Power from Penelope or Hermes + quint16 ain6; // AIN6,13.8v supply on Hermes + + bool mercury1_LT2208; //Mercury 1 LT2208 Overflow (1 = active, 0 = inactive) + bool mercury2_LT2208; //Mercury 2 LT2208 Overflow (1 = active, 0 = inactive) + bool mercury3_LT2208; //Mercury 3 LT2208 Overflow (1 = active, 0 = inactive) + bool mercury4_LT2208; //Mercury 4 LT2208 Overflow (1 = active, 0 = inactive) + + +} TCCParameterRx; + +typedef struct _ccParameterTx { + + bool mox; + bool ptt; + bool lineIn; + bool micGain20dB; + bool pennyOCenabled; + bool vnaMode; + + uchar clockByte; + uchar timeStamp; + uchar commonMercuryFrequencies; + + int hpsdr10MhzSource; + int hpsdr122_88MhzSource; + int hpsdrConfig; + int duplex; + int mercuryAttenuator; + int dither; + int random; + int currentAlexState; + + HamBand currentBand; + + QList mercuryAttenuators; + QList alexStates; + //QList alexConfiguration; + quint16 alexConfig; + QList rxJ6pinList; + QList txJ6pinList; + +} TCCParameterTx; + +typedef struct _hpsdrParameter { + + uchar control_in[5]; + uchar control_out[5]; + + QByteArray ccIn; + QByteArray ccOut; + + uchar output_buffer[IO_BUFFER_SIZE]; + //float in_buffer[2*BUFFER_SIZE]; + float out_buffer[2*BUFFER_SIZE]; + + qVectorFloat wbWindow; + + //CPX cpxIn; + //CPX cpxOut; + //CPX cpxTmp; + + QByteArray audioDatagram; + + QHQueue iq_queue; + QHQueue au_queue; + QHQueue wb_queue; + QHQueue > chirp_queue; + QHQueue > data_queue; + + QList inputBuffer; + + QList clientList; + + QMutex mutex; + QMutex networkIOMutex; + + QWaitCondition devicefound; + //QMutex iqMutex; + + QHostAddress hpsdrDeviceIPAddress; + QString hpsdrDeviceName; + + TCCParameterRx ccRx; + TCCParameterTx ccTx; + + int samplerate; + int speed; + int outputMultiplier; + + int metisFW; + int hermesFW; + int mercuryFW; + int penelopeFW; + int pennylaneFW; + + int clients; + int current_client; + int receivers; + int currentReceiver; + int audio_rx; + int timing; + + int currentMetisCard; + + //int hpsdr_10MhzSource; + //int hpsdr_122_88MhzSource; + int mic_source; + int rxClass; + int rx_freq_change; + int tx_freq_change; + + float mic_gain; + float mic_left_buffer[BUFFER_SIZE]; + float mic_right_buffer[BUFFER_SIZE]; + + qreal penelopeForwardVolts; + qreal penelopeForwardPower; + qreal alexForwardVolts; + qreal alexForwardPower; + qreal alexReverseVolts; + qreal alexReversePower; + qreal ain3Volts; + qreal ain4Volts; + qreal supplyVolts; + + bool rcveIQ_toggle; + bool sendIQ_toggle; + bool timeStamp; + bool mute; + + qint16 audiofileChannels; + +} THPSDRParameter; + +typedef struct _networkDeviceCard { + + QHostAddress ip_address; + char mac_address[18]; + int boardID; + QString boardName; + +} TNetworkDevicecard; + +typedef enum _panGraphicsMode { + + Line, // 0 + FilledLine, // 1 + Solid // 2 + +} PanGraphicsMode; + +typedef enum _waterfallColorMode { + + Simple, // 0 + Enhanced // 1 + +} WaterfallColorMode; + +Q_DECLARE_METATYPE (TNetworkDevicecard) +Q_DECLARE_METATYPE (QList) + +typedef struct _receiver { + + QSDR::_DSPCore dspCore; + + HamBand hamBand; + HamBand lastHamBand; + DSPMode dspMode; + AGCMode agcMode; + TDefaultFilterMode defaultFilterMode; + PanGraphicsMode panMode; + WaterfallColorMode waterfallMode; + + QList lastCenterFrequencyList; + QList lastVfoFrequencyList; + QList mercuryAttenuators; + QList dBmPanScaleMinList; + QList dBmPanScaleMaxList; + QList dspModeList; + + bool hangEnabled; + bool agcLines; + bool panLocked; + bool spectrumAveraging; + bool hairCross; + bool panGrid; + bool peakHold; + bool clickVFO; + + long ctrFrequency; + long vfoFrequency; + long ncoFrequency; + + float freqRulerPosition; + float audioVolume; + + qreal mouseWheelFreqStep; + qreal filterLo; + qreal filterHi; + qreal agcSlope; + qreal acgGain; + qreal acgThreshold_dB; + qreal agcHangThreshold; + qreal agcHangLevel; + qreal agcMaximumGain_dB; + qreal agcAttackTime; + qreal agcDecayTime; + qreal agcHangTime; + qreal agcFixedGain_dB; + qreal agcVariableGain; + + int sampleRate; + int framesPerSecond; + int waterfallOffsetLo; + int waterfallOffsetHi; + int averagingCnt; + +} TReceiver; + +typedef struct _wideband { + + PanGraphicsMode panMode; + + bool wideBandData; + bool wideBandDisplayStatus; + bool averaging; + + int numberOfBuffers; + int averagingCnt; + + float scalePosition; + + qreal dBmWBScaleMin; + qreal dBmWBScaleMax; + +} TWideband; + +typedef struct _transmitter { + + QSDR::_DSPCore dspCore; + + HamBand hamBand; + DSPMode dspMode; + AGCMode agcMode; + TDefaultFilterMode defaultFilterMode; + + bool txAllowed; + long frequency; + + float audioVolume; + +} TTransmitter; + +typedef struct t_panadapterColors { + + QColor panBackgroundColor; + QColor waterfallColor; + QColor panLineColor; + QColor panLineFilledColor; + QColor panSolidTopColor; + QColor panSolidBottomColor; + QColor wideBandLineColor; + QColor wideBandFilledColor; + QColor wideBandSolidTopColor; + QColor wideBandSolidBottomColor; + QColor distanceLineColor; + QColor distanceLineFilledColor; + QColor panCenterLineColor; + QColor gridLineColor; + +} TPanadapterColors; + + +typedef enum _smeterType { + + SIGNAL_STRENGTH, + AVG_SIGNAL_STRENGTH, + ADC_REAL, + ADC_IMAG, + AGC_GAIN, + MIC, + PWR, + ALC, + EQtap, + LEVELER, + COMP, + CPDR, + ALC_G, + LVL_G, + MIC_PK, + ALC_PK, + EQ_PK, + LEVELER_PK, + COMP_PK, + CPDR_PK + +} TMeterType; + +typedef enum _windowtype { + + RECTANGULAR_WINDOW, + HANNING_WINDOW, + WELCH_WINDOW, + PARZEN_WINDOW, + BARTLETT_WINDOW, + HAMMING_WINDOW, + BLACKMAN2_WINDOW, + BLACKMAN3_WINDOW, + BLACKMAN4_WINDOW, + EXPONENTIAL_WINDOW, + RIEMANN_WINDOW, + BLACKMANHARRIS_WINDOW, + NUTTALL_WINDOW + +} TWindowtype; + + +class Receiver; + +// ********************************************************************* +// thread class + +class QThreadEx : public QThread { + +protected: + void run() { exec(); } + +}; + +// ************************************** +// Settings class + +class Settings : public QObject { + + Q_OBJECT + +public: + static Settings *instance(QObject *parent = 0) { + + if (Settings::m_instance) + return Settings::m_instance; + + Settings::m_instance = new Settings(parent); + + return Settings::m_instance; + } + + static void delete_instance() { + + if (Settings::m_instance) { + + disconnect(Settings::m_instance, 0, 0, 0); + delete Settings::m_instance; + Settings::m_instance = 0; + } + } + + virtual ~Settings(); + + QMutex settingsMutex; + +private: + Settings(QObject *parent = 0); + + static Settings *m_instance; + + QSettings *settings; + QSettings *debugLog; + QErrorMessage *error; + +signals: + void systemMessageEvent(const QString &msg, int); + + void masterSwitchChanged(QObject *sender, bool power); + + void systemStateChanged( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void graphicModeChanged( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void cpuLoadChanged(short load); + void txAllowedChanged(QObject* sender, bool value); + void multiRxViewChanged(int view); + void sMeterValueChanged(int rx, float value); + void spectrumBufferChanged(int rx, const qVectorFloat& buffer); + void postSpectrumBufferChanged(int rx, const float* buffer); + + void sampleSizeChanged(int rx, int size); + void rxListChanged(QList rxList); + void clientConnectedChanged(QObject* sender, bool connect); + void clientNoConnectedChanged(QObject* sender, int client); + void audioRxChanged(QObject* sender, int rx); + void receiverChanged(int value); + void currentReceiverChanged(QObject *sender, int rx); + void connectedChanged(QObject *sender, bool connect); + + void clientConnectedEvent(int client); + void clientDisconnectedEvent(int client); + void rxConnectedStatusChanged(QObject* sender, int rx, bool value); + void framesPerSecondChanged(QObject* sender, int rx, int value); + + void settingsFilenameChanged(QString filename); + void settingsLoadedChanged(bool loaded); + + void newServerNetworkInterface(QString nicName, QString ipAddress); + void newHPSDRDeviceNIC(QString nicName, QString ipAddress); + void serverNICChanged(int); + void hpsdrDeviceNICChanged(int); + void socketBufferSizeChanged(QObject* sender, int value); + void manualSocketBufferChanged(QObject* sender, bool value); + //void metisCardListChanged(QList list); + void metisCardListChanged(const QList &list); + void hpsdrDevicesChanged(QObject *sender, THPSDRDevices devices); + void hpsdrNetworkDeviceChanged(TNetworkDevicecard card); + void networkDeviceNumberChanged(int value); + void networkIOComboBoxEntryAdded(QString str); + void clearNetworkIOComboBoxEntrySignal(); + void searchMetisSignal(); + void serverAddrChanged(QObject *sender, QString addr); + void hpsdrDeviceLocalAddrChanged(QObject *sender, QString addr); + void serverPortChanged(QObject *sender, quint16 port); + void listenPortChanged(QObject *sender, quint16 port); + void audioPortChanged(QObject *sender, quint16 port); + void metisPortChanged(QObject *sender, quint16 port); + + void showNetworkIO(); + void showWarning(const QString &msg); + + void callsignChanged(); + + void mouseWheelFreqStepChanged(QObject *sender, int rx, qreal value); + void mainVolumeChanged(QObject *sender, int rx, float volume ); + + //void hermesPresenceChanged(bool value); + void hpsdrHardwareChanged(int value); + void hermesVersionChanged(int value); + void mercuryPresenceChanged(bool value); + void mercuryVersionChanged(int value); + void penelopePresenceChanged(bool value); + void penelopeVersionChanged(int value); + void pennyLanePresenceChanged(bool value); + void pennyLaneVersionChanged(int value); + void alexPresenceChanged(bool value); + void excaliburPresenceChanged(bool value); + void metisVersionChanged(int value); + //void alexConfigurationChanged(const QList &conf); + void alexConfigurationChanged(quint16 config); + //void alexParametersChanged(TAlexParameters p); + void alexStatesChanged(const QList &states); + void alexStateChanged(HamBand band, const QList &states); + void alexStateChanged(int pos, int value); + void alexManualStateChanged(QObject *sender, bool value); + void checkFirmwareVersionChanged(QObject *sender, bool value); + void pennyOCEnabledChanged(bool value); + void rxJ6PinsChanged(const QList &states); + void txJ6PinsChanged(const QList &states); + + void protocolSyncChanged(int value); + void adcOverflowChanged(int value); + void packetLossChanged(int value); + void sendIQSignalChanged(int value); + void rcveIQSignalChanged(int value); + + void numberOfRXChanged(QObject *sender, int value); + void sampleRateChanged(QObject *sender, int value); + void mercuryAttenuatorChanged(QObject *sender, HamBand band, int value); + //void mercuryAttenuatorsChanged(QObject *sender, const QList &values); + void ditherChanged(QObject *sender, int value); + void randomChanged(QObject *sender, int value); + void src10MhzChanged(QObject *sender, int source); + void src122_88MhzChanged(QObject *sender, int source); + void micSourceChanged(QObject *sender, int source); + void classChanged(QObject *sender, int value); + void timingChanged(QObject *sender, int value); + void controlBytesOutChanged(QObject *sender, unsigned char *values); + //void ctrFrequencyChanged(QObject* sender, bool value, int rx, long frequency); + void ctrFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + //void vfoFrequencyChanged(QObject* sender, bool value, int rx, long frequency); + void vfoFrequencyChanged(QObject* sender, int mode, int rx, long frequency); + void ncoFrequencyChanged(int rx, long frequency); + + // wideband data + void widebandSpectrumBufferChanged(const qVectorFloat& buffer); + void widebandOptionsChanged(QObject* sender, TWideband options); + void widebandSpectrumBufferReset(); + void widebandStatusChanged(QObject* sender, bool value); + void widebandDataChanged(QObject* sender, bool value); + void widebanddBmScaleMinChanged(QObject *sender, qreal value); + void widebanddBmScaleMaxChanged(QObject *sender, qreal value); + void wideBandScalePositionChanged(QObject *sender, float position); + //void widebandAveragingChanged(QObject *sender, bool value); + //void widebandAveragingCntChanged(QObject *sender, int value); + + + void iqPortChanged(QObject* sender, int rx, int port); + + void hamBandChanged(QObject *sender, int rx, bool byButton, HamBand band); + void dspModeChanged(QObject *sender, int rx, DSPMode mode); + void agcModeChanged(QObject *sender, int rx, AGCMode mode, bool hangEnabled); + void agcHangEnabledChanged(QObject *sender, int rx, bool hang); + void agcGainChanged(QObject *sender, int rx, int value); + void agcThresholdChanged_dB(QObject *sender, int rx, qreal value); + void agcFixedGainChanged_dB(QObject *sender, int rx, qreal value); + void agcMaximumGainChanged_dB(QObject *sender, int rx, qreal value); + void agcHangThresholdChanged(QObject *sender, int rx, int value); + void agcHangThresholdSliderChanged(QObject *sender, int rx, qreal value); + void agcHangLevelChanged_dB(QObject *sender, int rx, qreal value); + void agcLineLevelsChanged(QObject *sender, int rx, qreal thresh, qreal hang); + void agcVariableGainChanged_dB(QObject *sender, int rx, qreal value); + void agcAttackTimeChanged(QObject *sender, int rx, qreal value); + void agcDecayTimeChanged(QObject *sender, int rx, qreal value); + void agcHangTimeChanged(QObject *sender, int rx, qreal value); + void filterFrequenciesChanged(QObject *sender, int rx, qreal low, qreal high); + + void cudaDevicesChanged(QObject *sender, int value); + void cudaDriverChanged(QObject *sender, int value); + void cudaRuntimeChanged(QObject *sender, int value); + void cudaCurrentDeviceChanged(QObject *sender, int value); + void cudaLastDeviceChanged(QObject* sender, int value); + + void freqRulerPositionChanged(QObject *sender, int rx, float position); + + + void audioFormatChanged(QObject *sender, const QAudioFormat &format); + void audioPositionChanged(QObject *sender, qint64 position); + void audioBufferChanged(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + //void audioBufferChanged(QObject *sender, const QByteArray &buffer); + + void chirpSignalModeChanged(QObject *sender); + void lowerChirpFreqChanged(QObject *sender, int value); + void upperChirpFreqChanged(QObject *sender, int value); + void chirpAmplitudeChanged(QObject *sender, qreal value); + void chirpSamplingFreqChanged(QObject *sender, int value); + void chirpBufferDurationUsChanged(QObject *sender, qint64 value); + void chirpRepetitionTimesChanged(QObject *sender, int value); + void chirpReceiverChanged(QObject *sender, int value); + void chirpBufferChanged(qint64 length, const QList &buffer); + void chirpAvgLengthChanged(int length); + void chirpFFTShowChanged(bool value); + void chirpSidebandChanged(bool value); + void chirpFilterLowerFrequencyChanged(int value); + void chirpFilterUpperFrequencyChanged(int value); + void chirpSpectrumBufferChanged(int sampleRate, qint64 length, const float *buffer); + void chirpSpectrumChanged(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + void chirpSpectrumListChanged(const QList &spectrumList); + + void displayWidgetHeightChanged(int value); + void spectrumSizeChanged(QObject *sender, int value); + void panadapterColorChanged(); + void panGridStatusChanged(bool value, int rx); + void peakHoldStatusChanged(bool value, int rx); + void panLockedStatusChanged(bool value, int rx); + void clickVFOStatusChanged(bool value, int rx); + void hairCrossStatusChanged(bool value, int rx); + void showAGCLinesStatusChanged(QObject *sender, bool value, int rx); + + void spectrumAveragingChanged(QObject *sender, int rx, bool value); + void spectrumAveragingCntChanged(QObject *sender, int rx, int value); + + + void waterfallTimeChanged(int rx, int value); + void waterfallOffesetLoChanged(int rx, int value); + void waterfallOffesetHiChanged(int rx, int value); + + void sMeterHoldTimeChanged(int value); + void dBmScaleMinChanged(int rx, qreal value); + void dBmScaleMaxChanged(int rx, qreal value); + + + void showRadioPopupChanged(bool value); + + void receiverDataReady(); + +public: + void debugSystemState(); + + int loadSettings(); + int saveSettings(); + + QSDR::_ServerMode getCurrentServerMode(); + QSDR::_HWInterfaceMode getHWInterface(); + QSDR::_DataEngineState getDataEngineState(); + + PanGraphicsMode getPanadapterMode(int rx); + WaterfallColorMode getWaterfallColorMode(int rx); + + QString getServerModeString(QSDR::_ServerMode mode); + QString getHWInterfaceModeString(QSDR::_HWInterfaceMode mode); + QString getHDataEngineStateString(QSDR::_DataEngineState mode); + QString getErrorString(QSDR::_Error err); + + QString getValue1000(double value, int valuePrefix, QString unitBase); + QString getValue1024(double value, int valuePrefix, QString unitBase); + + THPSDRDevices getHPSDRDevices(); + + bool getSettingsLoaded(); + bool getMainPower(); + bool getDefaultSkin(); + + int getMinimumWidgetWidth(); + int getMinimumGroupBoxWidth(); + int getMultiRxView(); + bool getPBOPresence(); + bool getFBOPresence(); + + bool getConnected(); + bool getClientConnected(); + bool getTxAllowed(); + + QString getTitleStr(); + QString getVersionStr(); + QString getSettingsFilename(); + QString getCallsign(); + + QString getSDRStyle(); + QString getWidgetStyle(); + QString getMainWindowStyle(); + QString getDockStyle(); + QString getDisplayToolbarStyle(); + QString getMainBtnToolbarStyle(); + QString getStatusbarStyle(); + QString getMessageBoxStyle(); + QString getLineEditStyle(); + QString getDialogStyle(); + QString getColorDialogStyle(); + QString getItemStyle(); + QString getLabelStyle(); + QString getSliderLabelStyle(); + QString getTableStyle(); + QString getComboBoxStyle(); + QString getSpinBoxStyle(); + QString getDoubleSpinBoxStyle(); + QString getMenuStyle(); + QString getMiniButtonStyle(); + QString getVolSliderStyle(); + QString getSplitterStyle(); + QString getFrameStyle(); + QString getTabWidgetStyle(); + //QString getNewSliderStyle(); + + + QString getServerAddr(); + QString getHPSDRDeviceLocalAddr(); + + quint16 getServerPort(); + quint16 getListenPort(); + quint16 getAudioPort(); + quint16 getMetisPort(); + + TNetworkDevicecard getCurrentMetisCard() { return m_currentHPSDRDevice; } + QList getMetisCardsList() { return m_metisCards; } + QList getReceiverDataList() { return m_receiverDataList; } + QList getBandFrequencyList() { return m_bandList; } + QList getHamBandTextList() { return m_bandTextList; } + QList getDefaultFilterList() { return m_defaultFilterList; } + TDefaultFilterMode getCurrentFilterMode() { return m_filterMode; } + quint16 getAlexConfig() { return m_alexConfig; } + QList getAlexStates() { return m_alexStates; } + QList getHPFLoFrequencies() { return m_HPFLoFrequencyList; } + QList getHPFHiFrequencies() { return m_HPFHiFrequencyList; } + QList getLPFLoFrequencies() { return m_LPFLoFrequencyList; } + QList getLPFHiFrequencies() { return m_LPFHiFrequencyList; } + QList getRxJ6Pins() { return m_rxJ6pinList; } + QList getTxJ6Pins() { return m_txJ6pinList; } + int getFramesPerSecond(int rx); + QString getDSPModeString(int mode); + + HamBand getCurrentHamBand(int rx); + QList getMercuryAttenuators(int rx); + //int getMercuryAttenuator(); + + bool getPennyOCEnabled() { return m_pennyOCEnabled; } + int getHpsdrNetworkDevices() { return m_hpsdrNetworkDevices; } + int getNetworkInterfacesNo() { return m_NetworkInterfacesNo; } + bool getMercuryPresence() { return m_devices.mercuryPresence; } + int getMercuryVersion() { return m_devices.mercuryFWVersion; } + bool getPenelopePresence() { return m_devices.penelopePresence; } + int getPenelopeVersion() { return m_devices.penelopeFWVersion; } + bool getPennyLanePresence() { return m_devices.pennylanePresence; } + int getPennyLaneVersion() { return m_devices.pennylaneFWVersion; } + bool getHermesPresence() { return m_devices.hermesPresence; } + int getHermesVersion() { return m_devices.hermesFWVersion; } + int getHPSDRHardware() { return m_hpsdrHardware; } + bool getAlexPresence() { return m_devices.alexPresence; } + bool getExcaliburPresence() { return m_devices.excaliburPresence; } + bool getMetisPresence() { return m_devices.metisPresence; } + int getMetisVersion() { return m_devices.metisFWVersion; } + int getSocketBufferSize() { return m_socketBufferSize; } + bool getManualSocketBufferSize() { return m_manualSocketBufferSize; } + bool getFirmwareVersionCheck() { return m_checkFirmwareVersions; } + + // wideband data & options + TWideband getWidebandOptions() { return m_widebandOptions; } + + bool getWidebandStatus() { return m_widebandOptions.wideBandDisplayStatus; } + bool getWidebandData() { return m_widebandOptions.wideBandData; } + qreal getWidebanddBmScaleMin() { return m_widebandOptions.dBmWBScaleMin; } + qreal getWidebanddBmScaleMax() { return m_widebandOptions.dBmWBScaleMax; } + int getWidebandBuffers() { return m_widebandOptions.numberOfBuffers; } + + + + bool getPanGridStatus(int rx); + bool getPeakHoldStatus(int rx); + bool getPanLockedStatus(int rx); + bool getClickVFOStatus(int rx); + bool getHairCrossStatus(int rx); + + int getMercurySpeed() { return m_mercurySpeed; } + int getOutputSampleIncrement() { return m_outputSampleIncrement; } + int getNumberOfReceivers() { return m_mercuryReceivers; } + //int getCurrentReceivers() { return m_mercuryReceivers; } + int getCurrentReceiver() { return m_currentReceiver; } + bool getFrequencyRx1onRx2() { return m_frequencyRx1onRx2; } + int getSampleRate() { return m_sampleRate; } + + //int getMercuryAttenuator() { return m_mercuryAttenuator; } + int getMercuryDither() { return m_mercuryDither; } + int getMercuryRandom() { return m_mercuryRandom; } + int get10MHzSource() { return m_10MHzSource; } + int get122_8MHzSource() { return m_122_8MHzSource; } + int getMicSource() { return m_micSource; } + int getRxClass() { return m_RxClass; } + int getRxTiming() { return m_RxTiming; } + + qreal getMainVolume(int rx); + qreal getMouseWheelFreqStep(int rx);// { return m_mouseWheelFreqStep; } + AGCMode getAGCMode(int rx); + QString getAGCModeString(int rx); + int getAGCGain(int rx); + qreal getAGCMaximumGain_dB(int rx); + qreal getAGCFixedGain_dB(int rx); + int getAGCHangThreshold(int rx); + int getAGCHangLeveldB(int rx); + + int getLowerChirpFreq() { return m_lowerChirpFreq; } + int getUpperChirpFreq() { return m_upperChirpFreq; } + qreal getChirpAmplitude() { return m_chirpAmplitude; } + int getChirpSamplingFreq() { return m_chirpSamplingFreq; } + qint64 getChirpBufferDurationUs() { return m_chirpBufferDurationUs; } + qint64 getChirpBufferLength() { return m_chirpBufferLength; } + int getChirpChannels() { return m_chirpChannels; } + int getChirpRepetitionTimes() { return m_chirpRepetitionTimes; } + int getChirpDownSampleRate() { return m_chirpDownSampleRate; } + int getChirpAvgLength() { return m_chirpAvgLength; } + int getChirpFilterLowerFrequency() { return m_chirpFilterLowerFrequency; } + int getChirpFilterUpperFrequency() { return m_chirpFilterUpperFrequency; } + bool getChirpReceiver() { return m_chirpReceiverOn; } + bool getChirpFFTShow() { return m_showChirpFFT; } + bool getChirpSideband() { return m_chirpUSB; } + + int getSpectrumSize() { return m_spectrumSize; } + + qreal getdBmDistScaleMin() { return m_dBmDistScaleMin; } + qreal getdBmDistScaleMax() { return m_dBmDistScaleMax; } + + int getSMeterHoldTime() { return m_sMeterHoldTime; } + + qreal getFilterFrequencyLow() { return m_filterFrequencyLow; } + qreal getFilterFrequencyHigh() { return m_filterFrequencyHigh; } + + QList m_ipAddressesList; + QList m_networkInterfaces; + + // audio + QAudio::Mode mode() const { return m_audioMode; } + QAudio::State state() const { return m_audioState; } + QAudioFormat getAudioFormat() const { return m_format; } + + // colors + TPanadapterColors getPanadapterColors() { return m_panadapterColors; } + + bool getSpectrumAveraging(int rx); + int getSpectrumAveragingCnt(int rx); + + int getFFTMultiplicator() { return m_fft; } + + QMutex debugMutex; + +public slots: + void setMainPower(QObject *sender, bool power); + void setDefaultSkin(QObject *sender, bool value); + void setSettingsFilename(QString filename); + + void setSystemMessage(const QString &msg, int time); + void setSettingsLoaded(bool loaded); + void setCPULoad(short load); + void setCallsign(const QString &callsign); + + void setPBOPresence(bool value); + void setFBOPresence(bool value); + + void setMainVolume(QObject *sender, int rx, float volume); + void setMainVolumeMute(QObject *sender, int rx, bool value); + + void setSystemState( + QObject *sender, + QSDR::_Error err, + QSDR::_HWInterfaceMode hwmode, + QSDR::_ServerMode mode, + QSDR::_DataEngineState state); + + void setGraphicsState( + QObject *sender, + int rx, + PanGraphicsMode panMode, + WaterfallColorMode waterfallColorMode); + + void setTxAllowed(QObject* sender, bool value); + void setMultiRxView(int view); + void setSMeterValue(int rx, float value); + void setSpectrumBuffer(int rx, const qVectorFloat &buffer); + void setPostSpectrumBuffer(int rx, const float*); + void setSampleSize(QObject* sender, int rx, int size); + void setRxList(QList rxList); + void setMetisCardList(QList list); + void searchHpsdrNetworkDevices(); + void clearMetisCardList(); + void setHPSDRDeviceNumber(int value); + void setCurrentHPSDRDevice(TNetworkDevicecard card); + void addNetworkIOComboBoxEntry(QString str); + void clearNetworkIOComboBoxEntry(); + void addServerNetworkInterface(QString nicName, QString ipAddress); + void addHPSDRDeviceNIC(QString nicName, QString ipAddress); + void setNumberOfNetworkInterfaces(int value); + void setServerNetworkInterface(int index); + void setHPSDRDeviceNIC(int index); + void setServerWidgetNIC(int index); + void setHPSDRWidgetNIC(int index); + void setServerAddr(QObject *sender, QString addr); + void setHPSDRDeviceLocalAddr(QObject *sender, QString addr); + void setServerPort(QObject *sender, quint16 port); + void setListenPort(QObject *sender, quint16 port); + void setAudioPort(QObject *sender, quint16 port); + void setMetisPort(QObject *sender, quint16 port); + void setClientConnected(QObject *sender, bool value); + void setClientNoConnected(QObject* sender, int client); + void setRxConnectedStatus(QObject* sender, int rx, bool value); + void setAudioRx(QObject* sender, int rx); + void setConnected(QObject *sender, bool value); + void setCheckFirmwareVersion(QObject *sender, bool value); + + void setHPSDRDevices(QObject *sender, THPSDRDevices devices); + //void setHermesPresence(bool value); + void setHermesVersion(int value); + void setHPSDRHardware(int value); + void setMercuryPresence(bool value); + void setMercuryVersion(int value); + void setPenelopePresence(bool value); + void setPenelopeVersion(int value); + void setPennyLanePresence(bool value); + void setPennyLaneVersion(int value); + void setAlexPresence(bool value); + void setExcaliburPresence(bool value); + void setMetisVersion(int value); + + //void setAlexConfiguration(QObject *sender, const QList &conf); + void setAlexConfiguration(QObject *sender, quint16 conf); + void setAlexHPFLoFrequencies(int filter, long value); + void setAlexHPFHiFrequencies(int filter, long value); + void setAlexLPFLoFrequencies(int filter, long value); + void setAlexLPFHiFrequencies(int filter, long value); + void setAlexStates(QObject *sender, const QList &states); + void setAlexState(QObject *sender, int pos, int value); + void setAlexState(QObject *sender, int value); + void setAlexToManual(QObject *sender, bool value); + int checkAlexState(int state); + + void setPennyOCEnabled(QObject *sender, bool value); + void setRxJ6Pin(QObject *sender, HamBand band, int value); + void setRxJ6Pins(QObject * sender, const QList &states); + void setTxJ6Pin(QObject *sender, HamBand band, int value); + void setTxJ6Pins(QObject * sender, const QList &states); + + void setIQPort(QObject *sender, int rx, int port); + + void setProtocolSync(int value); + void setADCOverflow(int value); + void setPacketLoss(int value); + void setSendIQ(int value); + void setRcveIQ(int value); + + void setReceivers(QObject *sender, int value); + //void setReceiver(QObject *sender, int value); + void setCurrentReceiver(QObject *sender, int value); + void setSampleRate(QObject *sender, int value); + void setMercuryAttenuator(QObject *sender, int value); + void setDither(QObject *sender, int value); + void setRandom(QObject *sender, int value); + void set10MhzSource(QObject *sender, int source); + void set122_88MhzSource(QObject *sender, int source); + void setMicSource(QObject *sender, int source); + void setClass(QObject *sender, int value); + void setTiming(QObject *sender, int value); + void setCtrFrequency(QObject *sender, int mode, int rx, long frequency); + void setCtrFrequency(int rx, long frequency); + long getCtrFrequency(int rx); + void setVFOFrequency(QObject *sender, int mode, int rx, long frequency); + void setVfoFrequency(int rx, long frequency); + long getVfoFrequency(int rx); + void setNCOFrequency(QObject *sender, bool value, int rx, long frequency); + + void clientDisconnected(int client); + void setFramesPerSecond(QObject *sender, int rx, int value); + void setMouseWheelFreqStep(QObject *sender, int rx, qreal value); + void setSocketBufferSize(QObject *sender, int value); + void setManualSocketBufferSize(QObject *sender, bool value); + + void setReceiverDataReady(); + + void setSpectrumSize(QObject *sender, int value); + void setdBmPanScaleMin(int rx, qreal value); + void setdBmPanScaleMax(int rx, qreal value); + + void setdBmDistScaleMin(qreal value); + void setdBmDistScaleMax(qreal value); + + void setHamBand(QObject* sender, int rx, bool byButton, HamBand band); + void setDSPMode(QObject* sender, int rx, DSPMode mode); + void setAGCMode(QObject* sender, int rx, AGCMode mode); + void setAGCGain(QObject* sender, int rx, int value); + void setAGCMaximumGain_dB(QObject *sender, int rx, qreal value); + void setAGCFixedGain_dB(QObject *sender, int rx, qreal value); + void setAGCThreshold_dB(QObject *sender, int rx, qreal value); + + void setAGCHangThresholdSlider(QObject *sender, int rx, qreal value); + void setAGCHangThreshold(QObject *sender, int rx, int value); + void setAGCHangLevel_dB(QObject *sender, int rx, qreal value); + void setAGCLineLevels(QObject *sender, int rx, qreal thresh, qreal hang); + void setAGCShowLines(QObject *sender, int rx, bool value); + void setAGCVariableGain_dB(QObject *sender, int rx, qreal value); + void setAGCAttackTime(QObject *sender, int rx, qreal value); + void setAGCDecayTime(QObject *sender, int rx, qreal value); + void setAGCHangTime(QObject *sender, int rx, qreal value); + void setRXFilter(QObject* sender, int rx, qreal low, qreal high); + + + // wideband data & options + void setWidebandBuffers(QObject *sender, int value); + void setWidebandSpectrumBuffer(const qVectorFloat &buffer); + void resetWidebandSpectrumBuffer(); + void setWidebandOptions(QObject* sender, TWideband options); + void setWidebandStatus(QObject* sender, bool value); + void setWidebandData(QObject* sender, bool value); + void setWidebanddBmScaleMin(QObject* sender, qreal value); + void setWidebanddBmScaleMax(QObject* sender, qreal value); + //void setWidebandAveraging(QObject *sender, bool value); + //void setWidebandAveragingCnt(QObject *sender, int value); + void setWideBandRulerPosition(QObject* sender, float pos); + + //void setOpenCLDevices(QList dev); + + /*void setCudaPresence(bool value); + void setCudaDevices(int value); + void setCudaLastDevice(QObject *sender, int vlaue); + void setCudaDriver(QObject *sender, int value); + void setCudaRuntime(QObject *sender, int value); + void setCurrentCudaDevice(QObject *sender, int value);*/ + + void setFreqRulerPosition(QObject* sender, int rx, float pos); + //void setRulerPosition(QObject *sender, float pos); + + void setAudioFormat(QObject *sender, const QAudioFormat &format); + void setAudioPosition(QObject *sender, qint64 position); + void setAudioBuffer(QObject *sender, qint64 position, qint64 length, const QByteArray &buffer); + //void setAudioBuffer(QObject *sender, const QByteArray &buffer); + + void switchToChirpSignalMode(QObject *sender); + void setLowerChirpFreq(int value); + void setUpperChirpFreq(int value); + void setChirpAmplitude(qreal value); + void setChirpSamplingFreq(int value); + void setChirpBufferDurationUs(int value); + void setChirpRepetitionTimes(int value); + void setChirpReceiver(bool value); + void setChirpAvgLength(int value); + void setChirpFFTShow(bool value); + void setChirpUSB(bool value); + void setChirpFilterLowerFrequency(int value); + void setChirpFilterUpperFrequency(int value); + //void setChirpDownSampleRate(int value); + //void setChirpBufferLength(qint64 length); + void setChirpBuffer(qint64 length, const QList &buffer); + //void setChirpSpectrumBuffer(const QList &buffer); + void setChirpSpectrumBuffer(int sampleRate, qint64 length, const float *buffer); + + //void setSpectrumBuffer(const float *buffer); + void setChirpSpectrum(qint64 position, qint64 length, const FrequencySpectrum &spectrum); + void setChirpSpectrumList(const QList &spectrumList); + + void moveDisplayWidget(int value); + + void setPanadapterColors(TPanadapterColors type); + void setPanGrid(bool value, int rx); + void setPeakHold(bool value, int rx); + void setPanLocked(bool value, int rx); + void setClickVFO(bool value, int rx); + void setHairCross(bool value, int rx); + + void setSpectrumAveraging(QObject *sender, int rx, bool value); + void setSpectrumAveragingCnt(QObject *sender, int rx, int value); + + + void setWaterfallTime(int rx, int value); + void setWaterfallOffesetLo(int rx, int value); + void setWaterfallOffesetHi(int rx, int value); + + void setSMeterHoldTime(int value); + + void showNetworkIODialog(); + void showWarningDialog(const QString &msg); + + void showRadioPopupWidget(); + + QList getCtrFrequencies(); + QList getVfoFrequencies(); + +private slots: + +private: + QSDR::_Error m_systemError; + QSDR::_ServerMode m_serverMode; + QSDR::_HWInterfaceMode m_hwInterface; + QSDR::_DataEngineState m_dataEngineState; + + QAudio::Mode m_audioMode; + QAudio::State m_audioState; + QAudioFormat m_format; + + THPSDRDevices m_devices; + TDefaultFilterMode m_filterMode; + TPanadapterColors m_panadapterColors; + TNetworkDevicecard m_currentHPSDRDevice; + TTransmitter m_transmitter; + TWideband m_widebandOptions; + + QList m_metisCards; + QList m_receiverDataList; + QList m_bandList; + QList m_bandTextList; + QList m_defaultFilterList; + //QList m_clDevices; + QList m_rxStringList; + QList m_alexStates; + QList m_HPFLoFrequencyList; + QList m_HPFHiFrequencyList; + QList m_LPFLoFrequencyList; + QList m_LPFHiFrequencyList; + QList m_rxJ6pinList; + QList m_txJ6pinList; + + QString m_titleString; + QString m_versionString; + QString m_serverAddress; + QString m_hpsdrDeviceLocalAddr; + QString m_callsignString; + QString settingsFilename; + + QDateTime startTime; + QDateTime now; + + QHostAddress m_hostAddress; + + + quint16 m_serverPort; + quint16 m_listenerPort; + quint16 m_audioPort; + quint16 m_metisPort; + quint16 m_alexConfig; + + bool setLoaded; + + bool m_mainPower; + bool m_defaultSkin; + bool m_connected; + bool m_clientConnected; + bool m_pboFound; + bool m_fboFound; + bool m_manualSocketBufferSize; + bool m_pennyOCEnabled; + + //bool main_mute; + bool m_checkFirmwareVersions; + bool m_specAveraging; + bool m_panGrid; + bool m_peakHold; + bool m_packetsToggle; + + bool m_frequencyRx1onRx2; + bool m_radioPopupVisible; + + int m_hpsdrHardware; + int m_hpsdrNetworkDevices; + int m_NetworkInterfacesNo; + int m_socketBufferSize; + int m_clientNoConnected; + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + int m_mercuryReceivers; + int m_currentReceiver; + int m_sampleRate; + int m_mercurySpeed; + + int m_mercuryAttenuator; + int m_mercuryDither; + int m_mercuryRandom; + + int m_outputSampleIncrement; + int m_10MHzSource; + int m_122_8MHzSource; + int m_micSource; + int m_RxClass; + int m_RxTiming; + + int m_framesPerSecond; + int m_multiRxView; + + //int m_wbBuffers; + int m_spectrumSize; + int m_sMeterHoldTime; + + long freq1; + + float m_mainVolume; + + int control_register; + bool connect_at_startup; + + qreal m_dBmDistScaleMin; + qreal m_dBmDistScaleMax; + + qreal m_filterFrequencyLow; + qreal m_filterFrequencyHigh; + + qreal m_chirpAmplitude; + + qint64 m_chirpBufferDurationUs; + qint64 m_chirpBufferLength; + + bool m_chirpReceiverOn; + bool m_showChirpFFT; + bool m_chirpUSB; + + int m_lowerChirpFreq; + int m_upperChirpFreq; + int m_chirpSamplingFreq; + int m_chirpChannels; + int m_chirpRepetitionTimes; + int m_chirpDownSampleRate; + int m_chirpAvgLength; + int m_chirpFilterLowerFrequency; + int m_chirpFilterUpperFrequency; + + int m_fft; + + /*bool m_cudaPresence; + int m_cuda_devices; + int m_cudaLastDevice; + int m_cuda_driver_version; + int m_cuda_runtime_version; + int m_current_cuda_device;*/ + + void checkHPSDRDevices(); +}; + + +//****************************************************** +// Macros + +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** The following Macro "CHECKED_CONNECT" is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ +// Macro which connects a signal to a slot, and which causes application to +// abort if the connection fails. This is intended to catch programming errors +// such as mis-typing a signal or slot name. It is necessary to write our own +// macro to do this - the following idiom +// Q_ASSERT(connect(source, signal, receiver, slot)); +// will not work because Q_ASSERT compiles to a no-op in release builds. + +#define CHECKED_CONNECT(source, signal, receiver, slot) \ + if(!connect(source, signal, receiver, slot)) \ + qt_assert_x(Q_FUNC_INFO, "CHECKED_CONNECT failed", __FILE__, __LINE__); + +#define CHECKED_CONNECT_OPT(source, signal, receiver, slot, opt) \ + if(!connect(source, signal, receiver, slot, opt)) \ + qt_assert_x(Q_FUNC_INFO, "CHECKED_CONNECT failed", __FILE__, __LINE__); + + + +//****************************************************** +// Debug output + +class NullDebug { + +public: + template + NullDebug& operator << (const T) { return *this; } +}; + +inline NullDebug nullDebug() { return NullDebug(); } + + +#ifdef LOG_SETTINGS +# define SETTINGS_DEBUG qDebug().nospace() << "Settings::\t" +#else +# define SETTINGS_DEBUG nullDebug() +#endif + + +//****************************************************** +// sleeper function + +class SleeperThread : public QThread { + + public: + static void msleep(unsigned long msecs) {QThread::msleep(msecs);} + static void usleep(unsigned long usecs) {QThread::usleep(usecs);} +}; + +#endif // CUSDR_SETTINGS_H diff --git a/Source/src/cusdr_transmitOptionsWidget.cpp b/Source/src/cusdr_transmitOptionsWidget.cpp new file mode 100644 index 0000000..93a8110 --- /dev/null +++ b/Source/src/cusdr_transmitOptionsWidget.cpp @@ -0,0 +1,369 @@ +/** +* @file cusdr_transmitOptionsWidget.h +* @brief transmit control widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-16 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#include +//#include +//#include +//#include +#include +#include + +#include "cusdr_transmitOptionsWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +TransmitOptionsWidget::TransmitOptionsWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + //, m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) + , m_minimumGroupBoxWidth(0) +{ + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 8, 4, 0); + setMouseTracking(true); + + // create groups + createSourceGroup(); + createTransmitFilterGroup(); + createPTTOptionsGroup(); + + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 4, 0); + hbox1->addWidget(sourceGroup); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(0); + hbox2->setContentsMargins(4, 0, 4, 0); + hbox2->addWidget(transmitFilterGroup); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(0); + hbox3->setContentsMargins(4, 0, 4, 0); + hbox3->addWidget(pttOptionsGroup); + + /*QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(0); + hbox4->setContentsMargins(4, 0, 4, 0); + hbox4->addWidget(searchNetworkDeviceGroupBox); + + if (m_hwInterface == QSDR::NoInterfaceMode) { + + deviceNIGroupBox->hide(); + searchNetworkDeviceGroupBox->hide(); + } + + QHBoxLayout *hbox5 = new QHBoxLayout(); + hbox5->setSpacing(0); + hbox5->setContentsMargins(4, 0, 4, 0); + hbox5->addWidget(source10MhzExclusiveGroup); + + QHBoxLayout *hbox6 = new QHBoxLayout(); + hbox6->setSpacing(0); + hbox6->setContentsMargins(4, 0, 4, 0); + hbox6->addWidget(source122_88MhzExclusiveGroup); + + QHBoxLayout *hbox7 = new QHBoxLayout(); + hbox7->setSpacing(0); + hbox7->setContentsMargins(4, 0, 4, 0); + hbox7->addWidget(numberOfReceiversGroup());*/ + + mainLayout->addLayout(hbox1); + mainLayout->addLayout(hbox2); + mainLayout->addLayout(hbox3); + /*mainLayout->addLayout(hbox4); + mainLayout->addLayout(hbox5); + mainLayout->addLayout(hbox6); + mainLayout->addLayout(hbox7);*/ + mainLayout->addStretch(); + setLayout(mainLayout); + + setupConnections(); +} + +TransmitOptionsWidget::~TransmitOptionsWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void TransmitOptionsWidget::setupConnections() { + +} + +void TransmitOptionsWidget::createSourceGroup() { + + QLabel* sourceLabel = new QLabel("Source:", this); + sourceLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + sourceLabel->setStyleSheet(set->getLabelStyle()); + + micInputBtn = new AeroButton("Mic Input", this); + micInputBtn->setRoundness(0); + micInputBtn->setFixedSize(btn_width, btn_height); + micInputBtn->setBtnState(AeroButton::ON); + + CHECKED_CONNECT( + micInputBtn, + SIGNAL(clicked()), + this, + SLOT(inputButtonClicked())); + + lineInputBtn = new AeroButton("Line Input", this); + lineInputBtn->setRoundness(0); + lineInputBtn->setFixedSize(btn_width, btn_height); + lineInputBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + lineInputBtn, + SIGNAL(clicked()), + this, + SLOT(inputButtonClicked())); + + + QLabel* maxLabel = new QLabel("Max Gain (dB):", this); + maxLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + maxLabel->setStyleSheet(set->getLabelStyle()); + + QLabel* minLabel = new QLabel("Min Gain (dB):", this); + minLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + minLabel->setStyleSheet(set->getLabelStyle()); + + micGainMaxSpinBox = new QSpinBox(this); + micGainMaxSpinBox->setMinimum(1); + micGainMaxSpinBox->setMaximum(70); + micGainMaxSpinBox->setStyleSheet(set->getSpinBoxStyle()); + micGainMaxSpinBox->setValue(10); + + micGainMinSpinBox = new QSpinBox(this); + micGainMinSpinBox->setMinimum(-96); + micGainMinSpinBox->setMaximum(0); + micGainMinSpinBox->setStyleSheet(set->getSpinBoxStyle()); + micGainMinSpinBox->setValue(-40); + + QLabel* boostLabel = new QLabel("20 dB Mic Boost:", this); + boostLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + boostLabel->setStyleSheet(set->getLabelStyle()); + + micBoostBtn = new AeroButton(" Off ", this); + micBoostBtn->setRoundness(0); + micBoostBtn->setFixedSize(btn_width, btn_height); + micBoostBtn->setBtnState(AeroButton::OFF); + + CHECKED_CONNECT( + micBoostBtn, + SIGNAL(clicked()), + this, + SLOT(boostButtonClicked())); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addWidget(sourceLabel); + hbox1->addStretch(); + hbox1->addWidget(micInputBtn); + hbox1->addWidget(lineInputBtn); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(4); + hbox2->addWidget(boostLabel); + hbox2->addStretch(); + hbox2->addWidget(micBoostBtn); + + QHBoxLayout *hbox3 = new QHBoxLayout(); + hbox3->setSpacing(4); + hbox3->addWidget(maxLabel); + hbox3->addStretch(); + hbox3->addWidget(micGainMaxSpinBox); + + QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(4); + hbox4->addWidget(minLabel); + hbox4->addStretch(); + hbox4->addWidget(micGainMinSpinBox); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + vbox->addSpacing(12); + vbox->addLayout(hbox3); + vbox->addLayout(hbox4); + + sourceGroup = new QGroupBox(tr("Mic / Line Options"), this); + sourceGroup->setMinimumWidth(m_minimumGroupBoxWidth); + sourceGroup->setLayout(vbox); + sourceGroup->setStyleSheet(set->getWidgetStyle()); + sourceGroup->setFont(QFont("Arial", 8)); +} + +void TransmitOptionsWidget::createTransmitFilterGroup() { + + QLabel* highLabel = new QLabel("High (Hz):", this); + highLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + highLabel->setStyleSheet(set->getLabelStyle()); + + QLabel* lowLabel = new QLabel("Low (Hz):", this); + lowLabel->setFrameStyle(QFrame::Box | QFrame::Raised); + lowLabel->setStyleSheet(set->getLabelStyle()); + + highFilterSpinBox = new QSpinBox(this); + highFilterSpinBox->setMinimum(1000); + highFilterSpinBox->setMaximum(5000); + highFilterSpinBox->setStyleSheet(set->getSpinBoxStyle()); + highFilterSpinBox->setValue(3100); + + lowFilterSpinBox = new QSpinBox(this); + lowFilterSpinBox->setMinimum(0); + lowFilterSpinBox->setMaximum(1000); + lowFilterSpinBox->setStyleSheet(set->getSpinBoxStyle()); + lowFilterSpinBox->setValue(200); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addWidget(highLabel); + hbox1->addStretch(); + hbox1->addWidget(highFilterSpinBox); + + QHBoxLayout *hbox2 = new QHBoxLayout(); + hbox2->setSpacing(4); + hbox2->addWidget(lowLabel); + hbox2->addStretch(); + hbox2->addWidget(lowFilterSpinBox); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + vbox->addLayout(hbox2); + + transmitFilterGroup = new QGroupBox(tr("Transmit Filter"), this); + transmitFilterGroup->setMinimumWidth(m_minimumGroupBoxWidth); + transmitFilterGroup->setLayout(vbox); + transmitFilterGroup->setStyleSheet(set->getWidgetStyle()); + transmitFilterGroup->setFont(QFont("Arial", 8)); +} + +void TransmitOptionsWidget::createPTTOptionsGroup() { + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(4); + hbox1->addStretch(); + //hbox1->addWidget(penelopeBtn); + //hbox1->addWidget(mercuryBtn); + + QVBoxLayout *vbox = new QVBoxLayout(); + vbox->setSpacing(4); + vbox->addSpacing(6); + vbox->addLayout(hbox1); + + pttOptionsGroup = new QGroupBox(tr("PTT Options"), this); + pttOptionsGroup->setMinimumWidth(m_minimumGroupBoxWidth); + pttOptionsGroup->setLayout(vbox); + pttOptionsGroup->setStyleSheet(set->getWidgetStyle()); + pttOptionsGroup->setFont(QFont("Arial", 8)); +} + + +// ************************************************************************ + +void TransmitOptionsWidget::inputButtonClicked() { + + AeroButton *button = qobject_cast(sender()); + + micInputBtn->setBtnState(AeroButton::OFF); + micInputBtn->update(); + lineInputBtn->setBtnState(AeroButton::OFF); + lineInputBtn->update(); + + button->setBtnState(AeroButton::ON); + button->update(); +} + +void TransmitOptionsWidget::boostButtonClicked() { + + if (micBoostBtn->btnState() == AeroButton::OFF) { + + micBoostBtn->setBtnState(AeroButton::ON); + micBoostBtn->setText(" On "); + } + else { + + micBoostBtn->setBtnState(AeroButton::OFF); + micBoostBtn->setText(" Off "); + } +} + +void TransmitOptionsWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void TransmitOptionsWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +void TransmitOptionsWidget::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void TransmitOptionsWidget::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void TransmitOptionsWidget::mouseMoveEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void TransmitOptionsWidget::mousePressEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void TransmitOptionsWidget::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + + diff --git a/Source/src/cusdr_transmitOptionsWidget.h b/Source/src/cusdr_transmitOptionsWidget.h new file mode 100644 index 0000000..43c3714 --- /dev/null +++ b/Source/src/cusdr_transmitOptionsWidget.h @@ -0,0 +1,97 @@ +/** +* @file cusdr_transmitOptionsWidget.h +* @brief transmit control widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-06-16 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_TRANSMIT_OPTIONS_WIDGET_H +#define _CUSDR_TRANSMIT_OPTIONS_WIDGET_H + +#include +#include +#include +#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + + +class TransmitOptionsWidget : public QWidget { + + Q_OBJECT + +public: + TransmitOptionsWidget(QWidget *parent = 0); + ~TransmitOptionsWidget(); + + +public slots: + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + void setupConnections(); + void createSourceGroup(); + void createTransmitFilterGroup(); + void createPTTOptionsGroup(); + +private: + Settings* set; + + QString m_message; + + QGroupBox* sourceGroup; + QGroupBox* transmitFilterGroup; + QGroupBox* pttOptionsGroup; + + QSpinBox* highFilterSpinBox; + QSpinBox* lowFilterSpinBox; + QSpinBox* micGainMaxSpinBox; + QSpinBox* micGainMinSpinBox; + + AeroButton* micInputBtn; + AeroButton* lineInputBtn; + AeroButton* micBoostBtn; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + +private slots: + void inputButtonClicked(); + void boostButtonClicked(); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString message); +}; + +#endif // _CUSDR_TRANSMIT_OPTIONS_WIDGET_H diff --git a/Source/src/cusdr_transmitPAWidget.cpp b/Source/src/cusdr_transmitPAWidget.cpp new file mode 100644 index 0000000..bb08e3d --- /dev/null +++ b/Source/src/cusdr_transmitPAWidget.cpp @@ -0,0 +1,228 @@ +/** +* @file cusdr_transmitPAWidget.cpp +* @brief transmit PA control widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-28 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +//#include +//#include +//#include +//#include +#include +#include + +#include "cusdr_transmitPAWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +TransmitPAWidget::TransmitPAWidget(QWidget *parent) + : QWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(0) +{ + setMinimumWidth(m_minimumWidgetWidth); + setContentsMargins(4, 8, 4, 0); + setMouseTracking(true); + + createGainGroup(); + //createTransmitFilterGroup(); + //createPTTOptionsGroup(); + + + QBoxLayout *mainLayout = new QBoxLayout(QBoxLayout::TopToBottom, this); + mainLayout->setSpacing(5); + mainLayout->setMargin(0); + mainLayout->addSpacing(8); + + QHBoxLayout *hbox1 = new QHBoxLayout(); + hbox1->setSpacing(0); + hbox1->setContentsMargins(4, 0, 4, 0); + hbox1->addWidget(gainGroup); + +// QHBoxLayout *hbox2 = new QHBoxLayout(); +// hbox2->setSpacing(0); +// hbox2->setContentsMargins(4, 0, 4, 0); +// hbox2->addWidget(transmitFilterGroup); +// +// QHBoxLayout *hbox3 = new QHBoxLayout(); +// hbox3->setSpacing(0); +// hbox3->setContentsMargins(4, 0, 4, 0); +// hbox3->addWidget(pttOptionsGroup); + + /*QHBoxLayout *hbox4 = new QHBoxLayout(); + hbox4->setSpacing(0); + hbox4->setContentsMargins(4, 0, 4, 0); + hbox4->addWidget(searchNetworkDeviceGroupBox); + + if (m_hwInterface == QSDR::NoInterfaceMode) { + + deviceNIGroupBox->hide(); + searchNetworkDeviceGroupBox->hide(); + } + + QHBoxLayout *hbox5 = new QHBoxLayout(); + hbox5->setSpacing(0); + hbox5->setContentsMargins(4, 0, 4, 0); + hbox5->addWidget(source10MhzExclusiveGroup); + + QHBoxLayout *hbox6 = new QHBoxLayout(); + hbox6->setSpacing(0); + hbox6->setContentsMargins(4, 0, 4, 0); + hbox6->addWidget(source122_88MhzExclusiveGroup); + + QHBoxLayout *hbox7 = new QHBoxLayout(); + hbox7->setSpacing(0); + hbox7->setContentsMargins(4, 0, 4, 0); + hbox7->addWidget(numberOfReceiversGroup());*/ + + mainLayout->addLayout(hbox1); + //mainLayout->addLayout(hbox2); + //mainLayout->addLayout(hbox3); + /*mainLayout->addLayout(hbox4); + mainLayout->addLayout(hbox5); + mainLayout->addLayout(hbox6); + mainLayout->addLayout(hbox7);*/ + mainLayout->addStretch(); + setLayout(mainLayout); + + setupConnections(); +} + +TransmitPAWidget::~TransmitPAWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +void TransmitPAWidget::setupConnections() { + +} + +void TransmitPAWidget::createGainGroup() { + +// QLabel *dBmLabel = new QLabel("dBm", this); +// dBmLabel->setFrameStyle(QFrame::Box | QFrame::Raised); +// dBmLabel->setStyleSheet(set->getLabelStyle()); + + // band label + QStringList bandNames; + bandNames << "2200m" << "630m" << "160 m" << "80 m" << "60 m" << "40 m" << "30 m" << "20 m" << "17 m" << "15 m" << "12 m" << "10 m" << "6 m" << "gen"; + + QList bandLabelList; + + for (int i = 0; i < MAX_BANDS-1; i++) { + + QLabel *label = new QLabel(bandNames.at(i), this); + label->setFrameStyle(QFrame::Box | QFrame::Raised); + label->setStyleSheet(set->getLabelStyle()); + + bandLabelList << label; + } + + // gain spinBox list + for (int i = 0; i < MAX_BANDS-1; i++) { + + QDoubleSpinBox *spinBox = new QDoubleSpinBox(); + spinBox->setStyleSheet(set->getComboBoxStyle()); + spinBox->setMinimum(38.8); + spinBox->setMaximum(100.0); + spinBox->setSingleStep(0.1); + spinBox->setStyleSheet(set->getDoubleSpinBoxStyle()); + + + //CHECKED_CONNECT(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(setAttenuatorValue(int))); + + gainSpinBoxList << spinBox; + } + + QGridLayout* grid = new QGridLayout(this); + grid->setVerticalSpacing(1); + grid->setHorizontalSpacing(1); + grid->setContentsMargins(7, 7, 5, 7); + + //grid->addWidget(attnLabel, 0, 0, 1, 2, Qt::AlignCenter); + //grid->addWidget(emptyLabel1, 0, 2, 1, 1, Qt::AlignCenter); + + for (int i = 0; i < MAX_BANDS-1; i++) { + + grid->addWidget(bandLabelList.at(i), i+1, 0, 1, 1, Qt::AlignLeft); + grid->addWidget(gainSpinBoxList.at(i), i+1, 1, 1, 1, Qt::AlignCenter); + //grid->addWidget(dBmLabel, i+1, 3, 1, 1, Qt::AlignLeft); + } + + + gainGroup = new QGroupBox(tr("Gain by Band (dB)"), this); + gainGroup->setMinimumWidth(m_minimumGroupBoxWidth); + gainGroup->setLayout(grid); + gainGroup->setStyleSheet(set->getWidgetStyle()); + gainGroup->setFont(QFont("Arial", 8)); +} + + +// ************************************************************************ + +void TransmitPAWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void TransmitPAWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +void TransmitPAWidget::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void TransmitPAWidget::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void TransmitPAWidget::mouseMoveEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void TransmitPAWidget::mousePressEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void TransmitPAWidget::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + + diff --git a/Source/src/cusdr_transmitPAWidget.h b/Source/src/cusdr_transmitPAWidget.h new file mode 100644 index 0000000..9658cfe --- /dev/null +++ b/Source/src/cusdr_transmitPAWidget.h @@ -0,0 +1,88 @@ +/** +* @file cusdr_transmitPAWidget.h +* @brief transmit PA control widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-28 +*/ + +/* + * + * Copyright 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_TRANSMIT_PA_WIDGET_H +#define _CUSDR_TRANSMIT_PA_WIDGET_H + +//#include +#include +#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" + + +class TransmitPAWidget : public QWidget { + + Q_OBJECT + +public: + TransmitPAWidget(QWidget *parent = 0); + ~TransmitPAWidget(); + + +public slots: + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + void setupConnections(); + void createGainGroup(); + +private: + Settings* set; + + QString m_message; + + QGroupBox *gainGroup; + + QList gainSpinBoxList; + +// AeroButton* micInputBtn; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + +private slots: +// void inputButtonClicked(); +// void boostButtonClicked(); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString message); +}; + +#endif // _CUSDR_TRANSMIT_PS_WIDGET_H diff --git a/Source/src/cusdr_transmitTabWidget.cpp b/Source/src/cusdr_transmitTabWidget.cpp new file mode 100644 index 0000000..d059a94 --- /dev/null +++ b/Source/src/cusdr_transmitTabWidget.cpp @@ -0,0 +1,164 @@ +/** +* @file cusdr_transmitTabWidget.cpp +* @brief Transmit settings tab widget class for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-28 +*/ + +/* + * + * Copyright 2010-2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +#include "cusdr_transmitTabWidget.h" + + +#define btn_height 15 +#define btn_width 74 +#define btn_width2 52 +#define btn_widths 40 + + +TransmitTabWidget::TransmitTabWidget(QWidget *parent) + : QTabWidget(parent) + , set(Settings::instance()) + , m_minimumWidgetWidth(set->getMinimumWidgetWidth()) + , m_minimumGroupBoxWidth(set->getMinimumGroupBoxWidth()) +{ + setStyleSheet(set->getTabWidgetStyle()); + //setMinimumWidth(m_minimumWidgetWidth); + //setMaximumWidth (247); + setContentsMargins(4, 4, 4, 0); + setMouseTracking(true); + + m_transmitOptionsWidget = new TransmitOptionsWidget(this); + m_transmitPAWidget = new TransmitPAWidget(this); + + this->addTab(m_transmitOptionsWidget, "Options"); + this->addTab(m_transmitPAWidget, "PA Settings"); + + if (!set->getPenelopePresence() && !set->getPennyLanePresence() && !QSDR::Hermes) { + + setTabEnabled(1, false); +// setTabEnabled(2, false); +// setTabEnabled(3, false); + } + +// if (!set->getAlexPresence()) +// setTabEnabled(4, false); + + setupConnections(); +} + +TransmitTabWidget::~TransmitTabWidget() { + + disconnect(set, 0, this, 0); + disconnect(this, 0, 0, 0); +} + +QSize TransmitTabWidget::sizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +QSize TransmitTabWidget::minimumSizeHint() const { + + return QSize(m_minimumWidgetWidth, height()); +} + +void TransmitTabWidget::setupConnections() { + +// CHECKED_CONNECT( +// set, +// SIGNAL(alexPresenceChanged(bool)), +// this, +// SLOT(setAlexPresence(bool))); + +// CHECKED_CONNECT( +// set, +// SIGNAL(penelopePresenceChanged(bool)), +// this, +// SLOT(setPennyPresence(bool))); +// +// CHECKED_CONNECT( +// set, +// SIGNAL(pennyLanePresenceChanged(bool)), +// this, +// SLOT(setPennyPresence(bool))); +} + +void TransmitTabWidget::setPennyPresence(bool value) { + + setTabEnabled(1, value); +// setTabEnabled(2, value); +// setTabEnabled(3, value); +} + +//void TransmitTabWidget::setAlexPresence(bool value) { +// +// setTabEnabled(4, value); +//} + +void TransmitTabWidget::addNICChangedConnection() { + + //m_hpsdrWidget->addNICChangedConnection(); +} + +void TransmitTabWidget::closeEvent(QCloseEvent *event) { + + emit closeEvent(this); + QWidget::closeEvent(event); +} + +void TransmitTabWidget::showEvent(QShowEvent *event) { + + emit showEvent(this); + QWidget::showEvent(event); +} + +void TransmitTabWidget::enterEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void TransmitTabWidget::leaveEvent(QEvent *event) { + + Q_UNUSED(event) +} + +void TransmitTabWidget::mouseMoveEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void TransmitTabWidget::mousePressEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + +void TransmitTabWidget::mouseReleaseEvent(QMouseEvent *event) { + + Q_UNUSED(event) +} + + diff --git a/Source/src/cusdr_transmitTabWidget.h b/Source/src/cusdr_transmitTabWidget.h new file mode 100644 index 0000000..d6a2766 --- /dev/null +++ b/Source/src/cusdr_transmitTabWidget.h @@ -0,0 +1,88 @@ +/** +* @file cusdr_transmitTabWidget.h +* @brief Transmit settings tab widget header file for cuSDR +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2012-08-28 +*/ + +/* + * + * Copyright 2010-2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef _CUSDR_TRANSMIT_TABWIDGET_H +#define _CUSDR_TRANSMIT_TABWIDGET_H + +//#include +#include +//#include +//#include + +#include "Util/cusdr_buttons.h" +#include "cusdr_settings.h" +#include "cusdr_transmitOptionsWidget.h" +#include "cusdr_transmitPAWidget.h" + + +class TransmitTabWidget : public QTabWidget { + + Q_OBJECT + +public: + TransmitTabWidget(QWidget *parent = 0); + ~TransmitTabWidget(); + + +public slots: + QSize sizeHint() const; + QSize minimumSizeHint() const; + void addNICChangedConnection(); + +protected: + void closeEvent(QCloseEvent *event); + void showEvent(QShowEvent *event); + void enterEvent(QEvent *event); + void leaveEvent(QEvent *event); + void mouseMoveEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event); + void mouseReleaseEvent(QMouseEvent *event); + +private: + Settings* set; + + QString m_message; + + TransmitOptionsWidget *m_transmitOptionsWidget; + TransmitPAWidget *m_transmitPAWidget; + + int m_minimumWidgetWidth; + int m_minimumGroupBoxWidth; + + void setupConnections(); + +private slots: + //void setAlexPresence(bool value); + void setPennyPresence(bool value); + +signals: + void showEvent(QObject *sender); + void closeEvent(QObject *sender); + void messageEvent(QString message); +}; + +#endif // _CUSDR_TRANSMIT_TABWIDGET_H diff --git a/Source/src/exception.h b/Source/src/exception.h new file mode 100644 index 0000000..adda4bc --- /dev/null +++ b/Source/src/exception.h @@ -0,0 +1,151 @@ +/* +* Copyright 1993-2013 NVIDIA Corporation. All rights reserved. +* +* Please refer to the NVIDIA end user license agreement (EULA) associated +* with this source code for terms and conditions that govern your use of +* this software. Any use, reproduction, disclosure, or distribution of +* this software and related documentation outside the terms of the EULA +* is strictly prohibited. +* +*/ + +/* CUda UTility Library */ +#ifndef _EXCEPTION_H_ +#define _EXCEPTION_H_ + +// includes, system +#include +#include +#include +#include + +//! Exception wrapper. +//! @param Std_Exception Exception out of namespace std for easy typing. +template +class Exception : public Std_Exception +{ + public: + + //! @brief Static construction interface + //! @return Alwayss throws ( Located_Exception) + //! @param file file in which the Exception occurs + //! @param line line in which the Exception occurs + //! @param detailed details on the code fragment causing the Exception + static void throw_it(const char *file, + const int line, + const char *detailed = "-"); + + //! Static construction interface + //! @return Alwayss throws ( Located_Exception) + //! @param file file in which the Exception occurs + //! @param line line in which the Exception occurs + //! @param detailed details on the code fragment causing the Exception + static void throw_it(const char *file, + const int line, + const std::string &detailed); + + //! Destructor + virtual ~Exception() throw(); + + private: + + //! Constructor, default (private) + Exception(); + + //! Constructor, standard + //! @param str string returned by what() + Exception(const std::string &str); + +}; + +//////////////////////////////////////////////////////////////////////////////// +//! Exception handler function for arbitrary exceptions +//! @param ex exception to handle +//////////////////////////////////////////////////////////////////////////////// +template +inline void +handleException(const Exception_Typ &ex) +{ + std::cerr << ex.what() << std::endl; + + exit(EXIT_FAILURE); +} + +//! Convenience macros + +//! Exception caused by dynamic program behavior, e.g. file does not exist +#define RUNTIME_EXCEPTION( msg) \ + Exception::throw_it( __FILE__, __LINE__, msg) + +//! Logic exception in program, e.g. an assert failed +#define LOGIC_EXCEPTION( msg) \ + Exception::throw_it( __FILE__, __LINE__, msg) + +//! Out of range exception +#define RANGE_EXCEPTION( msg) \ + Exception::throw_it( __FILE__, __LINE__, msg) + +//////////////////////////////////////////////////////////////////////////////// +//! Implementation + +// includes, system +#include + +//////////////////////////////////////////////////////////////////////////////// +//! Static construction interface. +//! @param Exception causing code fragment (file and line) and detailed infos. +//////////////////////////////////////////////////////////////////////////////// +/*static*/ template +void +Exception:: +throw_it(const char *file, const int line, const char *detailed) +{ + std::stringstream s; + + // Quiet heavy-weight but exceptions are not for + // performance / release versions + s << "Exception in file '" << file << "' in line " << line << "\n" + << "Detailed description: " << detailed << "\n"; + + throw Exception(s.str()); +} + +//////////////////////////////////////////////////////////////////////////////// +//! Static construction interface. +//! @param Exception causing code fragment (file and line) and detailed infos. +//////////////////////////////////////////////////////////////////////////////// +/*static*/ template +void +Exception:: +throw_it(const char *file, const int line, const std::string &msg) +{ + throw_it(file, line, msg.c_str()); +} + +//////////////////////////////////////////////////////////////////////////////// +//! Constructor, default (private). +//////////////////////////////////////////////////////////////////////////////// +template +Exception::Exception() : + Std_Exception("Unknown Exception.\n") +{ } + +//////////////////////////////////////////////////////////////////////////////// +//! Constructor, standard (private). +//! String returned by what(). +//////////////////////////////////////////////////////////////////////////////// +template +Exception::Exception(const std::string &s) : + Std_Exception(s) +{ } + +//////////////////////////////////////////////////////////////////////////////// +//! Destructor +//////////////////////////////////////////////////////////////////////////////// +template +Exception::~Exception() throw() { } + +// functions, exported + +#endif // #ifndef _EXCEPTION_H_ + diff --git a/Source/src/helper_cuda.h b/Source/src/helper_cuda.h new file mode 100644 index 0000000..3b3ff14 --- /dev/null +++ b/Source/src/helper_cuda.h @@ -0,0 +1,1185 @@ +/** + * Copyright 1993-2013 NVIDIA Corporation. All rights reserved. + * + * Please refer to the NVIDIA end user license agreement (EULA) associated + * with this source code for terms and conditions that govern your use of + * this software. Any use, reproduction, disclosure, or distribution of + * this software and related documentation outside the terms of the EULA + * is strictly prohibited. + * + */ + +//////////////////////////////////////////////////////////////////////////////// +// These are CUDA Helper functions for initialization and error checking + +#ifndef HELPER_CUDA_H +#define HELPER_CUDA_H + +#pragma once + +#include +#include +#include + +#include + +#ifndef EXIT_WAIVED +#define EXIT_WAIVED 2 +#endif + +// Note, it is required that your SDK sample to include the proper header files, please +// refer the CUDA examples for examples of the needed CUDA headers, which may change depending +// on which CUDA functions are used. + +// CUDA Runtime error messages +#ifdef __DRIVER_TYPES_H__ +static const char *_cudaGetErrorEnum(cudaError_t error) +{ + switch (error) + { + case cudaSuccess: + return "cudaSuccess"; + + case cudaErrorMissingConfiguration: + return "cudaErrorMissingConfiguration"; + + case cudaErrorMemoryAllocation: + return "cudaErrorMemoryAllocation"; + + case cudaErrorInitializationError: + return "cudaErrorInitializationError"; + + case cudaErrorLaunchFailure: + return "cudaErrorLaunchFailure"; + + case cudaErrorPriorLaunchFailure: + return "cudaErrorPriorLaunchFailure"; + + case cudaErrorLaunchTimeout: + return "cudaErrorLaunchTimeout"; + + case cudaErrorLaunchOutOfResources: + return "cudaErrorLaunchOutOfResources"; + + case cudaErrorInvalidDeviceFunction: + return "cudaErrorInvalidDeviceFunction"; + + case cudaErrorInvalidConfiguration: + return "cudaErrorInvalidConfiguration"; + + case cudaErrorInvalidDevice: + return "cudaErrorInvalidDevice"; + + case cudaErrorInvalidValue: + return "cudaErrorInvalidValue"; + + case cudaErrorInvalidPitchValue: + return "cudaErrorInvalidPitchValue"; + + case cudaErrorInvalidSymbol: + return "cudaErrorInvalidSymbol"; + + case cudaErrorMapBufferObjectFailed: + return "cudaErrorMapBufferObjectFailed"; + + case cudaErrorUnmapBufferObjectFailed: + return "cudaErrorUnmapBufferObjectFailed"; + + case cudaErrorInvalidHostPointer: + return "cudaErrorInvalidHostPointer"; + + case cudaErrorInvalidDevicePointer: + return "cudaErrorInvalidDevicePointer"; + + case cudaErrorInvalidTexture: + return "cudaErrorInvalidTexture"; + + case cudaErrorInvalidTextureBinding: + return "cudaErrorInvalidTextureBinding"; + + case cudaErrorInvalidChannelDescriptor: + return "cudaErrorInvalidChannelDescriptor"; + + case cudaErrorInvalidMemcpyDirection: + return "cudaErrorInvalidMemcpyDirection"; + + case cudaErrorAddressOfConstant: + return "cudaErrorAddressOfConstant"; + + case cudaErrorTextureFetchFailed: + return "cudaErrorTextureFetchFailed"; + + case cudaErrorTextureNotBound: + return "cudaErrorTextureNotBound"; + + case cudaErrorSynchronizationError: + return "cudaErrorSynchronizationError"; + + case cudaErrorInvalidFilterSetting: + return "cudaErrorInvalidFilterSetting"; + + case cudaErrorInvalidNormSetting: + return "cudaErrorInvalidNormSetting"; + + case cudaErrorMixedDeviceExecution: + return "cudaErrorMixedDeviceExecution"; + + case cudaErrorCudartUnloading: + return "cudaErrorCudartUnloading"; + + case cudaErrorUnknown: + return "cudaErrorUnknown"; + + case cudaErrorNotYetImplemented: + return "cudaErrorNotYetImplemented"; + + case cudaErrorMemoryValueTooLarge: + return "cudaErrorMemoryValueTooLarge"; + + case cudaErrorInvalidResourceHandle: + return "cudaErrorInvalidResourceHandle"; + + case cudaErrorNotReady: + return "cudaErrorNotReady"; + + case cudaErrorInsufficientDriver: + return "cudaErrorInsufficientDriver"; + + case cudaErrorSetOnActiveProcess: + return "cudaErrorSetOnActiveProcess"; + + case cudaErrorInvalidSurface: + return "cudaErrorInvalidSurface"; + + case cudaErrorNoDevice: + return "cudaErrorNoDevice"; + + case cudaErrorECCUncorrectable: + return "cudaErrorECCUncorrectable"; + + case cudaErrorSharedObjectSymbolNotFound: + return "cudaErrorSharedObjectSymbolNotFound"; + + case cudaErrorSharedObjectInitFailed: + return "cudaErrorSharedObjectInitFailed"; + + case cudaErrorUnsupportedLimit: + return "cudaErrorUnsupportedLimit"; + + case cudaErrorDuplicateVariableName: + return "cudaErrorDuplicateVariableName"; + + case cudaErrorDuplicateTextureName: + return "cudaErrorDuplicateTextureName"; + + case cudaErrorDuplicateSurfaceName: + return "cudaErrorDuplicateSurfaceName"; + + case cudaErrorDevicesUnavailable: + return "cudaErrorDevicesUnavailable"; + + case cudaErrorInvalidKernelImage: + return "cudaErrorInvalidKernelImage"; + + case cudaErrorNoKernelImageForDevice: + return "cudaErrorNoKernelImageForDevice"; + + case cudaErrorIncompatibleDriverContext: + return "cudaErrorIncompatibleDriverContext"; + + case cudaErrorPeerAccessAlreadyEnabled: + return "cudaErrorPeerAccessAlreadyEnabled"; + + case cudaErrorPeerAccessNotEnabled: + return "cudaErrorPeerAccessNotEnabled"; + + case cudaErrorDeviceAlreadyInUse: + return "cudaErrorDeviceAlreadyInUse"; + + case cudaErrorProfilerDisabled: + return "cudaErrorProfilerDisabled"; + + case cudaErrorProfilerNotInitialized: + return "cudaErrorProfilerNotInitialized"; + + case cudaErrorProfilerAlreadyStarted: + return "cudaErrorProfilerAlreadyStarted"; + + case cudaErrorProfilerAlreadyStopped: + return "cudaErrorProfilerAlreadyStopped"; + + /* Since CUDA 4.0*/ + case cudaErrorAssert: + return "cudaErrorAssert"; + + case cudaErrorTooManyPeers: + return "cudaErrorTooManyPeers"; + + case cudaErrorHostMemoryAlreadyRegistered: + return "cudaErrorHostMemoryAlreadyRegistered"; + + case cudaErrorHostMemoryNotRegistered: + return "cudaErrorHostMemoryNotRegistered"; + + /* Since CUDA 5.0 */ + case cudaErrorOperatingSystem: + return "cudaErrorOperatingSystem"; + + case cudaErrorPeerAccessUnsupported: + return "cudaErrorPeerAccessUnsupported"; + + case cudaErrorLaunchMaxDepthExceeded: + return "cudaErrorLaunchMaxDepthExceeded"; + + case cudaErrorLaunchFileScopedTex: + return "cudaErrorLaunchFileScopedTex"; + + case cudaErrorLaunchFileScopedSurf: + return "cudaErrorLaunchFileScopedSurf"; + + case cudaErrorSyncDepthExceeded: + return "cudaErrorSyncDepthExceeded"; + + case cudaErrorLaunchPendingCountExceeded: + return "cudaErrorLaunchPendingCountExceeded"; + + case cudaErrorNotPermitted: + return "cudaErrorNotPermitted"; + + case cudaErrorNotSupported: + return "cudaErrorNotSupported"; + + /* Since CUDA 6.0 */ + case cudaErrorHardwareStackError: + return "cudaErrorHardwareStackError"; + + case cudaErrorIllegalInstruction: + return "cudaErrorIllegalInstruction"; + + case cudaErrorMisalignedAddress: + return "cudaErrorMisalignedAddress"; + + case cudaErrorInvalidAddressSpace: + return "cudaErrorInvalidAddressSpace"; + + case cudaErrorInvalidPc: + return "cudaErrorInvalidPc"; + + case cudaErrorIllegalAddress: + return "cudaErrorIllegalAddress"; + + /* Since CUDA 6.5*/ +#if 0 //RRK + case cudaErrorInvalidPtx: + return "cudaErrorInvalidPtx"; + + case cudaErrorInvalidGraphicsContext: + return "cudaErrorInvalidGraphicsContext"; + + case cudaErrorStartupFailure: + return "cudaErrorStartupFailure"; + + case cudaErrorApiFailureBase: + return "cudaErrorApiFailureBase"; +#endif + } + + return ""; +} +#endif + +#ifdef __cuda_cuda_h__ +// CUDA Driver API errors +static const char *_cudaGetErrorEnum(CUresult error) +{ + switch (error) + { + case CUDA_SUCCESS: + return "CUDA_SUCCESS"; + + case CUDA_ERROR_INVALID_VALUE: + return "CUDA_ERROR_INVALID_VALUE"; + + case CUDA_ERROR_OUT_OF_MEMORY: + return "CUDA_ERROR_OUT_OF_MEMORY"; + + case CUDA_ERROR_NOT_INITIALIZED: + return "CUDA_ERROR_NOT_INITIALIZED"; + + case CUDA_ERROR_DEINITIALIZED: + return "CUDA_ERROR_DEINITIALIZED"; + + case CUDA_ERROR_PROFILER_DISABLED: + return "CUDA_ERROR_PROFILER_DISABLED"; + + case CUDA_ERROR_PROFILER_NOT_INITIALIZED: + return "CUDA_ERROR_PROFILER_NOT_INITIALIZED"; + + case CUDA_ERROR_PROFILER_ALREADY_STARTED: + return "CUDA_ERROR_PROFILER_ALREADY_STARTED"; + + case CUDA_ERROR_PROFILER_ALREADY_STOPPED: + return "CUDA_ERROR_PROFILER_ALREADY_STOPPED"; + + case CUDA_ERROR_NO_DEVICE: + return "CUDA_ERROR_NO_DEVICE"; + + case CUDA_ERROR_INVALID_DEVICE: + return "CUDA_ERROR_INVALID_DEVICE"; + + case CUDA_ERROR_INVALID_IMAGE: + return "CUDA_ERROR_INVALID_IMAGE"; + + case CUDA_ERROR_INVALID_CONTEXT: + return "CUDA_ERROR_INVALID_CONTEXT"; + + case CUDA_ERROR_CONTEXT_ALREADY_CURRENT: + return "CUDA_ERROR_CONTEXT_ALREADY_CURRENT"; + + case CUDA_ERROR_MAP_FAILED: + return "CUDA_ERROR_MAP_FAILED"; + + case CUDA_ERROR_UNMAP_FAILED: + return "CUDA_ERROR_UNMAP_FAILED"; + + case CUDA_ERROR_ARRAY_IS_MAPPED: + return "CUDA_ERROR_ARRAY_IS_MAPPED"; + + case CUDA_ERROR_ALREADY_MAPPED: + return "CUDA_ERROR_ALREADY_MAPPED"; + + case CUDA_ERROR_NO_BINARY_FOR_GPU: + return "CUDA_ERROR_NO_BINARY_FOR_GPU"; + + case CUDA_ERROR_ALREADY_ACQUIRED: + return "CUDA_ERROR_ALREADY_ACQUIRED"; + + case CUDA_ERROR_NOT_MAPPED: + return "CUDA_ERROR_NOT_MAPPED"; + + case CUDA_ERROR_NOT_MAPPED_AS_ARRAY: + return "CUDA_ERROR_NOT_MAPPED_AS_ARRAY"; + + case CUDA_ERROR_NOT_MAPPED_AS_POINTER: + return "CUDA_ERROR_NOT_MAPPED_AS_POINTER"; + + case CUDA_ERROR_ECC_UNCORRECTABLE: + return "CUDA_ERROR_ECC_UNCORRECTABLE"; + + case CUDA_ERROR_UNSUPPORTED_LIMIT: + return "CUDA_ERROR_UNSUPPORTED_LIMIT"; + + case CUDA_ERROR_CONTEXT_ALREADY_IN_USE: + return "CUDA_ERROR_CONTEXT_ALREADY_IN_USE"; + + case CUDA_ERROR_INVALID_SOURCE: + return "CUDA_ERROR_INVALID_SOURCE"; + + case CUDA_ERROR_FILE_NOT_FOUND: + return "CUDA_ERROR_FILE_NOT_FOUND"; + + case CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND: + return "CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND"; + + case CUDA_ERROR_SHARED_OBJECT_INIT_FAILED: + return "CUDA_ERROR_SHARED_OBJECT_INIT_FAILED"; + + case CUDA_ERROR_OPERATING_SYSTEM: + return "CUDA_ERROR_OPERATING_SYSTEM"; + + case CUDA_ERROR_INVALID_HANDLE: + return "CUDA_ERROR_INVALID_HANDLE"; + + case CUDA_ERROR_NOT_FOUND: + return "CUDA_ERROR_NOT_FOUND"; + + case CUDA_ERROR_NOT_READY: + return "CUDA_ERROR_NOT_READY"; + + case CUDA_ERROR_LAUNCH_FAILED: + return "CUDA_ERROR_LAUNCH_FAILED"; + + case CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES: + return "CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES"; + + case CUDA_ERROR_LAUNCH_TIMEOUT: + return "CUDA_ERROR_LAUNCH_TIMEOUT"; + + case CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING: + return "CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING"; + + case CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED: + return "CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED"; + + case CUDA_ERROR_PEER_ACCESS_NOT_ENABLED: + return "CUDA_ERROR_PEER_ACCESS_NOT_ENABLED"; + + case CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE: + return "CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE"; + + case CUDA_ERROR_CONTEXT_IS_DESTROYED: + return "CUDA_ERROR_CONTEXT_IS_DESTROYED"; + + case CUDA_ERROR_ASSERT: + return "CUDA_ERROR_ASSERT"; + + case CUDA_ERROR_TOO_MANY_PEERS: + return "CUDA_ERROR_TOO_MANY_PEERS"; + + case CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED: + return "CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED"; + + case CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED: + return "CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED"; + + case CUDA_ERROR_UNKNOWN: + return "CUDA_ERROR_UNKNOWN"; + } + + return ""; +} +#endif + +#ifdef CUBLAS_API_H_ +// cuBLAS API errors +static const char *_cudaGetErrorEnum(cublasStatus_t error) +{ + switch (error) + { + case CUBLAS_STATUS_SUCCESS: + return "CUBLAS_STATUS_SUCCESS"; + + case CUBLAS_STATUS_NOT_INITIALIZED: + return "CUBLAS_STATUS_NOT_INITIALIZED"; + + case CUBLAS_STATUS_ALLOC_FAILED: + return "CUBLAS_STATUS_ALLOC_FAILED"; + + case CUBLAS_STATUS_INVALID_VALUE: + return "CUBLAS_STATUS_INVALID_VALUE"; + + case CUBLAS_STATUS_ARCH_MISMATCH: + return "CUBLAS_STATUS_ARCH_MISMATCH"; + + case CUBLAS_STATUS_MAPPING_ERROR: + return "CUBLAS_STATUS_MAPPING_ERROR"; + + case CUBLAS_STATUS_EXECUTION_FAILED: + return "CUBLAS_STATUS_EXECUTION_FAILED"; + + case CUBLAS_STATUS_INTERNAL_ERROR: + return "CUBLAS_STATUS_INTERNAL_ERROR"; + } + + return ""; +} +#endif + +#ifdef _CUFFT_H_ +// cuFFT API errors +static const char *_cudaGetErrorEnum(cufftResult error) +{ + switch (error) + { + case CUFFT_SUCCESS: + return "CUFFT_SUCCESS"; + + case CUFFT_INVALID_PLAN: + return "CUFFT_INVALID_PLAN"; + + case CUFFT_ALLOC_FAILED: + return "CUFFT_ALLOC_FAILED"; + + case CUFFT_INVALID_TYPE: + return "CUFFT_INVALID_TYPE"; + + case CUFFT_INVALID_VALUE: + return "CUFFT_INVALID_VALUE"; + + case CUFFT_INTERNAL_ERROR: + return "CUFFT_INTERNAL_ERROR"; + + case CUFFT_EXEC_FAILED: + return "CUFFT_EXEC_FAILED"; + + case CUFFT_SETUP_FAILED: + return "CUFFT_SETUP_FAILED"; + + case CUFFT_INVALID_SIZE: + return "CUFFT_INVALID_SIZE"; + + case CUFFT_UNALIGNED_DATA: + return "CUFFT_UNALIGNED_DATA"; + + case CUFFT_INCOMPLETE_PARAMETER_LIST: + return "CUFFT_INCOMPLETE_PARAMETER_LIST"; + + case CUFFT_INVALID_DEVICE: + return "CUFFT_INVALID_DEVICE"; + + case CUFFT_PARSE_ERROR: + return "CUFFT_PARSE_ERROR"; + + case CUFFT_NO_WORKSPACE: + return "CUFFT_NO_WORKSPACE"; +#if 0 //RRK + case CUFFT_NOT_IMPLEMENTED: + return "CUFFT_NOT_IMPLEMENTED"; + + case CUFFT_LICENSE_ERROR: + return "CUFFT_LICENSE_ERROR"; +#endif + } + + return ""; +} +#endif + + +#ifdef CUSPARSEAPI +// cuSPARSE API errors +static const char *_cudaGetErrorEnum(cusparseStatus_t error) +{ + switch (error) + { + case CUSPARSE_STATUS_SUCCESS: + return "CUSPARSE_STATUS_SUCCESS"; + + case CUSPARSE_STATUS_NOT_INITIALIZED: + return "CUSPARSE_STATUS_NOT_INITIALIZED"; + + case CUSPARSE_STATUS_ALLOC_FAILED: + return "CUSPARSE_STATUS_ALLOC_FAILED"; + + case CUSPARSE_STATUS_INVALID_VALUE: + return "CUSPARSE_STATUS_INVALID_VALUE"; + + case CUSPARSE_STATUS_ARCH_MISMATCH: + return "CUSPARSE_STATUS_ARCH_MISMATCH"; + + case CUSPARSE_STATUS_MAPPING_ERROR: + return "CUSPARSE_STATUS_MAPPING_ERROR"; + + case CUSPARSE_STATUS_EXECUTION_FAILED: + return "CUSPARSE_STATUS_EXECUTION_FAILED"; + + case CUSPARSE_STATUS_INTERNAL_ERROR: + return "CUSPARSE_STATUS_INTERNAL_ERROR"; + + case CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED: + return "CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED"; + } + + return ""; +} +#endif + +#ifdef CURAND_H_ +// cuRAND API errors +static const char *_cudaGetErrorEnum(curandStatus_t error) +{ + switch (error) + { + case CURAND_STATUS_SUCCESS: + return "CURAND_STATUS_SUCCESS"; + + case CURAND_STATUS_VERSION_MISMATCH: + return "CURAND_STATUS_VERSION_MISMATCH"; + + case CURAND_STATUS_NOT_INITIALIZED: + return "CURAND_STATUS_NOT_INITIALIZED"; + + case CURAND_STATUS_ALLOCATION_FAILED: + return "CURAND_STATUS_ALLOCATION_FAILED"; + + case CURAND_STATUS_TYPE_ERROR: + return "CURAND_STATUS_TYPE_ERROR"; + + case CURAND_STATUS_OUT_OF_RANGE: + return "CURAND_STATUS_OUT_OF_RANGE"; + + case CURAND_STATUS_LENGTH_NOT_MULTIPLE: + return "CURAND_STATUS_LENGTH_NOT_MULTIPLE"; + + case CURAND_STATUS_DOUBLE_PRECISION_REQUIRED: + return "CURAND_STATUS_DOUBLE_PRECISION_REQUIRED"; + + case CURAND_STATUS_LAUNCH_FAILURE: + return "CURAND_STATUS_LAUNCH_FAILURE"; + + case CURAND_STATUS_PREEXISTING_FAILURE: + return "CURAND_STATUS_PREEXISTING_FAILURE"; + + case CURAND_STATUS_INITIALIZATION_FAILED: + return "CURAND_STATUS_INITIALIZATION_FAILED"; + + case CURAND_STATUS_ARCH_MISMATCH: + return "CURAND_STATUS_ARCH_MISMATCH"; + + case CURAND_STATUS_INTERNAL_ERROR: + return "CURAND_STATUS_INTERNAL_ERROR"; + } + + return ""; +} +#endif + +#ifdef NV_NPPIDEFS_H +// NPP API errors +static const char *_cudaGetErrorEnum(NppStatus error) +{ + switch (error) + { + case NPP_NOT_SUPPORTED_MODE_ERROR: + return "NPP_NOT_SUPPORTED_MODE_ERROR"; + + case NPP_ROUND_MODE_NOT_SUPPORTED_ERROR: + return "NPP_ROUND_MODE_NOT_SUPPORTED_ERROR"; + + case NPP_RESIZE_NO_OPERATION_ERROR: + return "NPP_RESIZE_NO_OPERATION_ERROR"; + + case NPP_NOT_SUFFICIENT_COMPUTE_CAPABILITY: + return "NPP_NOT_SUFFICIENT_COMPUTE_CAPABILITY"; + +#if ((NPP_VERSION_MAJOR << 12) + (NPP_VERSION_MINOR << 4)) <= 0x5000 + + case NPP_BAD_ARG_ERROR: + return "NPP_BAD_ARGUMENT_ERROR"; + + case NPP_COEFF_ERROR: + return "NPP_COEFFICIENT_ERROR"; + + case NPP_RECT_ERROR: + return "NPP_RECTANGLE_ERROR"; + + case NPP_QUAD_ERROR: + return "NPP_QUADRANGLE_ERROR"; + + case NPP_MEM_ALLOC_ERR: + return "NPP_MEMORY_ALLOCATION_ERROR"; + + case NPP_HISTO_NUMBER_OF_LEVELS_ERROR: + return "NPP_HISTOGRAM_NUMBER_OF_LEVELS_ERROR"; + + case NPP_INVALID_INPUT: + return "NPP_INVALID_INPUT"; + + case NPP_POINTER_ERROR: + return "NPP_POINTER_ERROR"; + + case NPP_WARNING: + return "NPP_WARNING"; + + case NPP_ODD_ROI_WARNING: + return "NPP_ODD_ROI_WARNING"; +#else + + // These are for CUDA 5.5 or higher + case NPP_BAD_ARGUMENT_ERROR: + return "NPP_BAD_ARGUMENT_ERROR"; + + case NPP_COEFFICIENT_ERROR: + return "NPP_COEFFICIENT_ERROR"; + + case NPP_RECTANGLE_ERROR: + return "NPP_RECTANGLE_ERROR"; + + case NPP_QUADRANGLE_ERROR: + return "NPP_QUADRANGLE_ERROR"; + + case NPP_MEMORY_ALLOCATION_ERR: + return "NPP_MEMORY_ALLOCATION_ERROR"; + + case NPP_HISTOGRAM_NUMBER_OF_LEVELS_ERROR: + return "NPP_HISTOGRAM_NUMBER_OF_LEVELS_ERROR"; + + case NPP_INVALID_HOST_POINTER_ERROR: + return "NPP_INVALID_HOST_POINTER_ERROR"; + + case NPP_INVALID_DEVICE_POINTER_ERROR: + return "NPP_INVALID_DEVICE_POINTER_ERROR"; +#endif + + case NPP_LUT_NUMBER_OF_LEVELS_ERROR: + return "NPP_LUT_NUMBER_OF_LEVELS_ERROR"; + + case NPP_TEXTURE_BIND_ERROR: + return "NPP_TEXTURE_BIND_ERROR"; + + case NPP_WRONG_INTERSECTION_ROI_ERROR: + return "NPP_WRONG_INTERSECTION_ROI_ERROR"; + + case NPP_NOT_EVEN_STEP_ERROR: + return "NPP_NOT_EVEN_STEP_ERROR"; + + case NPP_INTERPOLATION_ERROR: + return "NPP_INTERPOLATION_ERROR"; + + case NPP_RESIZE_FACTOR_ERROR: + return "NPP_RESIZE_FACTOR_ERROR"; + + case NPP_HAAR_CLASSIFIER_PIXEL_MATCH_ERROR: + return "NPP_HAAR_CLASSIFIER_PIXEL_MATCH_ERROR"; + + +#if ((NPP_VERSION_MAJOR << 12) + (NPP_VERSION_MINOR << 4)) <= 0x5000 + + case NPP_MEMFREE_ERR: + return "NPP_MEMFREE_ERR"; + + case NPP_MEMSET_ERR: + return "NPP_MEMSET_ERR"; + + case NPP_MEMCPY_ERR: + return "NPP_MEMCPY_ERROR"; + + case NPP_MIRROR_FLIP_ERR: + return "NPP_MIRROR_FLIP_ERR"; +#else + + case NPP_MEMFREE_ERROR: + return "NPP_MEMFREE_ERROR"; + + case NPP_MEMSET_ERROR: + return "NPP_MEMSET_ERROR"; + + case NPP_MEMCPY_ERROR: + return "NPP_MEMCPY_ERROR"; + + case NPP_MIRROR_FLIP_ERROR: + return "NPP_MIRROR_FLIP_ERROR"; +#endif + + case NPP_ALIGNMENT_ERROR: + return "NPP_ALIGNMENT_ERROR"; + + case NPP_STEP_ERROR: + return "NPP_STEP_ERROR"; + + case NPP_SIZE_ERROR: + return "NPP_SIZE_ERROR"; + + case NPP_NULL_POINTER_ERROR: + return "NPP_NULL_POINTER_ERROR"; + + case NPP_CUDA_KERNEL_EXECUTION_ERROR: + return "NPP_CUDA_KERNEL_EXECUTION_ERROR"; + + case NPP_NOT_IMPLEMENTED_ERROR: + return "NPP_NOT_IMPLEMENTED_ERROR"; + + case NPP_ERROR: + return "NPP_ERROR"; + + case NPP_SUCCESS: + return "NPP_SUCCESS"; + + case NPP_WRONG_INTERSECTION_QUAD_WARNING: + return "NPP_WRONG_INTERSECTION_QUAD_WARNING"; + + case NPP_MISALIGNED_DST_ROI_WARNING: + return "NPP_MISALIGNED_DST_ROI_WARNING"; + + case NPP_AFFINE_QUAD_INCORRECT_WARNING: + return "NPP_AFFINE_QUAD_INCORRECT_WARNING"; + + case NPP_DOUBLE_SIZE_WARNING: + return "NPP_DOUBLE_SIZE_WARNING"; + + case NPP_WRONG_INTERSECTION_ROI_WARNING: + return "NPP_WRONG_INTERSECTION_ROI_WARNING"; + +#if ((NPP_VERSION_MAJOR << 12) + (NPP_VERSION_MINOR << 4)) >= 0x6000 + /* These are 6.0 or higher */ + case NPP_LUT_PALETTE_BITSIZE_ERROR: + return "NPP_LUT_PALETTE_BITSIZE_ERROR"; + + case NPP_ZC_MODE_NOT_SUPPORTED_ERROR: + return "NPP_ZC_MODE_NOT_SUPPORTED_ERROR"; + + case NPP_QUALITY_INDEX_ERROR: + return "NPP_QUALITY_INDEX_ERROR"; + + case NPP_CHANNEL_ORDER_ERROR: + return "NPP_CHANNEL_ORDER_ERROR"; + + case NPP_ZERO_MASK_VALUE_ERROR: + return "NPP_ZERO_MASK_VALUE_ERROR"; + + case NPP_NUMBER_OF_CHANNELS_ERROR: + return "NPP_NUMBER_OF_CHANNELS_ERROR"; + + case NPP_COI_ERROR: + return "NPP_COI_ERROR"; + + case NPP_DIVISOR_ERROR: + return "NPP_DIVISOR_ERROR"; + + case NPP_CHANNEL_ERROR: + return "NPP_CHANNEL_ERROR"; + + case NPP_STRIDE_ERROR: + return "NPP_STRIDE_ERROR"; + + case NPP_ANCHOR_ERROR: + return "NPP_ANCHOR_ERROR"; + + case NPP_MASK_SIZE_ERROR: + return "NPP_MASK_SIZE_ERROR"; + + case NPP_MOMENT_00_ZERO_ERROR: + return "NPP_MOMENT_00_ZERO_ERROR"; + + case NPP_THRESHOLD_NEGATIVE_LEVEL_ERROR: + return "NPP_THRESHOLD_NEGATIVE_LEVEL_ERROR"; + + case NPP_THRESHOLD_ERROR: + return "NPP_THRESHOLD_ERROR"; + + case NPP_CONTEXT_MATCH_ERROR: + return "NPP_CONTEXT_MATCH_ERROR"; + + case NPP_FFT_FLAG_ERROR: + return "NPP_FFT_FLAG_ERROR"; + + case NPP_FFT_ORDER_ERROR: + return "NPP_FFT_ORDER_ERROR"; + + case NPP_SCALE_RANGE_ERROR: + return "NPP_SCALE_RANGE_ERROR"; + + case NPP_DATA_TYPE_ERROR: + return "NPP_DATA_TYPE_ERROR"; + + case NPP_OUT_OFF_RANGE_ERROR: + return "NPP_OUT_OFF_RANGE_ERROR"; + + case NPP_DIVIDE_BY_ZERO_ERROR: + return "NPP_DIVIDE_BY_ZERO_ERROR"; + + case NPP_RANGE_ERROR: + return "NPP_RANGE_ERROR"; + + case NPP_NO_MEMORY_ERROR: + return "NPP_NO_MEMORY_ERROR"; + + case NPP_ERROR_RESERVED: + return "NPP_ERROR_RESERVED"; + + case NPP_NO_OPERATION_WARNING: + return "NPP_NO_OPERATION_WARNING"; + + case NPP_DIVIDE_BY_ZERO_WARNING: + return "NPP_DIVIDE_BY_ZERO_WARNING"; +#endif + + } + + return ""; +} +#endif + +#ifdef __DRIVER_TYPES_H__ +#ifndef DEVICE_RESET +#define DEVICE_RESET cudaDeviceReset(); +#endif +#else +#ifndef DEVICE_RESET +#define DEVICE_RESET +#endif +#endif + +template< typename T > +void check(T result, char const *const func, const char *const file, int const line) +{ + if (result) + { + fprintf(stderr, "CUDA error at %s:%d code=%d(%s) \"%s\" \n", + file, line, static_cast(result), _cudaGetErrorEnum(result), func); + DEVICE_RESET + // Make sure we call CUDA Device Reset before exiting + exit(EXIT_FAILURE); + } +} + +#ifdef __DRIVER_TYPES_H__ +// This will output the proper CUDA error strings in the event that a CUDA host call returns an error +#define checkCudaErrors(val) check ( (val), #val, __FILE__, __LINE__ ) + +// This will output the proper error string when calling cudaGetLastError +#define getLastCudaError(msg) __getLastCudaError (msg, __FILE__, __LINE__) + +inline void __getLastCudaError(const char *errorMessage, const char *file, const int line) +{ + cudaError_t err = cudaGetLastError(); + + if (cudaSuccess != err) + { + fprintf(stderr, "%s(%i) : getLastCudaError() CUDA error : %s : (%d) %s.\n", + file, line, errorMessage, (int)err, cudaGetErrorString(err)); + DEVICE_RESET + exit(EXIT_FAILURE); + } +} +#endif + +#ifndef MAX +#define MAX(a,b) (a > b ? a : b) +#endif + +// Beginning of GPU Architecture definitions +inline int _ConvertSMVer2Cores(int major, int minor) +{ + // Defines for GPU Architecture types (using the SM version to determine the # of cores per SM + typedef struct + { + int SM; // 0xMm (hexidecimal notation), M = SM Major version, and m = SM minor version + int Cores; + } sSMtoCores; + + sSMtoCores nGpuArchCoresPerSM[] = + { + { 0x10, 8 }, // Tesla Generation (SM 1.0) G80 class + { 0x11, 8 }, // Tesla Generation (SM 1.1) G8x class + { 0x12, 8 }, // Tesla Generation (SM 1.2) G9x class + { 0x13, 8 }, // Tesla Generation (SM 1.3) GT200 class + { 0x20, 32 }, // Fermi Generation (SM 2.0) GF100 class + { 0x21, 48 }, // Fermi Generation (SM 2.1) GF10x class + { 0x30, 192}, // Kepler Generation (SM 3.0) GK10x class + { 0x32, 192}, // Kepler Generation (SM 3.2) GK10x class + { 0x35, 192}, // Kepler Generation (SM 3.5) GK11x class + { 0x37, 192}, // Kepler Generation (SM 3.7) GK21x class + { 0x50, 128}, // Maxwell Generation (SM 5.0) GM10x class + { -1, -1 } + }; + + int index = 0; + + while (nGpuArchCoresPerSM[index].SM != -1) + { + if (nGpuArchCoresPerSM[index].SM == ((major << 4) + minor)) + { + return nGpuArchCoresPerSM[index].Cores; + } + + index++; + } + + // If we don't find the values, we default use the previous one to run properly + printf("MapSMtoCores for SM %d.%d is undefined. Default to use %d Cores/SM\n", major, minor, nGpuArchCoresPerSM[index-1].Cores); + return nGpuArchCoresPerSM[index-1].Cores; +} +// end of GPU Architecture definitions + +#ifdef __CUDA_RUNTIME_H__ +// General GPU Device CUDA Initialization +inline int gpuDeviceInit(int devID) +{ + int device_count; + checkCudaErrors(cudaGetDeviceCount(&device_count)); + + if (device_count == 0) + { + fprintf(stderr, "gpuDeviceInit() CUDA error: no devices supporting CUDA.\n"); + exit(EXIT_FAILURE); + } + + if (devID < 0) + { + devID = 0; + } + + if (devID > device_count-1) + { + fprintf(stderr, "\n"); + fprintf(stderr, ">> %d CUDA capable GPU device(s) detected. <<\n", device_count); + fprintf(stderr, ">> gpuDeviceInit (-device=%d) is not a valid GPU device. <<\n", devID); + fprintf(stderr, "\n"); + return -devID; + } + + cudaDeviceProp deviceProp; + checkCudaErrors(cudaGetDeviceProperties(&deviceProp, devID)); + + if (deviceProp.computeMode == cudaComputeModeProhibited) + { + fprintf(stderr, "Error: device is running in , no threads can use ::cudaSetDevice().\n"); + return -1; + } + + if (deviceProp.major < 1) + { + fprintf(stderr, "gpuDeviceInit(): GPU device does not support CUDA.\n"); + exit(EXIT_FAILURE); + } + + checkCudaErrors(cudaSetDevice(devID)); + printf("gpuDeviceInit() CUDA Device [%d]: \"%s\n", devID, deviceProp.name); + + return devID; +} + +// This function returns the best GPU (with maximum GFLOPS) +inline int gpuGetMaxGflopsDeviceId() +{ + int current_device = 0, sm_per_multiproc = 0; + int max_perf_device = 0; + int device_count = 0, best_SM_arch = 0; + int devices_prohibited = 0; + + unsigned long long max_compute_perf = 0; + cudaDeviceProp deviceProp; + cudaGetDeviceCount(&device_count); + + checkCudaErrors(cudaGetDeviceCount(&device_count)); + + if (device_count == 0) + { + fprintf(stderr, "gpuGetMaxGflopsDeviceId() CUDA error: no devices supporting CUDA.\n"); + exit(EXIT_FAILURE); + } + + // Find the best major SM Architecture GPU device + while (current_device < device_count) + { + cudaGetDeviceProperties(&deviceProp, current_device); + + // If this GPU is not running on Compute Mode prohibited, then we can add it to the list + if (deviceProp.computeMode != cudaComputeModeProhibited) + { + if (deviceProp.major > 0 && deviceProp.major < 9999) + { + best_SM_arch = MAX(best_SM_arch, deviceProp.major); + } + } + else + { + devices_prohibited++; + } + + current_device++; + } + + if (devices_prohibited == device_count) + { + fprintf(stderr, "gpuGetMaxGflopsDeviceId() CUDA error: all devices have compute mode prohibited.\n"); + exit(EXIT_FAILURE); + } + + // Find the best CUDA capable GPU device + current_device = 0; + + while (current_device < device_count) + { + cudaGetDeviceProperties(&deviceProp, current_device); + + // If this GPU is not running on Compute Mode prohibited, then we can add it to the list + if (deviceProp.computeMode != cudaComputeModeProhibited) + { + if (deviceProp.major == 9999 && deviceProp.minor == 9999) + { + sm_per_multiproc = 1; + } + else + { + sm_per_multiproc = _ConvertSMVer2Cores(deviceProp.major, deviceProp.minor); + } + + unsigned long long compute_perf = (unsigned long long) deviceProp.multiProcessorCount * sm_per_multiproc * deviceProp.clockRate; + + if (compute_perf > max_compute_perf) + { + // If we find GPU with SM major > 2, search only these + if (best_SM_arch > 2) + { + // If our device==dest_SM_arch, choose this, or else pass + if (deviceProp.major == best_SM_arch) + { + max_compute_perf = compute_perf; + max_perf_device = current_device; + } + } + else + { + max_compute_perf = compute_perf; + max_perf_device = current_device; + } + } + } + + ++current_device; + } + + return max_perf_device; +} + + +// Initialization code to find the best CUDA Device +inline int findCudaDevice(int argc, const char **argv) +{ + cudaDeviceProp deviceProp; + int devID = 0; + + // If the command-line has a device number specified, use it + if (checkCmdLineFlag(argc, argv, "device")) + { + devID = getCmdLineArgumentInt(argc, argv, "device="); + + if (devID < 0) + { + printf("Invalid command line parameter\n "); + exit(EXIT_FAILURE); + } + else + { + devID = gpuDeviceInit(devID); + + if (devID < 0) + { + printf("exiting...\n"); + exit(EXIT_FAILURE); + } + } + } + else + { + // Otherwise pick the device with highest Gflops/s + devID = gpuGetMaxGflopsDeviceId(); + checkCudaErrors(cudaSetDevice(devID)); + checkCudaErrors(cudaGetDeviceProperties(&deviceProp, devID)); + printf("GPU Device %d: \"%s\" with compute capability %d.%d\n\n", devID, deviceProp.name, deviceProp.major, deviceProp.minor); + } + + return devID; +} + +// General check for CUDA GPU SM Capabilities +inline bool checkCudaCapabilities(int major_version, int minor_version) +{ + cudaDeviceProp deviceProp; + deviceProp.major = 0; + deviceProp.minor = 0; + int dev; + + checkCudaErrors(cudaGetDevice(&dev)); + checkCudaErrors(cudaGetDeviceProperties(&deviceProp, dev)); + + if ((deviceProp.major > major_version) || + (deviceProp.major == major_version && deviceProp.minor >= minor_version)) + { + printf(" Device %d: <%16s >, Compute SM %d.%d detected\n", dev, deviceProp.name, deviceProp.major, deviceProp.minor); + return true; + } + else + { + printf(" No GPU device was found that can support CUDA compute capability %d.%d.\n", major_version, minor_version); + return false; + } +} +#endif + +// end of CUDA Helper Functions + + +#endif diff --git a/Source/src/helper_functions.h b/Source/src/helper_functions.h new file mode 100644 index 0000000..11538ba --- /dev/null +++ b/Source/src/helper_functions.h @@ -0,0 +1,42 @@ +/** + * Copyright 1993-2013 NVIDIA Corporation. All rights reserved. + * + * Please refer to the NVIDIA end user license agreement (EULA) associated + * with this source code for terms and conditions that govern your use of + * this software. Any use, reproduction, disclosure, or distribution of + * this software and related documentation outside the terms of the EULA + * is strictly prohibited. + * + */ + +// These are helper functions for the SDK samples (string parsing, timers, image helpers, etc) +#ifndef HELPER_FUNCTIONS_H +#define HELPER_FUNCTIONS_H + +#ifdef WIN32 +#pragma warning(disable:4996) +#endif + +// includes, project +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +// includes, timer, string parsing, image helpers +#include // helper functions for timers +#include // helper functions for string parsing +#include // helper functions for image compare, dump, data comparisons + +#ifndef EXIT_WAIVED +#define EXIT_WAIVED 2 +#endif + +#endif // HELPER_FUNCTIONS_H diff --git a/Source/src/helper_image.h b/Source/src/helper_image.h new file mode 100644 index 0000000..4e8b25c --- /dev/null +++ b/Source/src/helper_image.h @@ -0,0 +1,1110 @@ +/** + * Copyright 1993-2013 NVIDIA Corporation. All rights reserved. + * + * Please refer to the NVIDIA end user license agreement (EULA) associated + * with this source code for terms and conditions that govern your use of + * this software. Any use, reproduction, disclosure, or distribution of + * this software and related documentation outside the terms of the EULA + * is strictly prohibited. + * + */ + +// These are helper functions for the SDK samples (image,bitmap) +#ifndef HELPER_IMAGE_H +#define HELPER_IMAGE_H + +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifndef MIN +#define MIN(a,b) ((a < b) ? a : b) +#endif +#ifndef MAX +#define MAX(a,b) ((a > b) ? a : b) +#endif + +#ifndef EXIT_WAIVED +#define EXIT_WAIVED 2 +#endif + +#include + +// namespace unnamed (internal) +namespace +{ + //! size of PGM file header + const unsigned int PGMHeaderSize = 0x40; + + // types + + //! Data converter from unsigned char / unsigned byte to type T + template + struct ConverterFromUByte; + + //! Data converter from unsigned char / unsigned byte + template<> + struct ConverterFromUByte + { + //! Conversion operator + //! @return converted value + //! @param val value to convert + float operator()(const unsigned char &val) + { + return static_cast(val); + } + }; + + //! Data converter from unsigned char / unsigned byte to float + template<> + struct ConverterFromUByte + { + //! Conversion operator + //! @return converted value + //! @param val value to convert + float operator()(const unsigned char &val) + { + return static_cast(val) / 255.0f; + } + }; + + //! Data converter from unsigned char / unsigned byte to type T + template + struct ConverterToUByte; + + //! Data converter from unsigned char / unsigned byte to unsigned int + template<> + struct ConverterToUByte + { + //! Conversion operator (essentially a passthru + //! @return converted value + //! @param val value to convert + unsigned char operator()(const unsigned char &val) + { + return val; + } + }; + + //! Data converter from unsigned char / unsigned byte to unsigned int + template<> + struct ConverterToUByte + { + //! Conversion operator + //! @return converted value + //! @param val value to convert + unsigned char operator()(const float &val) + { + return static_cast(val * 255.0f); + } + }; +} + +#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) +#ifndef FOPEN +#define FOPEN(fHandle,filename,mode) fopen_s(&fHandle, filename, mode) +#endif +#ifndef FOPEN_FAIL +#define FOPEN_FAIL(result) (result != 0) +#endif +#ifndef SSCANF +#define SSCANF sscanf_s +#endif +#else +#ifndef FOPEN +#define FOPEN(fHandle,filename,mode) (fHandle = fopen(filename, mode)) +#endif +#ifndef FOPEN_FAIL +#define FOPEN_FAIL(result) (result == NULL) +#endif +#ifndef SSCANF +#define SSCANF sscanf +#endif +#endif + +inline bool +__loadPPM(const char *file, unsigned char **data, + unsigned int *w, unsigned int *h, unsigned int *channels) +{ + FILE *fp = NULL; + + if (FOPEN_FAIL(FOPEN(fp, file, "rb"))) + { + std::cerr << "__LoadPPM() : Failed to open file: " << file << std::endl; + return false; + } + + // check header + char header[PGMHeaderSize]; + + if (fgets(header, PGMHeaderSize, fp) == NULL) + { + std::cerr << "__LoadPPM() : reading PGM header returned NULL" << std::endl; + return false; + } + + if (strncmp(header, "P5", 2) == 0) + { + *channels = 1; + } + else if (strncmp(header, "P6", 2) == 0) + { + *channels = 3; + } + else + { + std::cerr << "__LoadPPM() : File is not a PPM or PGM image" << std::endl; + *channels = 0; + return false; + } + + // parse header, read maxval, width and height + unsigned int width = 0; + unsigned int height = 0; + unsigned int maxval = 0; + unsigned int i = 0; + + while (i < 3) + { + if (fgets(header, PGMHeaderSize, fp) == NULL) + { + std::cerr << "__LoadPPM() : reading PGM header returned NULL" << std::endl; + return false; + } + + if (header[0] == '#') + { + continue; + } + + if (i == 0) + { + i += SSCANF(header, "%u %u %u", &width, &height, &maxval); + } + else if (i == 1) + { + i += SSCANF(header, "%u %u", &height, &maxval); + } + else if (i == 2) + { + i += SSCANF(header, "%u", &maxval); + } + } + + // check if given handle for the data is initialized + if (NULL != *data) + { + if (*w != width || *h != height) + { + std::cerr << "__LoadPPM() : Invalid image dimensions." << std::endl; + } + } + else + { + *data = (unsigned char *) malloc(sizeof(unsigned char) * width * height **channels); + *w = width; + *h = height; + } + + // read and close file + if (fread(*data, sizeof(unsigned char), width * height **channels, fp) == 0) + { + std::cerr << "__LoadPPM() read data returned error." << std::endl; + } + + fclose(fp); + + return true; +} + +template +inline bool +sdkLoadPGM(const char *file, T **data, unsigned int *w, unsigned int *h) +{ + unsigned char *idata = NULL; + unsigned int channels; + + if (true != __loadPPM(file, &idata, w, h, &channels)) + { + return false; + } + + unsigned int size = *w **h * channels; + + // initialize mem if necessary + // the correct size is checked / set in loadPGMc() + if (NULL == *data) + { + *data = (T *) malloc(sizeof(T) * size); + } + + // copy and cast data + std::transform(idata, idata + size, *data, ConverterFromUByte()); + + free(idata); + + return true; +} + +template +inline bool +sdkLoadPPM4(const char *file, T **data, + unsigned int *w,unsigned int *h) +{ + unsigned char *idata = 0; + unsigned int channels; + + if (__loadPPM(file, &idata, w, h, &channels)) + { + // pad 4th component + int size = *w **h; + // keep the original pointer + unsigned char *idata_orig = idata; + *data = (T *) malloc(sizeof(T) * size * 4); + unsigned char *ptr = *data; + + for (int i=0; i 0); + assert(h > 0); + + std::fstream fh(file, std::fstream::out | std::fstream::binary); + + if (fh.bad()) + { + std::cerr << "__savePPM() : Opening file failed." << std::endl; + return false; + } + + if (channels == 1) + { + fh << "P5\n"; + } + else if (channels == 3) + { + fh << "P6\n"; + } + else + { + std::cerr << "__savePPM() : Invalid number of channels." << std::endl; + return false; + } + + fh << w << "\n" << h << "\n" << 0xff << std::endl; + + for (unsigned int i = 0; (i < (w*h*channels)) && fh.good(); ++i) + { + fh << data[i]; + } + + fh.flush(); + + if (fh.bad()) + { + std::cerr << "__savePPM() : Writing data failed." << std::endl; + return false; + } + + fh.close(); + + return true; +} + +template +inline bool +sdkSavePGM(const char *file, T *data, unsigned int w, unsigned int h) +{ + unsigned int size = w * h; + unsigned char *idata = + (unsigned char *) malloc(sizeof(unsigned char) * size); + + std::transform(data, data + size, idata, ConverterToUByte()); + + // write file + bool result = __savePPM(file, idata, w, h, 1); + + // cleanup + free(idata); + + return result; +} + +inline bool +sdkSavePPM4ub(const char *file, unsigned char *data, + unsigned int w, unsigned int h) +{ + // strip 4th component + int size = w * h; + unsigned char *ndata = (unsigned char *) malloc(sizeof(unsigned char) * size*3); + unsigned char *ptr = ndata; + + for (int i=0; i +inline bool +sdkReadFile(const char *filename, T **data, unsigned int *len, bool verbose) +{ + // check input arguments + assert(NULL != filename); + assert(NULL != len); + + // intermediate storage for the data read + std::vector data_read; + + // open file for reading + FILE *fh = NULL; + + // check if filestream is valid + if (FOPEN_FAIL(FOPEN(fh, filename, "r"))) + { + printf("Unable to open input file: %s\n", filename); + return false; + } + + // read all data elements + T token; + + while (!feof(fh)) + { + fscanf(fh, "%f", &token); + data_read.push_back(token); + } + + // the last element is read twice + data_read.pop_back(); + fclose(fh); + + // check if the given handle is already initialized + if (NULL != *data) + { + if (*len != data_read.size()) + { + std::cerr << "sdkReadFile() : Initialized memory given but " + << "size mismatch with signal read " + << "(data read / data init = " << (unsigned int)data_read.size() + << " / " << *len << ")" << std::endl; + + return false; + } + } + else + { + // allocate storage for the data read + *data = (T *) malloc(sizeof(T) * data_read.size()); + // store signal size + *len = static_cast(data_read.size()); + } + + // copy data + memcpy(*data, &data_read.front(), sizeof(T) * data_read.size()); + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +//! Read file \filename and return the data +//! @return bool if reading the file succeeded, otherwise false +//! @param filename name of the source file +//! @param data uninitialized pointer, returned initialized and pointing to +//! the data read +//! @param len number of data elements in data, -1 on error +////////////////////////////////////////////////////////////////////////////// +template +inline bool +sdkReadFileBlocks(const char *filename, T **data, unsigned int *len, unsigned int block_num, unsigned int block_size, bool verbose) +{ + // check input arguments + assert(NULL != filename); + assert(NULL != len); + + // open file for reading + FILE *fh = fopen(filename, "rb"); + + if (fh == NULL && verbose) + { + std::cerr << "sdkReadFile() : Opening file failed." << std::endl; + return false; + } + + // check if the given handle is already initialized + // allocate storage for the data read + data[block_num] = (T *) malloc(block_size); + + // read all data elements + fseek(fh, block_num * block_size, SEEK_SET); + *len = fread(data[block_num], sizeof(T), block_size/sizeof(T), fh); + + fclose(fh); + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +//! Write a data file \filename +//! @return true if writing the file succeeded, otherwise false +//! @param filename name of the source file +//! @param data data to write +//! @param len number of data elements in data, -1 on error +//! @param epsilon epsilon for comparison +////////////////////////////////////////////////////////////////////////////// +template +inline bool +sdkWriteFile(const char *filename, const T *data, unsigned int len, + const S epsilon, bool verbose, bool append = false) +{ + assert(NULL != filename); + assert(NULL != data); + + // open file for writing + // if (append) { + std::fstream fh(filename, std::fstream::out | std::fstream::ate); + + if (verbose) + { + std::cerr << "sdkWriteFile() : Open file " << filename << " for write/append." << std::endl; + } + + /* } else { + std::fstream fh(filename, std::fstream::out); + if (verbose) { + std::cerr << "sdkWriteFile() : Open file " << filename << " for write." << std::endl; + } + } + */ + + // check if filestream is valid + if (! fh.good()) + { + if (verbose) + { + std::cerr << "sdkWriteFile() : Opening file failed." << std::endl; + } + + return false; + } + + // first write epsilon + fh << "# " << epsilon << "\n"; + + // write data + for (unsigned int i = 0; (i < len) && (fh.good()); ++i) + { + fh << data[i] << ' '; + } + + // Check if writing succeeded + if (! fh.good()) + { + if (verbose) + { + std::cerr << "sdkWriteFile() : Writing file failed." << std::endl; + } + + return false; + } + + // file ends with nl + fh << std::endl; + + return true; +} + +////////////////////////////////////////////////////////////////////////////// +//! Compare two arrays of arbitrary type +//! @return true if \a reference and \a data are identical, otherwise false +//! @param reference timer_interface to the reference data / gold image +//! @param data handle to the computed data +//! @param len number of elements in reference and data +//! @param epsilon epsilon to use for the comparison +////////////////////////////////////////////////////////////////////////////// +template +inline bool +compareData(const T *reference, const T *data, const unsigned int len, + const S epsilon, const float threshold) +{ + assert(epsilon >= 0); + + bool result = true; + unsigned int error_count = 0; + + for (unsigned int i = 0; i < len; ++i) + { + float diff = (float)reference[i] - (float)data[i]; + bool comp = (diff <= epsilon) && (diff >= -epsilon); + result &= comp; + + error_count += !comp; + +#if 0 + + if (! comp) + { + std::cerr << "ERROR, i = " << i << ",\t " + << reference[i] << " / " + << data[i] + << " (reference / data)\n"; + } + +#endif + } + + if (threshold == 0.0f) + { + return (result) ? true : false; + } + else + { + if (error_count) + { + printf("%4.2f(%%) of bytes mismatched (count=%d)\n", (float)error_count*100/(float)len, error_count); + } + + return (len*threshold > error_count) ? true : false; + } +} + +#ifndef __MIN_EPSILON_ERROR +#define __MIN_EPSILON_ERROR 1e-3f +#endif + +////////////////////////////////////////////////////////////////////////////// +//! Compare two arrays of arbitrary type +//! @return true if \a reference and \a data are identical, otherwise false +//! @param reference handle to the reference data / gold image +//! @param data handle to the computed data +//! @param len number of elements in reference and data +//! @param epsilon epsilon to use for the comparison +//! @param epsilon threshold % of (# of bytes) for pass/fail +////////////////////////////////////////////////////////////////////////////// +template +inline bool +compareDataAsFloatThreshold(const T *reference, const T *data, const unsigned int len, + const S epsilon, const float threshold) +{ + assert(epsilon >= 0); + + // If we set epsilon to be 0, let's set a minimum threshold + float max_error = MAX((float)epsilon, __MIN_EPSILON_ERROR); + int error_count = 0; + bool result = true; + + for (unsigned int i = 0; i < len; ++i) + { + float diff = fabs((float)reference[i] - (float)data[i]); + bool comp = (diff < max_error); + result &= comp; + + if (! comp) + { + error_count++; +#if 0 + + if (error_count < 50) + { + printf("\n ERROR(epsilon=%4.3f), i=%d, (ref)0x%02x / (data)0x%02x / (diff)%d\n", + max_error, i, + *(unsigned int *)&reference[i], + *(unsigned int *)&data[i], + (unsigned int)diff); + } + +#endif + } + } + + if (threshold == 0.0f) + { + if (error_count) + { + printf("total # of errors = %d\n", error_count); + } + + return (error_count == 0) ? true : false; + } + else + { + if (error_count) + { + printf("%4.2f(%%) of bytes mismatched (count=%d)\n", (float)error_count*100/(float)len, error_count); + } + + return ((len*threshold > error_count) ? true : false); + } +} + +inline +void sdkDumpBin(void *data, unsigned int bytes, const char *filename) +{ + printf("sdkDumpBin: <%s>\n", filename); + FILE *fp; + FOPEN(fp, filename, "wb"); + fwrite(data, bytes, 1, fp); + fflush(fp); + fclose(fp); +} + +inline +bool sdkCompareBin2BinUint(const char *src_file, const char *ref_file, unsigned int nelements, const float epsilon, const float threshold, char *exec_path) +{ + unsigned int *src_buffer, *ref_buffer; + FILE *src_fp = NULL, *ref_fp = NULL; + + unsigned long error_count = 0; + size_t fsize = 0; + + if (FOPEN_FAIL(FOPEN(src_fp, src_file, "rb"))) + { + printf("compareBin2Bin unable to open src_file: %s\n", src_file); + error_count++; + } + + char *ref_file_path = sdkFindFilePath(ref_file, exec_path); + + if (ref_file_path == NULL) + { + printf("compareBin2Bin unable to find <%s> in <%s>\n", ref_file, exec_path); + printf(">>> Check info.xml and [project//data] folder <%s> <<<\n", ref_file); + printf("Aborting comparison!\n"); + printf(" FAILED\n"); + error_count++; + + if (src_fp) + { + fclose(src_fp); + } + + if (ref_fp) + { + fclose(ref_fp); + } + } + else + { + if (FOPEN_FAIL(FOPEN(ref_fp, ref_file_path, "rb"))) + { + printf("compareBin2Bin unable to open ref_file: %s\n", ref_file_path); + error_count++; + } + + if (src_fp && ref_fp) + { + src_buffer = (unsigned int *)malloc(nelements*sizeof(unsigned int)); + ref_buffer = (unsigned int *)malloc(nelements*sizeof(unsigned int)); + + fsize = fread(src_buffer, nelements, sizeof(unsigned int), src_fp); + fsize = fread(ref_buffer, nelements, sizeof(unsigned int), ref_fp); + + printf("> compareBin2Bin nelements=%d, epsilon=%4.2f, threshold=%4.2f\n", nelements, epsilon, threshold); + printf(" src_file <%s>, size=%d bytes\n", src_file, (int)fsize); + printf(" ref_file <%s>, size=%d bytes\n", ref_file_path, (int)fsize); + + if (!compareData(ref_buffer, src_buffer, nelements, epsilon, threshold)) + { + error_count++; + } + + fclose(src_fp); + fclose(ref_fp); + + free(src_buffer); + free(ref_buffer); + } + else + { + if (src_fp) + { + fclose(src_fp); + } + + if (ref_fp) + { + fclose(ref_fp); + } + } + } + + if (error_count == 0) + { + printf(" OK\n"); + } + else + { + printf(" FAILURE: %d errors...\n", (unsigned int)error_count); + } + + return (error_count == 0); // returns true if all pixels pass +} + +inline +bool sdkCompareBin2BinFloat(const char *src_file, const char *ref_file, unsigned int nelements, const float epsilon, const float threshold, char *exec_path) +{ + float *src_buffer, *ref_buffer; + FILE *src_fp = NULL, *ref_fp = NULL; + size_t fsize = 0; + + unsigned long error_count = 0; + + if (FOPEN_FAIL(FOPEN(src_fp, src_file, "rb"))) + { + printf("compareBin2Bin unable to open src_file: %s\n", src_file); + error_count = 1; + } + + char *ref_file_path = sdkFindFilePath(ref_file, exec_path); + + if (ref_file_path == NULL) + { + printf("compareBin2Bin unable to find <%s> in <%s>\n", ref_file, exec_path); + printf(">>> Check info.xml and [project//data] folder <%s> <<<\n", exec_path); + printf("Aborting comparison!\n"); + printf(" FAILED\n"); + error_count++; + + if (src_fp) + { + fclose(src_fp); + } + + if (ref_fp) + { + fclose(ref_fp); + } + } + else + { + if (FOPEN_FAIL(FOPEN(ref_fp, ref_file_path, "rb"))) + { + printf("compareBin2Bin unable to open ref_file: %s\n", ref_file_path); + error_count = 1; + } + + if (src_fp && ref_fp) + { + src_buffer = (float *)malloc(nelements*sizeof(float)); + ref_buffer = (float *)malloc(nelements*sizeof(float)); + + fsize = fread(src_buffer, nelements, sizeof(float), src_fp); + fsize = fread(ref_buffer, nelements, sizeof(float), ref_fp); + + printf("> compareBin2Bin nelements=%d, epsilon=%4.2f, threshold=%4.2f\n", nelements, epsilon, threshold); + printf(" src_file <%s>, size=%d bytes\n", src_file, (int)fsize); + printf(" ref_file <%s>, size=%d bytes\n", ref_file_path, (int)fsize); + + if (!compareDataAsFloatThreshold(ref_buffer, src_buffer, nelements, epsilon, threshold)) + { + error_count++; + } + + fclose(src_fp); + fclose(ref_fp); + + free(src_buffer); + free(ref_buffer); + } + else + { + if (src_fp) + { + fclose(src_fp); + } + + if (ref_fp) + { + fclose(ref_fp); + } + } + } + + if (error_count == 0) + { + printf(" OK\n"); + } + else + { + printf(" FAILURE: %d errors...\n", (unsigned int)error_count); + } + + return (error_count == 0); // returns true if all pixels pass +} + +inline bool +sdkCompareL2fe(const float *reference, const float *data, + const unsigned int len, const float epsilon) +{ + assert(epsilon >= 0); + + float error = 0; + float ref = 0; + + for (unsigned int i = 0; i < len; ++i) + { + + float diff = reference[i] - data[i]; + error += diff * diff; + ref += reference[i] * reference[i]; + } + + float normRef = sqrtf(ref); + + if (fabs(ref) < 1e-7) + { +#ifdef _DEBUG + std::cerr << "ERROR, reference l2-norm is 0\n"; +#endif + return false; + } + + float normError = sqrtf(error); + error = normError / normRef; + bool result = error < epsilon; +#ifdef _DEBUG + + if (! result) + { + std::cerr << "ERROR, l2-norm error " + << error << " is greater than epsilon " << epsilon << "\n"; + } + +#endif + + return result; +} + +inline bool +sdkLoadPPMub(const char *file, unsigned char **data, + unsigned int *w,unsigned int *h) +{ + unsigned int channels; + return __loadPPM(file, data, w, h, &channels); +} + +inline bool +sdkLoadPPM4ub(const char *file, unsigned char **data, + unsigned int *w, unsigned int *h) +{ + unsigned char *idata = 0; + unsigned int channels; + + if (__loadPPM(file, &idata, w, h, &channels)) + { + // pad 4th component + int size = *w **h; + // keep the original pointer + unsigned char *idata_orig = idata; + *data = (unsigned char *) malloc(sizeof(unsigned char) * size * 4); + unsigned char *ptr = *data; + + for (int i=0; i Compare (a)rendered: <" << src_file << ">\n"; + std::cerr << "> (b)reference: <" << ref_file << ">\n"; + } + + + if (sdkLoadPPM4ub(ref_file, &ref_data, &ref_width, &ref_height) != true) + { + if (verboseErrors) + { + std::cerr << "PPMvsPPM: unable to load ref image file: "<< ref_file << "\n"; + } + + return false; + } + + if (sdkLoadPPM4ub(src_file, &src_data, &src_width, &src_height) != true) + { + std::cerr << "PPMvsPPM: unable to load src image file: " << src_file << "\n"; + return false; + } + + if (src_height != ref_height || src_width != ref_width) + { + if (verboseErrors) std::cerr << "PPMvsPPM: source and ref size mismatch (" << src_width << + "," << src_height << ")vs(" << ref_width << "," << ref_height << ")\n"; + } + + if (verboseErrors) std::cerr << "PPMvsPPM: comparing images size (" << src_width << + "," << src_height << ") epsilon(" << epsilon << "), threshold(" << threshold*100 << "%)\n"; + + if (compareData(ref_data, src_data, src_width*src_height*4, epsilon, threshold) == false) + { + error_count=1; + } + + if (error_count == 0) + { + if (verboseErrors) + { + std::cerr << " OK\n\n"; + } + } + else + { + if (verboseErrors) + { + std::cerr << " FAILURE! "< Compare (a)rendered: <" << src_file << ">\n"; + std::cerr << "> (b)reference: <" << ref_file << ">\n"; + } + + + if (sdkLoadPPMub(ref_file, &ref_data, &ref_width, &ref_height) != true) + { + if (verboseErrors) + { + std::cerr << "PGMvsPGM: unable to load ref image file: "<< ref_file << "\n"; + } + + return false; + } + + if (sdkLoadPPMub(src_file, &src_data, &src_width, &src_height) != true) + { + std::cerr << "PGMvsPGM: unable to load src image file: " << src_file << "\n"; + return false; + } + + if (src_height != ref_height || src_width != ref_width) + { + if (verboseErrors) std::cerr << "PGMvsPGM: source and ref size mismatch (" << src_width << + "," << src_height << ")vs(" << ref_width << "," << ref_height << ")\n"; + } + + if (verboseErrors) std::cerr << "PGMvsPGM: comparing images size (" << src_width << + "," << src_height << ") epsilon(" << epsilon << "), threshold(" << threshold*100 << "%)\n"; + + if (compareData(ref_data, src_data, src_width*src_height, epsilon, threshold) == false) + { + error_count=1; + } + + if (error_count == 0) + { + if (verboseErrors) + { + std::cerr << " OK\n\n"; + } + } + else + { + if (verboseErrors) + { + std::cerr << " FAILURE! "< +#include +#include +#include + +#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) +#ifndef _CRT_SECURE_NO_DEPRECATE +#define _CRT_SECURE_NO_DEPRECATE +#endif +#ifndef STRCASECMP +#define STRCASECMP _stricmp +#endif +#ifndef STRNCASECMP +#define STRNCASECMP _strnicmp +#endif +#ifndef STRCPY +#define STRCPY(sFilePath, nLength, sPath) strcpy_s(sFilePath, nLength, sPath) +#endif + +#ifndef FOPEN +#define FOPEN(fHandle,filename,mode) fopen_s(&fHandle, filename, mode) +#endif +#ifndef FOPEN_FAIL +#define FOPEN_FAIL(result) (result != 0) +#endif +#ifndef SSCANF +#define SSCANF sscanf_s +#endif +#ifndef SPRINTF +#define SPRINTF sprintf_s +#endif +#else // Linux Includes +#include +#include + +#ifndef STRCASECMP +#define STRCASECMP strcasecmp +#endif +#ifndef STRNCASECMP +#define STRNCASECMP strncasecmp +#endif +#ifndef STRCPY +#define STRCPY(sFilePath, nLength, sPath) strcpy(sFilePath, sPath) +#endif + +#ifndef FOPEN +#define FOPEN(fHandle,filename,mode) (fHandle = fopen(filename, mode)) +#endif +#ifndef FOPEN_FAIL +#define FOPEN_FAIL(result) (result == NULL) +#endif +#ifndef SSCANF +#define SSCANF sscanf +#endif +#ifndef SPRINTF +#define SPRINTF sprintf +#endif +#endif + +#ifndef EXIT_WAIVED +#define EXIT_WAIVED 2 +#endif + +// CUDA Utility Helper Functions +inline int stringRemoveDelimiter(char delimiter, const char *string) +{ + int string_start = 0; + + while (string[string_start] == delimiter) + { + string_start++; + } + + if (string_start >= (int)strlen(string)-1) + { + return 0; + } + + return string_start; +} + +inline int getFileExtension(char *filename, char **extension) +{ + int string_length = (int)strlen(filename); + + while (filename[string_length--] != '.') + { + if (string_length == 0) + break; + } + + if (string_length > 0) string_length += 2; + + if (string_length == 0) + *extension = NULL; + else + *extension = &filename[string_length]; + + return string_length; +} + + +inline bool checkCmdLineFlag(const int argc, const char **argv, const char *string_ref) +{ + bool bFound = false; + + if (argc >= 1) + { + for (int i=1; i < argc; i++) + { + int string_start = stringRemoveDelimiter('-', argv[i]); + const char *string_argv = &argv[i][string_start]; + + const char *equal_pos = strchr(string_argv, '='); + int argv_length = (int)(equal_pos == 0 ? strlen(string_argv) : equal_pos - string_argv); + + int length = (int)strlen(string_ref); + + if (length == argv_length && !STRNCASECMP(string_argv, string_ref, length)) + { + bFound = true; + continue; + } + } + } + + return bFound; +} + +// This function wraps the CUDA Driver API into a template function +template +inline bool getCmdLineArgumentValue(const int argc, const char **argv, const char *string_ref, T *value) +{ + bool bFound = false; + + if (argc >= 1) + { + for (int i=1; i < argc; i++) + { + int string_start = stringRemoveDelimiter('-', argv[i]); + const char *string_argv = &argv[i][string_start]; + int length = (int)strlen(string_ref); + + if (!STRNCASECMP(string_argv, string_ref, length)) + { + if (length+1 <= (int)strlen(string_argv)) + { + int auto_inc = (string_argv[length] == '=') ? 1 : 0; + *value = (T)atoi(&string_argv[length + auto_inc]); + } + + bFound = true; + i=argc; + } + } + } + + return bFound; +} + +inline int getCmdLineArgumentInt(const int argc, const char **argv, const char *string_ref) +{ + bool bFound = false; + int value = -1; + + if (argc >= 1) + { + for (int i=1; i < argc; i++) + { + int string_start = stringRemoveDelimiter('-', argv[i]); + const char *string_argv = &argv[i][string_start]; + int length = (int)strlen(string_ref); + + if (!STRNCASECMP(string_argv, string_ref, length)) + { + if (length+1 <= (int)strlen(string_argv)) + { + int auto_inc = (string_argv[length] == '=') ? 1 : 0; + value = atoi(&string_argv[length + auto_inc]); + } + else + { + value = 0; + } + + bFound = true; + continue; + } + } + } + + if (bFound) + { + return value; + } + else + { + return 0; + } +} + +inline float getCmdLineArgumentFloat(const int argc, const char **argv, const char *string_ref) +{ + bool bFound = false; + float value = -1; + + if (argc >= 1) + { + for (int i=1; i < argc; i++) + { + int string_start = stringRemoveDelimiter('-', argv[i]); + const char *string_argv = &argv[i][string_start]; + int length = (int)strlen(string_ref); + + if (!STRNCASECMP(string_argv, string_ref, length)) + { + if (length+1 <= (int)strlen(string_argv)) + { + int auto_inc = (string_argv[length] == '=') ? 1 : 0; + value = (float)atof(&string_argv[length + auto_inc]); + } + else + { + value = 0.f; + } + + bFound = true; + continue; + } + } + } + + if (bFound) + { + return value; + } + else + { + return 0; + } +} + +inline bool getCmdLineArgumentString(const int argc, const char **argv, + const char *string_ref, char **string_retval) +{ + bool bFound = false; + + if (argc >= 1) + { + for (int i=1; i < argc; i++) + { + int string_start = stringRemoveDelimiter('-', argv[i]); + char *string_argv = (char *)&argv[i][string_start]; + int length = (int)strlen(string_ref); + + if (!STRNCASECMP(string_argv, string_ref, length)) + { + *string_retval = &string_argv[length+1]; + bFound = true; + continue; + } + } + } + + if (!bFound) + { + *string_retval = NULL; + } + + return bFound; +} + +////////////////////////////////////////////////////////////////////////////// +//! Find the path for a file assuming that +//! files are found in the searchPath. +//! +//! @return the path if succeeded, otherwise 0 +//! @param filename name of the file +//! @param executable_path optional absolute path of the executable +////////////////////////////////////////////////////////////////////////////// +inline char *sdkFindFilePath(const char *filename, const char *executable_path) +{ + // defines a variable that is replaced with the name of the executable + + // Typical relative search paths to locate needed companion files (e.g. sample input data, or JIT source files) + // The origin for the relative search may be the .exe file, a .bat file launching an .exe, a browser .exe launching the .exe or .bat, etc + const char *searchPath[] = + { + "./", // same dir + "./common/", // "/common/" subdir + "./common/data/", // "/common/data/" subdir + "./data/", // "/data/" subdir + "./src/", // "/src/" subdir + "./src//data/", // "/src//data/" subdir + "./inc/", // "/inc/" subdir + "./0_Simple/", // "/0_Simple/" subdir + "./1_Utilities/", // "/1_Utilities/" subdir + "./2_Graphics/", // "/2_Graphics/" subdir + "./3_Imaging/", // "/3_Imaging/" subdir + "./4_Financial/", // "/4_Financial/" subdir + "./5_Simulations/", // "/5_Simulations/" subdir + "./6_Advanced/", // "/6_Advanced/" subdir + "./7_CUDALibraries/", // "/7_CUDALibraries/" subdir + "./8_Android/", // "/8_Android/" subdir + "./samples/", // "/samples/" subdir + + "../", // up 1 in tree + "../common/", // up 1 in tree, "/common/" subdir + "../common/data/", // up 1 in tree, "/common/data/" subdir + "../data/", // up 1 in tree, "/data/" subdir + "../src/", // up 1 in tree, "/src/" subdir + "../inc/", // up 1 in tree, "/inc/" subdir + + "../0_Simple//data/", // up 1 in tree, "/0_Simple//" subdir + "../1_Utilities//data/", // up 1 in tree, "/1_Utilities//" subdir + "../2_Graphics//data/", // up 1 in tree, "/2_Graphics//" subdir + "../3_Imaging//data/", // up 1 in tree, "/3_Imaging//" subdir + "../4_Financial//data/", // up 1 in tree, "/4_Financial//" subdir + "../5_Simulations//data/", // up 1 in tree, "/5_Simulations//" subdir + "../6_Advanced//data/", // up 1 in tree, "/6_Advanced//" subdir + "../7_CUDALibraries//data/",// up 1 in tree, "/7_CUDALibraries//" subdir + "../8_Android//data/", // up 1 in tree, "/8_Android//" subdir + "../samples//data/", // up 1 in tree, "/samples//" subdir + "../../", // up 2 in tree + "../../common/", // up 2 in tree, "/common/" subdir + "../../common/data/", // up 2 in tree, "/common/data/" subdir + "../../data/", // up 2 in tree, "/data/" subdir + "../../src/", // up 2 in tree, "/src/" subdir + "../../inc/", // up 2 in tree, "/inc/" subdir + "../../sandbox//data/", // up 2 in tree, "/sandbox//" subdir + "../../0_Simple//data/", // up 2 in tree, "/0_Simple//" subdir + "../../1_Utilities//data/", // up 2 in tree, "/1_Utilities//" subdir + "../../2_Graphics//data/", // up 2 in tree, "/2_Graphics//" subdir + "../../3_Imaging//data/", // up 2 in tree, "/3_Imaging//" subdir + "../../4_Financial//data/", // up 2 in tree, "/4_Financial//" subdir + "../../5_Simulations//data/", // up 2 in tree, "/5_Simulations//" subdir + "../../6_Advanced//data/", // up 2 in tree, "/6_Advanced//" subdir + "../../7_CUDALibraries//data/", // up 2 in tree, "/7_CUDALibraries//" subdir + "../../8_Android//data/", // up 2 in tree, "/8_Android//" subdir + "../../samples//data/", // up 2 in tree, "/samples//" subdir + "../../../", // up 3 in tree + "../../../src//", // up 3 in tree, "/src//" subdir + "../../../src//data/", // up 3 in tree, "/src//data/" subdir + "../../../src//src/", // up 3 in tree, "/src//src/" subdir + "../../../src//inc/", // up 3 in tree, "/src//inc/" subdir + "../../../sandbox//", // up 3 in tree, "/sandbox//" subdir + "../../../sandbox//data/", // up 3 in tree, "/sandbox//data/" subdir + "../../../sandbox//src/", // up 3 in tree, "/sandbox//src/" subdir + "../../../sandbox//inc/", // up 3 in tree, "/sandbox//inc/" subdir + "../../../0_Simple//data/", // up 3 in tree, "/0_Simple//" subdir + "../../../1_Utilities//data/", // up 3 in tree, "/1_Utilities//" subdir + "../../../2_Graphics//data/", // up 3 in tree, "/2_Graphics//" subdir + "../../../3_Imaging//data/", // up 3 in tree, "/3_Imaging//" subdir + "../../../4_Financial//data/", // up 3 in tree, "/4_Financial//" subdir + "../../../5_Simulations//data/", // up 3 in tree, "/5_Simulations//" subdir + "../../../6_Advanced//data/", // up 3 in tree, "/6_Advanced//" subdir + "../../../7_CUDALibraries//data/", // up 3 in tree, "/7_CUDALibraries//" subdir + "../../../8_Android//data/", // up 3 in tree, "/8_Android//" subdir + "../../../samples//data/", // up 3 in tree, "/samples//" subdir + "../../../common/", // up 3 in tree, "../../../common/" subdir + "../../../common/data/", // up 3 in tree, "../../../common/data/" subdir + "../../../data/", // up 3 in tree, "../../../data/" subdir + "../../../../", // up 4 in tree + "../../../../src//", // up 4 in tree, "/src//" subdir + "../../../../src//data/", // up 4 in tree, "/src//data/" subdir + "../../../../src//src/", // up 4 in tree, "/src//src/" subdir + "../../../../src//inc/", // up 4 in tree, "/src//inc/" subdir + "../../../../sandbox//", // up 4 in tree, "/sandbox//" subdir + "../../../../sandbox//data/", // up 4 in tree, "/sandbox//data/" subdir + "../../../../sandbox//src/", // up 4 in tree, "/sandbox//src/" subdir + "../../../../sandbox//inc/", // up 4 in tree, "/sandbox//inc/" subdir + "../../../../0_Simple//data/", // up 4 in tree, "/0_Simple//" subdir + "../../../../1_Utilities//data/", // up 4 in tree, "/1_Utilities//" subdir + "../../../../2_Graphics//data/", // up 4 in tree, "/2_Graphics//" subdir + "../../../../3_Imaging//data/", // up 4 in tree, "/3_Imaging//" subdir + "../../../../4_Financial//data/", // up 4 in tree, "/4_Financial//" subdir + "../../../../5_Simulations//data/",// up 4 in tree, "/5_Simulations//" subdir + "../../../../6_Advanced//data/", // up 4 in tree, "/6_Advanced//" subdir + "../../../../7_CUDALibraries//data/", // up 4 in tree, "/7_CUDALibraries//" subdir + "../../../../8_Android//data/", // up 4 in tree, "/8_Android//" subdir + "../../../../samples//data/", // up 4 in tree, "/samples//" subdir + "../../../../common/", // up 4 in tree, "../../../common/" subdir + "../../../../common/data/", // up 4 in tree, "../../../common/data/" subdir + "../../../../data/", // up 4 in tree, "../../../data/" subdir + "../../../../../", // up 5 in tree + "../../../../../src//", // up 5 in tree, "/src//" subdir + "../../../../../src//data/", // up 5 in tree, "/src//data/" subdir + "../../../../../src//src/", // up 5 in tree, "/src//src/" subdir + "../../../../../src//inc/", // up 5 in tree, "/src//inc/" subdir + "../../../../../sandbox//", // up 5 in tree, "/sandbox//" subdir + "../../../../../sandbox//data/", // up 5 in tree, "/sandbox//data/" subdir + "../../../../../sandbox//src/", // up 5 in tree, "/sandbox//src/" subdir + "../../../../../sandbox//inc/", // up 5 in tree, "/sandbox//inc/" subdir + "../../../../../0_Simple//data/", // up 5 in tree, "/0_Simple//" subdir + "../../../../../1_Utilities//data/", // up 5 in tree, "/1_Utilities//" subdir + "../../../../../2_Graphics//data/", // up 5 in tree, "/2_Graphics//" subdir + "../../../../../3_Imaging//data/", // up 5 in tree, "/3_Imaging//" subdir + "../../../../../4_Financial//data/", // up 5 in tree, "/4_Financial//" subdir + "../../../../../5_Simulations//data/",// up 5 in tree, "/5_Simulations//" subdir + "../../../../../6_Advanced//data/", // up 5 in tree, "/6_Advanced//" subdir + "../../../../../7_CUDALibraries//data/", // up 5 in tree, "/7_CUDALibraries//" subdir + "../../../../../8_Android//data/", // up 5 in tree, "/8_Android//" subdir + "../../../../../samples//data/", // up 5 in tree, "/samples//" subdir + "../../../../../common/", // up 5 in tree, "../../../common/" subdir + "../../../../../common/data/", // up 5 in tree, "../../../common/data/" subdir + }; + + // Extract the executable name + std::string executable_name; + + if (executable_path != 0) + { + executable_name = std::string(executable_path); + +#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) + // Windows path delimiter + size_t delimiter_pos = executable_name.find_last_of('\\'); + executable_name.erase(0, delimiter_pos + 1); + + if (executable_name.rfind(".exe") != std::string::npos) + { + // we strip .exe, only if the .exe is found + executable_name.resize(executable_name.size() - 4); + } + +#else + // Linux & OSX path delimiter + size_t delimiter_pos = executable_name.find_last_of('/'); + executable_name.erase(0,delimiter_pos+1); +#endif + } + + // Loop over all search paths and return the first hit + for (unsigned int i = 0; i < sizeof(searchPath)/sizeof(char *); ++i) + { + std::string path(searchPath[i]); + size_t executable_name_pos = path.find(""); + + // If there is executable_name variable in the searchPath + // replace it with the value + if (executable_name_pos != std::string::npos) + { + if (executable_path != 0) + { + path.replace(executable_name_pos, strlen(""), executable_name); + } + else + { + // Skip this path entry if no executable argument is given + continue; + } + } + +#ifdef _DEBUG + printf("sdkFindFilePath <%s> in %s\n", filename, path.c_str()); +#endif + + // Test if the file exists + path.append(filename); + FILE *fp; + FOPEN(fp, path.c_str(), "rb"); + + if (fp != NULL) + { + fclose(fp); + // File found + // returning an allocated array here for backwards compatibility reasons + char *file_path = (char *) malloc(path.length() + 1); + STRCPY(file_path, path.length() + 1, path.c_str()); + return file_path; + } + + if (fp) + { + fclose(fp); + } + } + + // File not found + return 0; +} + +#endif diff --git a/Source/src/helper_timer.h b/Source/src/helper_timer.h new file mode 100644 index 0000000..39ddc77 --- /dev/null +++ b/Source/src/helper_timer.h @@ -0,0 +1,499 @@ +/** + * Copyright 1993-2013 NVIDIA Corporation. All rights reserved. + * + * Please refer to the NVIDIA end user license agreement (EULA) associated + * with this source code for terms and conditions that govern your use of + * this software. Any use, reproduction, disclosure, or distribution of + * this software and related documentation outside the terms of the EULA + * is strictly prohibited. + * + */ + +// Helper Timing Functions +#ifndef HELPER_TIMER_H +#define HELPER_TIMER_H + +#ifndef EXIT_WAIVED +#define EXIT_WAIVED 2 +#endif + +// includes, system +#include + +// includes, project +#include + +// Definition of the StopWatch Interface, this is used if we don't want to use the CUT functions +// But rather in a self contained class interface +class StopWatchInterface +{ + public: + StopWatchInterface() {}; + virtual ~StopWatchInterface() {}; + + public: + //! Start time measurement + virtual void start() = 0; + + //! Stop time measurement + virtual void stop() = 0; + + //! Reset time counters to zero + virtual void reset() = 0; + + //! Time in msec. after start. If the stop watch is still running (i.e. there + //! was no call to stop()) then the elapsed time is returned, otherwise the + //! time between the last start() and stop call is returned + virtual float getTime() = 0; + + //! Mean time to date based on the number of times the stopwatch has been + //! _stopped_ (ie finished sessions) and the current total time + virtual float getAverageTime() = 0; +}; + + +////////////////////////////////////////////////////////////////// +// Begin Stopwatch timer class definitions for all OS platforms // +////////////////////////////////////////////////////////////////// +#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) +// includes, system +#define WINDOWS_LEAN_AND_MEAN +#include +#undef min +#undef max + +//! Windows specific implementation of StopWatch +class StopWatchWin : public StopWatchInterface +{ + public: + //! Constructor, default + StopWatchWin() : + start_time(), end_time(), + diff_time(0.0f), total_time(0.0f), + running(false), clock_sessions(0), freq(0), freq_set(false) + { + if (! freq_set) + { + // helper variable + LARGE_INTEGER temp; + + // get the tick frequency from the OS + QueryPerformanceFrequency((LARGE_INTEGER *) &temp); + + // convert to type in which it is needed + freq = ((double) temp.QuadPart) / 1000.0; + + // rememeber query + freq_set = true; + } + }; + + // Destructor + ~StopWatchWin() { }; + + public: + //! Start time measurement + inline void start(); + + //! Stop time measurement + inline void stop(); + + //! Reset time counters to zero + inline void reset(); + + //! Time in msec. after start. If the stop watch is still running (i.e. there + //! was no call to stop()) then the elapsed time is returned, otherwise the + //! time between the last start() and stop call is returned + inline float getTime(); + + //! Mean time to date based on the number of times the stopwatch has been + //! _stopped_ (ie finished sessions) and the current total time + inline float getAverageTime(); + + private: + // member variables + + //! Start of measurement + LARGE_INTEGER start_time; + //! End of measurement + LARGE_INTEGER end_time; + + //! Time difference between the last start and stop + float diff_time; + + //! TOTAL time difference between starts and stops + float total_time; + + //! flag if the stop watch is running + bool running; + + //! Number of times clock has been started + //! and stopped to allow averaging + int clock_sessions; + + //! tick frequency + double freq; + + //! flag if the frequency has been set + bool freq_set; +}; + +// functions, inlined + +//////////////////////////////////////////////////////////////////////////////// +//! Start time measurement +//////////////////////////////////////////////////////////////////////////////// +inline void +StopWatchWin::start() +{ + QueryPerformanceCounter((LARGE_INTEGER *) &start_time); + running = true; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Stop time measurement and increment add to the current diff_time summation +//! variable. Also increment the number of times this clock has been run. +//////////////////////////////////////////////////////////////////////////////// +inline void +StopWatchWin::stop() +{ + QueryPerformanceCounter((LARGE_INTEGER *) &end_time); + diff_time = (float) + (((double) end_time.QuadPart - (double) start_time.QuadPart) / freq); + + total_time += diff_time; + clock_sessions++; + running = false; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Reset the timer to 0. Does not change the timer running state but does +//! recapture this point in time as the current start time if it is running. +//////////////////////////////////////////////////////////////////////////////// +inline void +StopWatchWin::reset() +{ + diff_time = 0; + total_time = 0; + clock_sessions = 0; + + if (running) + { + QueryPerformanceCounter((LARGE_INTEGER *) &start_time); + } +} + + +//////////////////////////////////////////////////////////////////////////////// +//! Time in msec. after start. If the stop watch is still running (i.e. there +//! was no call to stop()) then the elapsed time is returned added to the +//! current diff_time sum, otherwise the current summed time difference alone +//! is returned. +//////////////////////////////////////////////////////////////////////////////// +inline float +StopWatchWin::getTime() +{ + // Return the TOTAL time to date + float retval = total_time; + + if (running) + { + LARGE_INTEGER temp; + QueryPerformanceCounter((LARGE_INTEGER *) &temp); + retval += (float) + (((double)(temp.QuadPart - start_time.QuadPart)) / freq); + } + + return retval; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Time in msec. for a single run based on the total number of COMPLETED runs +//! and the total time. +//////////////////////////////////////////////////////////////////////////////// +inline float +StopWatchWin::getAverageTime() +{ + return (clock_sessions > 0) ? (total_time/clock_sessions) : 0.0f; +} +#else +// Declarations for Stopwatch on Linux and Mac OSX +// includes, system +#include +#include + +//! Windows specific implementation of StopWatch +class StopWatchLinux : public StopWatchInterface +{ + public: + //! Constructor, default + StopWatchLinux() : + start_time(), diff_time(0.0), total_time(0.0), + running(false), clock_sessions(0) + { }; + + // Destructor + virtual ~StopWatchLinux() + { }; + + public: + //! Start time measurement + inline void start(); + + //! Stop time measurement + inline void stop(); + + //! Reset time counters to zero + inline void reset(); + + //! Time in msec. after start. If the stop watch is still running (i.e. there + //! was no call to stop()) then the elapsed time is returned, otherwise the + //! time between the last start() and stop call is returned + inline float getTime(); + + //! Mean time to date based on the number of times the stopwatch has been + //! _stopped_ (ie finished sessions) and the current total time + inline float getAverageTime(); + + private: + + // helper functions + + //! Get difference between start time and current time + inline float getDiffTime(); + + private: + + // member variables + + //! Start of measurement + struct timeval start_time; + + //! Time difference between the last start and stop + float diff_time; + + //! TOTAL time difference between starts and stops + float total_time; + + //! flag if the stop watch is running + bool running; + + //! Number of times clock has been started + //! and stopped to allow averaging + int clock_sessions; +}; + +// functions, inlined + +//////////////////////////////////////////////////////////////////////////////// +//! Start time measurement +//////////////////////////////////////////////////////////////////////////////// +inline void +StopWatchLinux::start() +{ + gettimeofday(&start_time, 0); + running = true; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Stop time measurement and increment add to the current diff_time summation +//! variable. Also increment the number of times this clock has been run. +//////////////////////////////////////////////////////////////////////////////// +inline void +StopWatchLinux::stop() +{ + diff_time = getDiffTime(); + total_time += diff_time; + running = false; + clock_sessions++; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Reset the timer to 0. Does not change the timer running state but does +//! recapture this point in time as the current start time if it is running. +//////////////////////////////////////////////////////////////////////////////// +inline void +StopWatchLinux::reset() +{ + diff_time = 0; + total_time = 0; + clock_sessions = 0; + + if (running) + { + gettimeofday(&start_time, 0); + } +} + +//////////////////////////////////////////////////////////////////////////////// +//! Time in msec. after start. If the stop watch is still running (i.e. there +//! was no call to stop()) then the elapsed time is returned added to the +//! current diff_time sum, otherwise the current summed time difference alone +//! is returned. +//////////////////////////////////////////////////////////////////////////////// +inline float +StopWatchLinux::getTime() +{ + // Return the TOTAL time to date + float retval = total_time; + + if (running) + { + retval += getDiffTime(); + } + + return retval; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Time in msec. for a single run based on the total number of COMPLETED runs +//! and the total time. +//////////////////////////////////////////////////////////////////////////////// +inline float +StopWatchLinux::getAverageTime() +{ + return (clock_sessions > 0) ? (total_time/clock_sessions) : 0.0f; +} +//////////////////////////////////////////////////////////////////////////////// + +//////////////////////////////////////////////////////////////////////////////// +inline float +StopWatchLinux::getDiffTime() +{ + struct timeval t_time; + gettimeofday(&t_time, 0); + + // time difference in milli-seconds + return (float)(1000.0 * (t_time.tv_sec - start_time.tv_sec) + + (0.001 * (t_time.tv_usec - start_time.tv_usec))); +} +#endif // WIN32 + +//////////////////////////////////////////////////////////////////////////////// +//! Timer functionality exported + +//////////////////////////////////////////////////////////////////////////////// +//! Create a new timer +//! @return true if a time has been created, otherwise false +//! @param name of the new timer, 0 if the creation failed +//////////////////////////////////////////////////////////////////////////////// +inline bool +sdkCreateTimer(StopWatchInterface **timer_interface) +{ + //printf("sdkCreateTimer called object %08x\n", (void *)*timer_interface); +#if defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64) + *timer_interface = (StopWatchInterface *)new StopWatchWin(); +#else + *timer_interface = (StopWatchInterface *)new StopWatchLinux(); +#endif + return (*timer_interface != NULL) ? true : false; +} + + +//////////////////////////////////////////////////////////////////////////////// +//! Delete a timer +//! @return true if a time has been deleted, otherwise false +//! @param name of the timer to delete +//////////////////////////////////////////////////////////////////////////////// +inline bool +sdkDeleteTimer(StopWatchInterface **timer_interface) +{ + //printf("sdkDeleteTimer called object %08x\n", (void *)*timer_interface); + if (*timer_interface) + { + delete *timer_interface; + *timer_interface = NULL; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Start the time with name \a name +//! @param name name of the timer to start +//////////////////////////////////////////////////////////////////////////////// +inline bool +sdkStartTimer(StopWatchInterface **timer_interface) +{ + //printf("sdkStartTimer called object %08x\n", (void *)*timer_interface); + if (*timer_interface) + { + (*timer_interface)->start(); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Stop the time with name \a name. Does not reset. +//! @param name name of the timer to stop +//////////////////////////////////////////////////////////////////////////////// +inline bool +sdkStopTimer(StopWatchInterface **timer_interface) +{ + // printf("sdkStopTimer called object %08x\n", (void *)*timer_interface); + if (*timer_interface) + { + (*timer_interface)->stop(); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Resets the timer's counter. +//! @param name name of the timer to reset. +//////////////////////////////////////////////////////////////////////////////// +inline bool +sdkResetTimer(StopWatchInterface **timer_interface) +{ + // printf("sdkResetTimer called object %08x\n", (void *)*timer_interface); + if (*timer_interface) + { + (*timer_interface)->reset(); + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +//! Return the average time for timer execution as the total time +//! for the timer dividied by the number of completed (stopped) runs the timer +//! has made. +//! Excludes the current running time if the timer is currently running. +//! @param name name of the timer to return the time of +//////////////////////////////////////////////////////////////////////////////// +inline float +sdkGetAverageTimerValue(StopWatchInterface **timer_interface) +{ + // printf("sdkGetAverageTimerValue called object %08x\n", (void *)*timer_interface); + if (*timer_interface) + { + return (*timer_interface)->getAverageTime(); + } + else + { + return 0.0f; + } +} + +//////////////////////////////////////////////////////////////////////////////// +//! Total execution time for the timer over all runs since the last reset +//! or timer creation. +//! @param name name of the timer to obtain the value of. +//////////////////////////////////////////////////////////////////////////////// +inline float +sdkGetTimerValue(StopWatchInterface **timer_interface) +{ + // printf("sdkGetTimerValue called object %08x\n", (void *)*timer_interface); + if (*timer_interface) + { + return (*timer_interface)->getTime(); + } + else + { + return 0.0f; + } +} + +#endif // HELPER_TIMER_H diff --git a/Source/src/main.cpp b/Source/src/main.cpp new file mode 100644 index 0000000..f7baf67 --- /dev/null +++ b/Source/src/main.cpp @@ -0,0 +1,385 @@ +/** +* @file main.cpp +* @brief main +* @author Hermann von Hasseln, DL3HVH +* @version 0.1 +* @date 2010-09-08 +*/ + +/* + * Copyright 2010, 2011, 2012 Hermann von Hasseln, DL3HVH + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "Util/cusdr_splash.h" +#include "cusdr_settings.h" + + +#if defined(Q_OS_WIN32) + #include "Util/cusdr_cpuUsage.h" +#elif defined(Q_OS_LINUX) + #include "Util/cusdr_cpuUsage_unix.h" +#endif + +#include "fftw3.h" +#include "cusdr_mainWidget.h" + +//#include +#include +#include +#include +//#include +#include +#include +//#include + +//#ifndef _WIN32_WINNT // Specifies that the minimum required platform is Windows Vista. +//#define _WIN32_WINNT 0x0600 // Change this to the appropriate value to target other versions of Windows. +//#endif + +// CPU usage +#if defined(Q_OS_WIN32) + DWORD WINAPI WatchItThreadProc(LPVOID lpParam); + CpuUsage usage; + + DWORD WINAPI WatchItThreadProc(LPVOID lpParam) { + + Q_UNUSED(lpParam) + + DWORD dummy; + while (true) { + + short cpuUsage = usage.GetUsage(); + Settings::instance()->setCPULoad(cpuUsage); + + Sleep(1000); + } + return dummy; + } +#endif + +void cuSDRMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { + + Q_UNUSED(type) + + QString txt; + QDateTime date; + + txt = msg; + txt.prepend(": "); + txt.prepend(date.currentDateTime().toString()); + + QFile outFile("cudaSDR.log"); + outFile.open(QIODevice::WriteOnly | QIODevice::Append); + QTextStream ts(&outFile); + ts << txt << endl << flush; +} + +static void my_fftw_write_char(char c, void *f) { fputc(c, (FILE *) f); } +#define fftw_export_wisdom_to_file(f) fftw_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwf_export_wisdom_to_file(f) fftwf_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwl_export_wisdom_to_file(f) fftwl_export_wisdom(my_fftw_write_char, (void*) (f)) + +static int my_fftw_read_char(void *f) { return fgetc((FILE *) f); } +#define fftw_import_wisdom_from_file(f) fftw_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwf_import_wisdom_from_file(f) fftwf_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwl_import_wisdom_from_file(f) fftwl_import_wisdom(my_fftw_read_char, (void*) (f)) + +void runFFTWWisdom() { + + QString directory = QDir::currentPath(); + + QDir currentDir = QDir(directory); + qDebug() << currentDir; + + if (currentDir.exists("wisdom")) { + + qDebug() << "wisdom exists !"; + return; + } + else { + + qDebug() << "wisdom does not exist - planning FFT..."; + + /*const char* wisdom_file = "wisdom"; + if (!fftw_import_wisdom_from_file(wisdom_file)) { + + int size = 64; + + QString str = "Planning FFT size %1"; + + fftwf_complex* cpxbuf; + fftwf_plan plan_fwd; + fftwf_plan plan_rev; + + while (size <= MAX_FFTSIZE) { + + qDebug() << str.arg(size); + cpxbuf = (fftwf_complex *) fftwf_malloc(sizeof(fftwf_complex) * size); + + plan_fwd = fftwf_plan_dft_1d(size , cpxbuf, cpxbuf, FFTW_FORWARD, FFTW_PATIENT); + fftwf_execute(plan_fwd); + fftwf_destroy_plan(plan_fwd); + + plan_rev = fftwf_plan_dft_1d(size, cpxbuf, cpxbuf, FFTW_BACKWARD, FFTW_PATIENT); + fftwf_execute(plan_rev); + fftwf_destroy_plan(plan_rev); + + size *= 2; + } + fftw_export_wisdom_to_file(wisdom_file); + }*/ + //QProcess process; + //process.start("fftwf-wisdom.exe"); + //process.waitForFinished(); + } +} + +int main(int argc, char *argv[]) { + + #ifndef DEBUG + qInstallMessageHandler(cuSDRMessageHandler); + #endif + + QApplication app(argc, argv); + + Settings::instance(&app); + + app.setApplicationName(Settings::instance()->getTitleStr()); + app.setApplicationVersion(Settings::instance()->getVersionStr()); + + class SleeperThread : public QThread { + + public: + static void msleep(unsigned long msecs) {QThread::msleep(msecs);} + }; + + QPixmap splash_pixmap(":/img/cudaSDRLogo.png"); + + CSplashScreen* splash = new CSplashScreen(splash_pixmap); + + splash->setGeometry( + QStyle::alignedRect( + Qt::LeftToRight, + Qt::AlignCenter, + splash->size(), + app.desktop()->availableGeometry())); + + splash->show(); + + float splash_transparency = 0; + QTime splash_fade_timer; + splash_fade_timer.start(); + + while (splash_transparency < 1) { + + splash_transparency = (float)splash_fade_timer.elapsed() / 500;//1000; + if (splash_transparency > 1) splash_transparency = 1; + splash->setWindowOpacity(splash_transparency); + splash->repaint(); + } + + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": Loading settings .."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + SleeperThread::msleep(500); + + Settings::instance()->setSettingsFilename(QCoreApplication::applicationDirPath() + + "/" + Settings::instance()->getSettingsFilename()); + + Settings::instance()->setSettingsLoaded(Settings::instance()->loadSettings() >= 0); + + if (Settings::instance()->getSettingsLoaded()) { + + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": Settings loaded."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + SleeperThread::msleep(100); + } + else { + + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": Settings not loaded."), + Qt::AlignTop | Qt::AlignLeft, Qt::red); + + //splash->showMessage("\n " + QObject::tr(copyright), Qt::AlignBottom | Qt::AlignLeft, Qt::black); + } + + // **************************** + // check for OpenGL + + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": Checking for OpenGL V 2.0 ..."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + SleeperThread::msleep(100); + + if (!QGLFormat::hasOpenGL() && QGLFormat::OpenGL_Version_2_0) { + + qDebug() << "Init::\tOpenGL not found!"; + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": not found!"), + Qt::AlignTop | Qt::AlignLeft, Qt::red); + + splash->hide(); + + QMessageBox::critical(0, + QApplication::applicationName(), + QApplication::applicationName() + " requires OpenGL v2.0 or later to run.", + QMessageBox::Abort); + + return -1; + } + + if (!(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)) { + + qDebug() << "Init::\tOpenGL found, but appears to be less than OGL v2.0."; + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": found but appears to be less than OGL v2.0"), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + splash->hide(); + + QMessageBox::critical(0, + QApplication::applicationName(), + QApplication::applicationName() + " requires OpenGL v2.0 or later to run.", + QMessageBox::Ok); + + return -1; + } + //if (QGLFormat::OpenGL_Version_2_0) + // qDebug() << "OpenGL version > 2.0"; + + qDebug() << "Init::\tOpenGL found."; + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": OpenGL found."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + SleeperThread::msleep(100); + + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) { + + qDebug() << "Init::Framebuffer Objects not found!\n"; + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": fbuffers not found!"), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + Settings::instance()->setFBOPresence(false); + SleeperThread::msleep(100); + return -1; + //splash->hide(); + } + else { + + qDebug() << "Init::\tFramebuffer Objects found."; + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": OpenGL Frame Buffer support found."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + Settings::instance()->setFBOPresence(true); + } + SleeperThread::msleep(100); + + // **************************** + + // cpu usage +#if defined(Q_OS_WIN32) + CreateThread(NULL, 0, WatchItThreadProc, NULL, 0, NULL); +#endif + + // **************************** + // setup main window + + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": setting up main window .."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + qDebug() << "Init::\tmain window setup ..."; + MainWindow mainWindow; + mainWindow.setup(); + qDebug() << "Init::\tmain window setup done."; + + splash->showMessage( + "\n " + + Settings::instance()->getTitleStr() + " " + + Settings::instance()->getVersionStr() + + QObject::tr(": Displaying main window .."), + Qt::AlignTop | Qt::AlignLeft, Qt::yellow); + + SleeperThread::msleep(300); + + //app.processEvents(); + + mainWindow.show(); + app.processEvents(); + + /*splash_fade_timer.restart(); + while (splash_transparency > 0) + { + splash_transparency = 1 - (float)splash_fade_timer.elapsed() / 300; + if (splash_transparency < 0) splash_transparency = 0; + if (splash_transparency > 1) splash_transparency = 1; + splash->setWindowOpacity(splash_transparency); + splash->repaint(); + }*/ + splash->hide(); + + delete splash; + + mainWindow.update(); + mainWindow.setFocus(); + +#if defined(Q_OS_LINUX) + cusdr_cpuUsage *cpu_load = new cusdr_cpuUsage(); + cpu_load->start(); +#endif + + qDebug() << "Init::\trunning application ...\n"; + + return app.exec(); +}